Compare commits

..

1 Commits

Author SHA1 Message Date
Muhammad Faraz Maqsood
f16ccfe9cf fix: use hyperlink instead of Link 2025-04-21 11:10:42 +05:00
1070 changed files with 33576 additions and 33567 deletions

7
.env
View File

@@ -41,10 +41,9 @@ HOTJAR_APP_ID=''
HOTJAR_VERSION=6
HOTJAR_DEBUG=false
INVITE_STUDENTS_EMAIL_TO=''
ENABLE_HOME_PAGE_COURSE_API_V2=true
ENABLE_CHECKLIST_QUALITY=''
ENABLE_GRADING_METHOD_IN_PROBLEMS=false
# "Multi-level" blocks are unsupported in libraries
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder"
# Fallback in local style files
PARAGON_THEME_URLS={}
COURSE_TEAM_SUPPORT_EMAIL=''
# TODO: Missing support for ORA2
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder,openassessment"

View File

@@ -44,10 +44,8 @@ HOTJAR_APP_ID=''
HOTJAR_VERSION=6
HOTJAR_DEBUG=true
INVITE_STUDENTS_EMAIL_TO="someone@domain.com"
ENABLE_HOME_PAGE_COURSE_API_V2=true
ENABLE_CHECKLIST_QUALITY=true
ENABLE_GRADING_METHOD_IN_PROBLEMS=false
# "Multi-level" blocks are unsupported in libraries
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder"
# Fallback in local style files
PARAGON_THEME_URLS={}
COURSE_TEAM_SUPPORT_EMAIL=''

View File

@@ -40,6 +40,5 @@ ENABLE_HOME_PAGE_COURSE_API_V2=true
ENABLE_CHECKLIST_QUALITY=true
ENABLE_GRADING_METHOD_IN_PROBLEMS=false
# "Multi-level" blocks are unsupported in libraries
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder"
PARAGON_THEME_URLS=
COURSE_TEAM_SUPPORT_EMAIL='support@example.com'
# TODO: Missing support for ORA2
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder,openassessment"

View File

@@ -2,37 +2,26 @@
Describe what this pull request changes, and why. Include implications for people using this change.
Design decisions and their rationales should be documented in the repo (docstring / ADR), per
[OEP-19](https://open-edx-proposals.readthedocs.io/en/latest/oep-0019-bp-developer-documentation.html), and can be linked here.
Useful information to include:
- Which user roles will this change impact? Common user roles are "Learner", "Course Author",
- Which edX user roles will this change impact? Common user roles are "Learner", "Course Author",
"Developer", and "Operator".
- Include screenshots for changes to the UI (ideally, both "before" and "after" screenshots, if applicable).
- Provide links to the description of corresponding configuration changes. Remember to correctly annotate these
changes.
## Supporting information
Link to other information about the change, such as GitHub issues, or Discourse discussions.
Link to other information about the change, such as Jira issues, GitHub issues, or Discourse discussions.
Be sure to check they are publicly readable, or if not, repeat the information here.
## Testing instructions
Please provide detailed step-by-step instructions for manually testing this change.
Please provide detailed step-by-step instructions for testing this change.
## Other information
Include anything else that will help reviewers and consumers understand the change.
- Does this change depend on other changes elsewhere?
- Any special concerns or limitations? For example: deprecations, migrations, security, or accessibility.
## Best Practices Checklist
We're trying to move away from some deprecated patterns in this codebase. Please
check if your PR meets these recommendations before asking for a review:
- [ ] Any _new_ files are using TypeScript (`.ts`, `.tsx`).
- [ ] Deprecated `propTypes`, `defaultProps`, and `injectIntl` patterns are not used in any new or modified code.
- [ ] Tests should use the helpers in `src/testUtils.tsx` (specifically `initializeMocks`)
- [ ] Do not add new fields to the Redux state/store. Use React Context to share state among multiple components.
- [ ] Use React Query to load data from REST APIs. See any `apiHooks.ts` in this repo for examples.
- [ ] All new i18n messages in `messages.ts` files have a `description` for translators to use.
- [ ] Imports avoid using `../`. To import from parent folders, use `@src`, e.g. `import { initializeMocks } from '@src/testUtils';` instead of `from '../../../../testUtils'`
- Any special concerns or limitations? For example: deprecations, migrations, security, or accessibility.

View File

@@ -1,18 +0,0 @@
# Run the workflow that adds new tickets that are labelled "release testing"
# to the org-wide BTR project board
name: Add release testing issues to the BTR project board
on:
issues:
types: [labeled]
# This workflow is triggered when an issue is labeled with 'release testing'.
# It adds the issue to the BTR project and applies the 'needs triage' label
# if it doesn't already have it.
jobs:
handle-release-testing:
uses: openedx/.github/.github/workflows/add-issue-to-btr-project.yml@master
secrets:
GITHUB_APP_ID: ${{ secrets.GRAPHQL_AUTH_APP_ID }}
GITHUB_APP_PRIVATE_KEY: ${{ secrets.GRAPHQL_AUTH_APP_PEM }}

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
@@ -25,13 +25,13 @@ jobs:
runs-on: ubuntu-latest
needs: tests
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Download code coverage results
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: code-coverage-report
- name: Upload coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}

2
CODEOWNERS Normal file
View File

@@ -0,0 +1,2 @@
# The following users are the maintainers of all frontend-app-authoring files
* @openedx/2u-tnl

View File

@@ -165,7 +165,21 @@ Feature: New React XBlock Editors
.. image:: ./docs/readme-images/feature-problem-editor.png
New React editors for the HTML, Video, and Problem XBlocks are provided here and are rendered by this MFE instead of by the XBlock's authoring view.
This allows an operator to enable the use of new React editors for the HTML, Video, and Problem XBlocks, all of which are provided here.
Requirements
------------
* ``edx-platform`` Waffle flags:
* ``new_core_editors.use_new_text_editor``: must be enabled for the new HTML Xblock editor to be used in Studio
* ``new_core_editors.use_new_video_editor``: must be enabled for the new Video Xblock editor to be used in Studio
* ``new_core_editors.use_new_problem_editor``: must be enabled for the new Problem Xblock editor to be used in Studio
Feature Description
-------------------
When a corresponding waffle flag is set, upon editing a block in Studio, the view is rendered by this MFE instead of by the XBlock's authoring view. The user remains in Studio.
Feature: New Proctoring Exams View
==================================
@@ -179,6 +193,10 @@ Requirements
* ``ZENDESK_*``: necessary if automatic ZenDesk ticket creation is desired
* ``edx-platform`` Feature flags:
* ``ENABLE_EXAM_SETTINGS_HTML_VIEW``: this feature flag must be enabled for the link to the settings view to be shown
* `edx-exams <https://github.com/edx/edx-exams>`_: for this feature to work, the ``edx-exams`` IDA must be deployed and its API accessible by the browser
Configuration
@@ -203,6 +221,16 @@ Feature: Advanced Settings
.. image:: ./docs/readme-images/feature-advanced-settings.png
Requirements
------------
* ``edx-platform`` Waffle flags:
* ``contentstore.new_studio_mfe.use_new_advanced_settings_page``: this feature flag must be enabled for the link to the settings view to be shown. It can be enabled on a per-course basis.
Feature Description
-------------------
In Studio, the "Advanced Settings" page for each enabled course will now be served by this frontend, instead of the UI built into edx-platform. The advanced settings page holds many different settings for the course, such as what features or XBlocks are enabled.
Feature: Files & Uploads
@@ -210,6 +238,16 @@ Feature: Files & Uploads
.. image:: ./docs/readme-images/feature-files-uploads.png
Requirements
------------
* ``edx-platform`` Waffle flags:
* ``contentstore.new_studio_mfe.use_new_files_uploads_page``: this feature flag must be enabled for the link to the Files & Uploads page to go to the MFE. It can be enabled on a per-course basis.
Feature Description
-------------------
In Studio, the "Files & Uploads" page for each enabled course will now be served by this frontend, instead of the UI built into edx-platform. This page allows managing static asset files like PDFs, images, etc. used for the course.
Feature: Course Updates
@@ -217,11 +255,26 @@ Feature: Course Updates
.. image:: ./docs/readme-images/feature-course-updates.png
Requirements
------------
* ``edx-platform`` Waffle flags:
* ``contentstore.new_studio_mfe.use_new_updates_page``: this feature flag must be enabled.
Feature: Import/Export Pages
============================
.. image:: ./docs/readme-images/feature-export.png
Requirements
------------
* ``edx-platform`` Waffle flags:
* ``contentstore.new_studio_mfe.use_new_export_page``: this feature flag will change the CMS to link to the new export page.
* ``contentstore.new_studio_mfe.use_new_import_page``: this feature flag will change the CMS to link to the new import page.
Feature: Tagging/Taxonomy Pages
================================
@@ -327,20 +380,6 @@ For more information about these options, see the `Getting Help`_ page.
.. _Getting Help: https://openedx.org/community/connect
Legacy Studio
*************
If you would like to use legacy studio for certain features, you can set the following waffle flags in ``edx-platform``:
* ``legacy_studio.text_editor``: loads the legacy HTML Xblock editor when editing a text block
* ``legacy_studio.video_editor``: loads the legacy Video editor when editing a video block
* ``legacy_studio.problem_editor``: loads the legacy Problem editor when editing a problem block
* ``legacy_studio.advanced_settings``: Advanced Settings page
* ``legacy_studio.updates``: Updates page
* ``legacy_studio.export``: Export page
* ``legacy_studio.import``: Import page
* ``legacy_studio.files_uploads``: Files page
* ``legacy_studio.exam_settings``: loads the legacy Exam Settings
License
*******

View File

@@ -14,6 +14,6 @@ metadata:
openedx.org/arch-interest-groups: ""
openedx.org/release: "master"
spec:
owner: user:bradenmacdonald
owner: group:2u-tnl
type: 'website'
lifecycle: 'production'

View File

@@ -10,5 +10,4 @@ coverage:
threshold: 0%
ignore:
- "src/grading-settings/grading-scale/react-ranger.js"
- "src/generic/DraggableList/verticalSortableList.ts"
- "src/index.js"

View File

@@ -11,11 +11,9 @@ module.exports = createConfig('jest', {
],
moduleNameMapper: {
'^lodash-es$': 'lodash',
// This alias is for any code in the src directory that wants to avoid '../../' style relative imports:
'^@src/(.*)$': '<rootDir>/src/$1',
// This alias is used for plugins in the plugins/ folder only.
'^CourseAuthoring/(.*)$': '<rootDir>/src/$1',
},
modulePathIgnorePatterns: [
'/src/pages-and-resources/utils.test.jsx',
],
});

4843
package-lock.json generated
View File

@@ -10,7 +10,6 @@
"license": "AGPL-3.0",
"dependencies": {
"@codemirror/lang-html": "^6.0.0",
"@codemirror/lang-markdown": "^6.0.0",
"@codemirror/lang-xml": "^6.0.0",
"@codemirror/lint": "^6.2.1",
"@codemirror/state": "^6.0.0",
@@ -20,12 +19,12 @@
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.3",
"@edx/browserslist-config": "1.5.0",
"@edx/frontend-component-footer": "^14.9.0",
"@edx/browserslist-config": "1.2.0",
"@edx/frontend-component-footer": "^14.3.0",
"@edx/frontend-component-header": "^6.2.0",
"@edx/frontend-enterprise-hotjar": "^7.2.0",
"@edx/frontend-platform": "^8.4.0",
"@edx/openedx-atlas": "^0.7.0",
"@edx/frontend-platform": "^8.3.1",
"@edx/openedx-atlas": "^0.6.0",
"@openedx-plugins/course-app-calculator": "file:plugins/course-apps/calculator",
"@openedx-plugins/course-app-edxnotes": "file:plugins/course-apps/edxnotes",
"@openedx-plugins/course-app-learning_assistant": "file:plugins/course-apps/learning_assistant",
@@ -36,12 +35,13 @@
"@openedx-plugins/course-app-teams": "file:plugins/course-apps/teams",
"@openedx-plugins/course-app-wiki": "file:plugins/course-apps/wiki",
"@openedx-plugins/course-app-xpert_unit_summary": "file:plugins/course-apps/xpert_unit_summary",
"@openedx/frontend-build": "^14.5.0",
"@openedx/frontend-plugin-framework": "^1.7.0",
"@openedx/paragon": "^23.5.0",
"@openedx/frontend-build": "^14.3.3",
"@openedx/frontend-plugin-framework": "^1.6.0",
"@openedx/frontend-slot-footer": "^1.2.0",
"@openedx/paragon": "^22.16.0",
"@redux-devtools/extension": "^3.3.0",
"@reduxjs/toolkit": "1.9.7",
"@tanstack/react-query": "4.40.1",
"@tanstack/react-query": "4.36.1",
"@tinymce/tinymce-react": "^3.14.0",
"classnames": "2.5.1",
"codemirror": "^6.0.0",
@@ -55,6 +55,7 @@
"meilisearch": "^0.41.0",
"moment": "2.30.1",
"moment-shortformat": "^2.1.0",
"npm": "^10.8.1",
"prop-types": "^15.8.1",
"react": "^18.3.1",
"react-datepicker": "^4.13.0",
@@ -64,31 +65,31 @@
"react-onclickoutside": "^6.13.0",
"react-redux": "7.2.9",
"react-responsive": "9.0.2",
"react-router": "6.30.1",
"react-router-dom": "6.30.1",
"react-select": "5.10.2",
"react-router": "6.27.0",
"react-router-dom": "6.27.0",
"react-select": "5.8.0",
"react-textarea-autosize": "^8.5.3",
"react-transition-group": "4.4.5",
"redux": "4.2.1",
"redux": "4.0.5",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.4.1",
"reselect": "^4.1.5",
"start": "^5.1.0",
"tinymce": "^5.10.4",
"universal-cookie": "^4.0.4",
"uuid": "^11.1.0",
"uuid": "^3.4.0",
"xmlchecker": "^0.1.0",
"yup": "0.32.11"
"yup": "0.31.1"
},
"devDependencies": {
"@edx/react-unit-test-utils": "^4.0.0",
"@edx/stylelint-config-edx": "2.3.3",
"@edx/typescript-config": "^1.0.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.1",
"@types/lodash": "^4.17.17",
"@types/react": "^18",
"@types/react-dom": "^18",
"axios-mock-adapter": "2.1.0",
"@testing-library/user-event": "^13.2.1",
"@types/lodash": "^4.17.7",
"axios-mock-adapter": "1.22.0",
"eslint-import-resolver-webpack": "^0.13.8",
"fetch-mock-jest": "^1.5.1",
"jest-canvas-mock": "^2.5.2",
@@ -147,14 +148,14 @@
}
},
"node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
"integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"license": "MIT",
"dependencies": {
"@babel/helper-validator-identifier": "^7.27.1",
"@babel/helper-validator-identifier": "^7.25.9",
"js-tokens": "^4.0.0",
"picocolors": "^1.1.1"
"picocolors": "^1.0.0"
},
"engines": {
"node": ">=6.9.0"
@@ -436,9 +437,9 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -1963,215 +1964,6 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
"license": "MIT"
},
"node_modules/@bundled-es-modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/@bundled-es-modules/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-Rk453EklPUPC3NRWc3VUNI/SSUjdBaFoaQvFRmNBNtMHVtOFD5AntiWg5kEE1hqcPqedYFDzxE3ZcMYPcA195w==",
"license": "ISC",
"dependencies": {
"deepmerge": "^4.3.1"
}
},
"node_modules/@bundled-es-modules/glob": {
"version": "10.4.2",
"resolved": "https://registry.npmjs.org/@bundled-es-modules/glob/-/glob-10.4.2.tgz",
"integrity": "sha512-740y5ofkzydsFao5EXJrGilcIL6EFEw/cmPf2uhTw9J6G1YOhiIFjNFCHdpgEiiH5VlU3G0SARSjlFlimRRSMA==",
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
"buffer": "^6.0.3",
"events": "^3.3.0",
"glob": "^10.4.2",
"patch-package": "^8.0.0",
"path": "^0.12.7",
"stream": "^0.0.3",
"string_decoder": "^1.3.0",
"url": "^0.11.3"
}
},
"node_modules/@bundled-es-modules/glob/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@bundled-es-modules/glob/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"
}
],
"license": "MIT",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/@bundled-es-modules/glob/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@bundled-es-modules/glob/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@bundled-es-modules/glob/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==",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/@bundled-es-modules/memfs": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/@bundled-es-modules/memfs/-/memfs-4.17.0.tgz",
"integrity": "sha512-ykdrkEmQr9BV804yd37ikXfNnvxrwYfY9Z2/EtMHFEFadEjsQXJ1zL9bVZrKNLDtm91UdUOEHso6Aweg93K6xQ==",
"license": "Apache-2.0",
"dependencies": {
"assert": "^2.1.0",
"buffer": "^6.0.3",
"events": "^3.3.0",
"memfs": "^4.17.0",
"path": "^0.12.7",
"stream": "^0.0.3",
"util": "^0.12.5"
}
},
"node_modules/@bundled-es-modules/memfs/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"
}
],
"license": "MIT",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/@bundled-es-modules/memfs/node_modules/memfs": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-4.17.0.tgz",
"integrity": "sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg==",
"license": "Apache-2.0",
"dependencies": {
"@jsonjoy.com/json-pack": "^1.0.3",
"@jsonjoy.com/util": "^1.3.0",
"tree-dump": "^1.0.1",
"tslib": "^2.0.0"
},
"engines": {
"node": ">= 4.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/streamich"
}
},
"node_modules/@bundled-es-modules/postcss-calc-ast-parser": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@bundled-es-modules/postcss-calc-ast-parser/-/postcss-calc-ast-parser-0.1.6.tgz",
"integrity": "sha512-y65TM5zF+uaxo9OeekJ3rxwTINlQvrkbZLogYvQYVoLtxm4xEiHfZ7e/MyiWbStYyWZVZkVqsaVU6F4SUK5XUA==",
"license": "ISC",
"dependencies": {
"postcss-calc-ast-parser": "^0.1.4"
}
},
"node_modules/@chevrotain/cst-dts-gen": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz",
"integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==",
"license": "Apache-2.0",
"dependencies": {
"@chevrotain/gast": "11.0.3",
"@chevrotain/types": "11.0.3",
"lodash-es": "4.17.21"
}
},
"node_modules/@chevrotain/gast": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz",
"integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==",
"license": "Apache-2.0",
"dependencies": {
"@chevrotain/types": "11.0.3",
"lodash-es": "4.17.21"
}
},
"node_modules/@chevrotain/regexp-to-ast": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz",
"integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==",
"license": "Apache-2.0"
},
"node_modules/@chevrotain/types": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz",
"integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==",
"license": "Apache-2.0"
},
"node_modules/@chevrotain/utils": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz",
"integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==",
"license": "Apache-2.0"
},
"node_modules/@codemirror/autocomplete": {
"version": "6.18.6",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz",
@@ -2185,9 +1977,9 @@
}
},
"node_modules/@codemirror/commands": {
"version": "6.8.1",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz",
"integrity": "sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==",
"version": "6.8.0",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.0.tgz",
"integrity": "sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ==",
"license": "MIT",
"dependencies": {
"@codemirror/language": "^6.0.0",
@@ -2241,21 +2033,6 @@
"@lezer/javascript": "^1.0.0"
}
},
"node_modules/@codemirror/lang-markdown": {
"version": "6.3.4",
"resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.3.4.tgz",
"integrity": "sha512-fBm0BO03azXnTAsxhONDYHi/qWSI+uSEIpzKM7h/bkIc9fHnFp9y7KTMXKON0teNT97pFhc1a9DQTtWBYEZ7ug==",
"license": "MIT",
"dependencies": {
"@codemirror/autocomplete": "^6.7.1",
"@codemirror/lang-html": "^6.0.0",
"@codemirror/language": "^6.3.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.2.1",
"@lezer/markdown": "^1.0.0"
}
},
"node_modules/@codemirror/lang-xml": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz",
@@ -2316,13 +2093,12 @@
}
},
"node_modules/@codemirror/view": {
"version": "6.38.1",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.1.tgz",
"integrity": "sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ==",
"version": "6.36.4",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.4.tgz",
"integrity": "sha512-ZQ0V5ovw/miKEXTvjgzRyjnrk9TwriUB1k4R5p7uNnHR9Hus+D1SXHGdJshijEzPFjU25xea/7nhIeSqYFKdbA==",
"license": "MIT",
"dependencies": {
"@codemirror/state": "^6.5.0",
"crelt": "^1.0.6",
"style-mod": "^4.1.0",
"w3c-keyname": "^2.2.4"
}
@@ -2530,9 +2306,9 @@
"license": "GPL-3.0-or-later"
},
"node_modules/@edx/browserslist-config": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@edx/browserslist-config/-/browserslist-config-1.5.0.tgz",
"integrity": "sha512-d2ggwi5j4DOBJOwhWZxBWQSDR0DhT4ke/1PbzRauICdFkuOyax+PsFjK8GUh443K2OaQpy9PGfiCzZ1Yg37AUA==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@edx/browserslist-config/-/browserslist-config-1.2.0.tgz",
"integrity": "sha512-T1+6P52Yx7SMkmoIr4O0Q3m/DyRdrLTJbv1xVijdRLFEq1hqdafEs+Ln1423U5LSkTePb9AOkEtL1G0RZLFl1w==",
"license": "AGPL-3.0"
},
"node_modules/@edx/eslint-config": {
@@ -2553,9 +2329,9 @@
}
},
"node_modules/@edx/frontend-component-footer": {
"version": "14.9.0",
"resolved": "https://registry.npmjs.org/@edx/frontend-component-footer/-/frontend-component-footer-14.9.0.tgz",
"integrity": "sha512-eI3ffSvAKDoP1K/vBuQrCL7ca0U7hJqRlGjBq62dSAlsgOS59t+9T1ZkIWCSoRUzHLv4fS+taiBeCsIQVV356Q==",
"version": "14.3.0",
"resolved": "https://registry.npmjs.org/@edx/frontend-component-footer/-/frontend-component-footer-14.3.0.tgz",
"integrity": "sha512-domQOIsAf+b1YiQvpt245Cfz6OgrKKw3TJrDIFS+J70Mn98MpCGGg55mBraOzTfopsouzp5bN03F1PLkXyjnEQ==",
"license": "AGPL-3.0",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "6.7.2",
@@ -2563,7 +2339,6 @@
"@fortawesome/free-regular-svg-icons": "6.7.2",
"@fortawesome/free-solid-svg-icons": "6.7.2",
"@fortawesome/react-fontawesome": "0.2.2",
"@openedx/frontend-plugin-framework": "^1.7.0",
"classnames": "^2.5.1",
"jest-environment-jsdom": "^29.7.0",
"lodash": "^4.17.21",
@@ -2578,18 +2353,21 @@
}
},
"node_modules/@edx/frontend-component-header": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/@edx/frontend-component-header/-/frontend-component-header-6.6.0.tgz",
"integrity": "sha512-Qp4f0ZaKmwYdEXcjr24zePbN9oEdVFPuamxA4nH6dUGVi2whwX+US80yVJ1abQs3BX23zPpzYnqyc6/UhOqhLw==",
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/@edx/frontend-component-header/-/frontend-component-header-6.2.0.tgz",
"integrity": "sha512-rM/+NtvPAQk+RmAA/fhXnsneeta/CGi319Wei/or6aW7ETpSmMkfoYM4MKv+JPhF/vLMxqBzz6lwzefF9D62Lw==",
"license": "AGPL-3.0",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "6.7.2",
"@fortawesome/free-brands-svg-icons": "6.7.2",
"@fortawesome/free-regular-svg-icons": "6.7.2",
"@fortawesome/free-solid-svg-icons": "6.7.2",
"@fortawesome/fontawesome-svg-core": "6.6.0",
"@fortawesome/free-brands-svg-icons": "6.6.0",
"@fortawesome/free-regular-svg-icons": "6.6.0",
"@fortawesome/free-solid-svg-icons": "6.6.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@openedx/frontend-plugin-framework": "^1.7.0",
"@openedx/frontend-plugin-framework": "^1.6.0",
"axios-mock-adapter": "1.22.0",
"babel-polyfill": "6.26.0",
"classnames": "^2.5.1",
"jest-environment-jsdom": "^29.7.0",
"react-responsive": "8.2.0",
"react-transition-group": "4.4.5"
},
@@ -2602,6 +2380,63 @@
"react-router-dom": "^6.14.2"
}
},
"node_modules/@edx/frontend-component-header/node_modules/@fortawesome/fontawesome-common-types": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.6.0.tgz",
"integrity": "sha512-xyX0X9mc0kyz9plIyryrRbl7ngsA9jz77mCZJsUkLl+ZKs0KWObgaEBoSgQiYWAsSmjz/yjl0F++Got0Mdp4Rw==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/@edx/frontend-component-header/node_modules/@fortawesome/fontawesome-svg-core": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.6.0.tgz",
"integrity": "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg==",
"license": "MIT",
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.6.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-brands-svg-icons": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.6.0.tgz",
"integrity": "sha512-1MPD8lMNW/earme4OQi1IFHtmHUwAKgghXlNwWi9GO7QkTfD+IIaYpIai4m2YJEzqfEji3jFHX1DZI5pbY/biQ==",
"license": "(CC-BY-4.0 AND MIT)",
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.6.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-regular-svg-icons": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.6.0.tgz",
"integrity": "sha512-Yv9hDzL4aI73BEwSEh20clrY8q/uLxawaQ98lekBx6t9dQKDHcDzzV1p2YtBGTtolYtNqcWdniOnhzB+JPnQEQ==",
"license": "(CC-BY-4.0 AND MIT)",
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.6.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@edx/frontend-component-header/node_modules/@fortawesome/free-solid-svg-icons": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.6.0.tgz",
"integrity": "sha512-IYv/2skhEDFc2WGUcqvFJkeK39Q+HyPf5GHUrT/l2pKbtgEIv1al1TKd6qStR5OIwQdN1GZP54ci3y4mroJWjA==",
"license": "(CC-BY-4.0 AND MIT)",
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.6.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@edx/frontend-component-header/node_modules/react-responsive": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-8.2.0.tgz",
@@ -2632,16 +2467,16 @@
}
},
"node_modules/@edx/frontend-platform": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/@edx/frontend-platform/-/frontend-platform-8.5.0.tgz",
"integrity": "sha512-nzz46Pe0G1mFHoywzOWPhwy2m26CmD3o11FubeU8F94VsKfJsAexTETyWHRvwuVhQs6qaFzgobAjjEl8w0mu6A==",
"version": "8.3.3",
"resolved": "https://registry.npmjs.org/@edx/frontend-platform/-/frontend-platform-8.3.3.tgz",
"integrity": "sha512-xj8uKY4k9DgScYWsBFx8B1cngZ6HTPHvmd7W+NpBB4Kqw9yCT1OUii4p8/8khF68vb7hcTQuu13A9hM0lkE5bw==",
"license": "AGPL-3.0",
"dependencies": {
"@cospired/i18n-iso-languages": "4.2.0",
"@formatjs/intl-pluralrules": "4.3.3",
"@formatjs/intl-relativetimeformat": "10.0.1",
"axios": "1.9.0",
"axios-cache-interceptor": "1.8.0",
"axios": "1.8.4",
"axios-cache-interceptor": "1.6.2",
"form-urlencoded": "4.1.4",
"glob": "7.2.3",
"history": "4.10.1",
@@ -2670,12 +2505,6 @@
"react-redux": "^7.1.1 || ^8.1.1",
"react-router-dom": "^6.0.0",
"redux": "^4.0.4"
},
"peerDependenciesMeta": {
"@openedx/frontend-build": {
"optional": true,
"reason": "This package is only a peer dependency to ensure using a minimum compatible version that provides env.config and PARAGON_THEME support. It is not needed at runtime, and may be omitted with `--omit=optional`."
}
}
},
"node_modules/@edx/new-relic-source-map-webpack-plugin": {
@@ -2688,14 +2517,39 @@
}
},
"node_modules/@edx/openedx-atlas": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@edx/openedx-atlas/-/openedx-atlas-0.7.0.tgz",
"integrity": "sha512-jqv0IV1pHsSn9+RO8Rdsr8jm3SOd84CCzzmo2QC9yvh1MK1+p4YDURQLpmmgKJ0JzE5Cb6ImhnNL/ogpJ2wetQ==",
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/@edx/openedx-atlas/-/openedx-atlas-0.6.2.tgz",
"integrity": "sha512-28Q8vzJDMS4wUxdkbIUBQpzWJ3HTdMaGlaEhFjrVGfuZkh++1AG6Tn/7FMD88cegalYAkphu530VQCHEkMZQhw==",
"license": "AGPL-3.0",
"bin": {
"atlas": "atlas"
}
},
"node_modules/@edx/react-unit-test-utils": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@edx/react-unit-test-utils/-/react-unit-test-utils-4.0.0.tgz",
"integrity": "sha512-QlVYhYD9L2bzx1eAtf8BbCJr00ek9rrHrG+/pW2bVSt+t0uvKHQpX1CNdMrDePv18DsMeC7IOB00t8ZIn4mi7w==",
"dev": true,
"license": "AGPL-3.0",
"dependencies": {
"@edx/browserslist-config": "^1.1.1",
"@reduxjs/toolkit": "^1.5.1",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"classnames": "^2.2.6",
"core-js": "3.6.5",
"lodash": "^4.17.21",
"react-dev-utils": "^12.0.1",
"react-test-renderer": "^18.3.1"
},
"peerDependencies": {
"@edx/frontend-platform": "^8.3.1",
"@openedx/frontend-build": "^14.3.0",
"@openedx/paragon": "^22.0.0 || ^23.0.0",
"react": "^18.0.0"
}
},
"node_modules/@edx/stylelint-config-edx": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@edx/stylelint-config-edx/-/stylelint-config-edx-2.3.3.tgz",
@@ -2719,20 +2573,20 @@
}
},
"node_modules/@emnapi/core": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz",
"integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.3.1.tgz",
"integrity": "sha512-pVGjBIt1Y6gg3EJN8jTcfpP/+uuRksIo055oE/OBkDNcjZqVbfkWCksG1Jp4yZnj3iKWyWX8fdG/j6UDYPbFog==",
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/wasi-threads": "1.0.2",
"@emnapi/wasi-threads": "1.0.1",
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/runtime": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz",
"integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz",
"integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -2740,9 +2594,9 @@
}
},
"node_modules/@emnapi/wasi-threads": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz",
"integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz",
"integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -2879,9 +2733,9 @@
"license": "MIT"
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz",
"integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==",
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz",
"integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==",
"license": "MIT",
"dependencies": {
"eslint-visitor-keys": "^3.4.3"
@@ -3020,9 +2874,9 @@
"license": "MIT"
},
"node_modules/@formatjs/cli": {
"version": "6.6.4",
"resolved": "https://registry.npmjs.org/@formatjs/cli/-/cli-6.6.4.tgz",
"integrity": "sha512-VSDPsT7AO/mtth1rEBwl97Us5dMgqZpI8v7QJXakB4f90pDJsqHBdBeTbjHYrlFr2WvBLVo3/6mGPw9DeX7PUg==",
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/@formatjs/cli/-/cli-6.6.3.tgz",
"integrity": "sha512-vW9EQdHmxQg/+s9K39ZwKcIyyhmEMHOtsv1KyQFtjv+pbE3XmiB5ohoo4wAx3HDsrufrTsplGnQdQ+KB2wY/bA==",
"license": "MIT",
"bin": {
"formatjs": "bin/formatjs"
@@ -3348,9 +3202,9 @@
}
},
"node_modules/@formatjs/ts-transformer/node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"version": "5.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
@@ -3477,102 +3331,6 @@
"deprecated": "Use @eslint/object-schema instead",
"license": "BSD-3-Clause"
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"license": "ISC",
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/@isaacs/cliui/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==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/@isaacs/cliui/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==",
"license": "MIT"
},
"node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@isaacs/cliui/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==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"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",
@@ -4048,60 +3806,6 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@jsonjoy.com/base64": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz",
"integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==",
"license": "Apache-2.0",
"engines": {
"node": ">=10.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/streamich"
},
"peerDependencies": {
"tslib": "2"
}
},
"node_modules/@jsonjoy.com/json-pack": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.2.0.tgz",
"integrity": "sha512-io1zEbbYcElht3tdlqEOFxZ0dMTYrHz9iMf0gqn1pPjZFTCgM5R4R5IMA20Chb2UPYYsxjzs8CgZ7Nb5n2K2rA==",
"license": "Apache-2.0",
"dependencies": {
"@jsonjoy.com/base64": "^1.1.1",
"@jsonjoy.com/util": "^1.1.2",
"hyperdyperid": "^1.2.0",
"thingies": "^1.20.0"
},
"engines": {
"node": ">=10.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/streamich"
},
"peerDependencies": {
"tslib": "2"
}
},
"node_modules/@jsonjoy.com/util": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.5.0.tgz",
"integrity": "sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==",
"license": "Apache-2.0",
"engines": {
"node": ">=10.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/streamich"
},
"peerDependencies": {
"tslib": "2"
}
},
"node_modules/@leichtgewicht/ip-codec": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
@@ -4146,9 +3850,9 @@
}
},
"node_modules/@lezer/javascript": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.1.tgz",
"integrity": "sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw==",
"version": "1.4.21",
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.21.tgz",
"integrity": "sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==",
"license": "MIT",
"dependencies": {
"@lezer/common": "^1.2.0",
@@ -4165,16 +3869,6 @@
"@lezer/common": "^1.0.0"
}
},
"node_modules/@lezer/markdown": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.4.3.tgz",
"integrity": "sha512-kfw+2uMrQ/wy/+ONfrH83OkdFNM0ye5Xq96cLlaCy7h5UT9FO54DU4oRoIc0CSBh5NWmWuiIJA7NGLMJbQ+Oxg==",
"license": "MIT",
"dependencies": {
"@lezer/common": "^1.0.0",
"@lezer/highlight": "^1.0.0"
}
},
"node_modules/@lezer/xml": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz",
@@ -4193,21 +3887,21 @@
"license": "MIT"
},
"node_modules/@napi-rs/wasm-runtime": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.9.tgz",
"integrity": "sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==",
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.7.tgz",
"integrity": "sha512-5yximcFK5FNompXfJFoWanu5l8v1hNGqNHh9du1xETp9HWk/B/PzvchX55WYOPaIeNglG8++68AAiauBAtbnzw==",
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/core": "^1.4.0",
"@emnapi/runtime": "^1.4.0",
"@emnapi/core": "^1.3.1",
"@emnapi/runtime": "^1.3.1",
"@tybys/wasm-util": "^0.9.0"
}
},
"node_modules/@newrelic/publish-sourcemap": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/@newrelic/publish-sourcemap/-/publish-sourcemap-5.1.4.tgz",
"integrity": "sha512-35Nm26FxnVi7Nrfrl7nMHObIrHlkCStIPul/fQnru7RBlZIZiYKeGA9eEKBuho1ccoFK783w12nuntSV6wohlg==",
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/@newrelic/publish-sourcemap/-/publish-sourcemap-5.1.3.tgz",
"integrity": "sha512-CuHiYXRVU4kDJ4D0nZYVRlRKb8V+s8MFpIyA2D5UBNCOntf/8jv+rxJR1wJ8WYkTio7f+uBKXn/K4GzrhWvKUw==",
"license": "New Relic proprietary",
"dependencies": {
"superagent": "^10.1.0",
@@ -4235,18 +3929,6 @@
"eslint-scope": "5.1.1"
}
},
"node_modules/@noble/hashes": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
"integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
"license": "MIT",
"engines": {
"node": "^14.21.3 || >=16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -4323,9 +4005,9 @@
"link": true
},
"node_modules/@openedx/frontend-build": {
"version": "14.6.1",
"resolved": "https://registry.npmjs.org/@openedx/frontend-build/-/frontend-build-14.6.1.tgz",
"integrity": "sha512-HPswCfxThP0F92fmKqOetQ+E7HNiXDmOE+vHkfrpdKYNUj6Sn+7jaBICn8pNfif8uq4tF2ZGRnAgfUphry2ORQ==",
"version": "14.4.0",
"resolved": "https://registry.npmjs.org/@openedx/frontend-build/-/frontend-build-14.4.0.tgz",
"integrity": "sha512-9TrJ2x9n7VkMymah2e1+6cRhC0kpNdFDv63s2RbPdCHjfoFBvaelqfrwMw1KXfudnc6EO3M7scQTw2z3vfNrpA==",
"license": "AGPL-3.0",
"dependencies": {
"@babel/cli": "7.24.8",
@@ -4407,9 +4089,9 @@
}
},
"node_modules/@openedx/frontend-build/node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -4475,9 +4157,9 @@
}
},
"node_modules/@openedx/frontend-plugin-framework": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@openedx/frontend-plugin-framework/-/frontend-plugin-framework-1.7.0.tgz",
"integrity": "sha512-8tGkuHvtzhbqb9dU4sXUtR0K44+Hjh1uGR6DvhZAt9wSKQC1v4RBk34ef8DFzQhoNQa/Jtn6BJuta4Un6MmHmw==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@openedx/frontend-plugin-framework/-/frontend-plugin-framework-1.6.0.tgz",
"integrity": "sha512-zgP+/hs/cvcPmFOgVm2xt/qgX1nheNsfipzCO7I3bON4hHyOhmOyzwFZJ7pz7GzCJwKlMVguh3HcJgf4p/BPKQ==",
"license": "AGPL-3.0",
"dependencies": {
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
@@ -4551,10 +4233,33 @@
}
}
},
"node_modules/@openedx/frontend-plugin-framework/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==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.9.2"
}
},
"node_modules/@openedx/frontend-slot-footer": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@openedx/frontend-slot-footer/-/frontend-slot-footer-1.2.0.tgz",
"integrity": "sha512-bJuqgdiAlPRj1QuUOJWtNqGTCTcdsk4vHeOM3jRkxtWycq+j1JpGnnZEWAmjoRv9dDKr39vt2buNrmvj0sCTbA==",
"license": "AGPL-3.0",
"dependencies": {
"@openedx/frontend-plugin-framework": "^1.5.0"
},
"peerDependencies": {
"@edx/frontend-component-footer": "*",
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
}
},
"node_modules/@openedx/paragon": {
"version": "23.14.2",
"resolved": "https://registry.npmjs.org/@openedx/paragon/-/paragon-23.14.2.tgz",
"integrity": "sha512-mBsoH9nwt4VGkoE9y33BrSJsjTzWlKjooWGXeJng4LdFNnBy7bhtEvRENQ9/0L0/trWhEMZffAMP7h9HBfg5EQ==",
"version": "22.17.0",
"resolved": "https://registry.npmjs.org/@openedx/paragon/-/paragon-22.17.0.tgz",
"integrity": "sha512-MzOLQ0myaOErwumPJwxVZXTw7zJKrARtu4YMSaISF5Sz6pE1/dYz9qfRcqaraYRcJGNdbPRzOG0v3iqbZo1uHQ==",
"license": "Apache-2.0",
"workspaces": [
"example",
@@ -4564,33 +4269,20 @@
"dependent-usage-analyzer"
],
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.1.1",
"@fortawesome/react-fontawesome": "^0.1.18",
"@popperjs/core": "^2.11.4",
"@tokens-studio/sd-transforms": "^1.2.4",
"axios": "^0.27.2",
"bootstrap": "^4.6.2",
"chalk": "^4.1.2",
"child_process": "^1.0.2",
"chroma-js": "^2.4.2",
"classnames": "^2.3.1",
"cli-progress": "^3.12.0",
"commander": "^9.4.1",
"email-prop-type": "^3.0.0",
"file-selector": "^0.6.0",
"font-awesome": "^4.7.0",
"glob": "^8.0.3",
"inquirer": "^8.2.5",
"js-toml": "^1.0.0",
"lodash.uniqby": "^4.7.0",
"log-update": "^4.0.0",
"lz-string": "^1.5.0",
"mailto-link": "^2.0.0",
"minimist": "^1.2.8",
"ora": "^5.4.1",
"postcss": "^8.4.21",
"postcss-combine-duplicated-selectors": "^10.0.3",
"postcss-custom-media": "^9.1.2",
"postcss-import": "^15.1.0",
"postcss-map": "^0.11.0",
"postcss-minify": "^1.1.0",
"prop-types": "^15.8.1",
"react-bootstrap": "^1.6.5",
"react-colorful": "^5.6.1",
@@ -4603,8 +4295,6 @@
"react-responsive": "^8.2.0",
"react-table": "^7.7.0",
"react-transition-group": "^4.4.2",
"sass": "^1.58.3",
"style-dictionary": "^4.3.2",
"tabbable": "^5.3.3",
"uncontrollable": "^7.2.1",
"uuid": "^9.0.0"
@@ -4618,34 +4308,28 @@
"react-intl": "^5.25.1 || ^6.4.0"
}
},
"node_modules/@openedx/paragon/node_modules/axios": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"node_modules/@openedx/paragon/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==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
"prop-types": "^15.8.1"
},
"peerDependencies": {
"@fortawesome/fontawesome-svg-core": "~1 || ~6",
"react": ">=16.x"
}
},
"node_modules/@openedx/paragon/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@openedx/paragon/node_modules/commander": {
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
"license": "MIT",
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/@openedx/paragon/node_modules/glob": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
@@ -4678,34 +4362,6 @@
"node": ">=10"
}
},
"node_modules/@openedx/paragon/node_modules/postcss-custom-media": {
"version": "9.1.5",
"resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-9.1.5.tgz",
"integrity": "sha512-GStyWMz7Qbo/Gtw1xVspzVSX8eipgNg4lpsO3CAeY4/A1mzok+RV6MCv3fg62trWijh/lYEj6vps4o8JcBBpDA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"license": "MIT",
"dependencies": {
"@csstools/cascade-layer-name-parser": "^1.0.2",
"@csstools/css-parser-algorithms": "^2.2.0",
"@csstools/css-tokenizer": "^2.1.1",
"@csstools/media-query-list-parser": "^2.1.1"
},
"engines": {
"node": "^14 || ^16 || >=18"
},
"peerDependencies": {
"postcss": "^8.4"
}
},
"node_modules/@openedx/paragon/node_modules/react-responsive": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-8.2.0.tgz",
@@ -4737,15 +4393,6 @@
"uuid": "dist/bin/uuid"
}
},
"node_modules/@paralleldrive/cuid2": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz",
"integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "^1.1.5"
}
},
"node_modules/@parcel/watcher": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
@@ -5042,16 +4689,6 @@
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=14"
}
},
"node_modules/@pmmmwh/react-refresh-webpack-plugin": {
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz",
@@ -5101,9 +4738,9 @@
}
},
"node_modules/@polka/url": {
"version": "1.0.0-next.29",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
"integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
"version": "1.0.0-next.28",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz",
"integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==",
"license": "MIT"
},
"node_modules/@popperjs/core": {
@@ -5153,10 +4790,19 @@
}
}
},
"node_modules/@reduxjs/toolkit/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==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.9.2"
}
},
"node_modules/@remix-run/router": {
"version": "1.23.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz",
"integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==",
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.20.0.tgz",
"integrity": "sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
@@ -5471,9 +5117,9 @@
}
},
"node_modules/@tanstack/query-core": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.40.0.tgz",
"integrity": "sha512-7MJTtZkCSuehMC7IxMOCGsLvHS3jHx4WjveSrGsG1Nc1UQLjaFwwkpLA2LmPfvOAxnH4mszMOBFD6LlZE+aB+Q==",
"version": "4.36.1",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.36.1.tgz",
"integrity": "sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==",
"license": "MIT",
"funding": {
"type": "github",
@@ -5481,12 +5127,12 @@
}
},
"node_modules/@tanstack/react-query": {
"version": "4.40.1",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.40.1.tgz",
"integrity": "sha512-mgD07S5N8e5v81CArKDWrHE4LM7HxZ9k/KLeD3+NUD9WimGZgKIqojUZf/rXkfAMYZU9p0Chzj2jOXm7xpgHHQ==",
"version": "4.36.1",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.36.1.tgz",
"integrity": "sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==",
"license": "MIT",
"dependencies": {
"@tanstack/query-core": "4.40.0",
"@tanstack/query-core": "4.36.1",
"use-sync-external-store": "^1.2.0"
},
"funding": {
@@ -5513,7 +5159,6 @@
"integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
@@ -5529,17 +5174,18 @@
}
},
"node_modules/@testing-library/jest-dom": {
"version": "6.8.0",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.8.0.tgz",
"integrity": "sha512-WgXcWzVM6idy5JaftTVC8Vs83NKRmGJz4Hqs4oyOuO2J4r/y79vvKZsb+CaGyCSEbUPI6OsewfPd0G1A0/TUZQ==",
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz",
"integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@adobe/css-tools": "^4.4.0",
"aria-query": "^5.0.0",
"chalk": "^3.0.0",
"css.escape": "^1.5.1",
"dom-accessibility-api": "^0.6.3",
"picocolors": "^1.1.1",
"lodash": "^4.17.21",
"redent": "^3.0.0"
},
"engines": {
@@ -5548,6 +5194,20 @@
"yarn": ">=1"
}
},
"node_modules/@testing-library/jest-dom/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,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=8"
}
},
"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",
@@ -5556,9 +5216,9 @@
"license": "MIT"
},
"node_modules/@testing-library/react": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz",
"integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==",
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.2.0.tgz",
"integrity": "sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5584,13 +5244,16 @@
}
},
"node_modules/@testing-library/user-event": {
"version": "14.6.1",
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz",
"integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==",
"version": "13.5.0",
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz",
"integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.5"
},
"engines": {
"node": ">=12",
"node": ">=10",
"npm": ">=6"
},
"peerDependencies": {
@@ -5611,32 +5274,6 @@
"react-dom": "^18.0.0 || ^17.0.1 || ^16.7.0"
}
},
"node_modules/@tokens-studio/sd-transforms": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@tokens-studio/sd-transforms/-/sd-transforms-1.3.0.tgz",
"integrity": "sha512-zVbiYjTGWpSuwzZwiuvcWf79CQEcTMKSxrOaQJ0zHXFxEmrpETWeIRxv2IO8rtMos/cS8mvnDwPngoHQOMs1SA==",
"license": "MIT",
"dependencies": {
"@bundled-es-modules/deepmerge": "^4.3.1",
"@bundled-es-modules/postcss-calc-ast-parser": "^0.1.6",
"@tokens-studio/types": "^0.5.1",
"colorjs.io": "^0.5.2",
"expr-eval-fork": "^2.0.2",
"is-mergeable-object": "^1.1.1"
},
"engines": {
"node": ">=18.0.0"
},
"peerDependencies": {
"style-dictionary": "^4.3.0 || ^5.0.0-rc.0"
}
},
"node_modules/@tokens-studio/types": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/@tokens-studio/types/-/types-0.5.2.tgz",
"integrity": "sha512-rzMcZP0bj2E5jaa7Fj0LGgYHysoCrbrxILVbT0ohsCUH5uCHY/u6J7Qw/TE0n6gR9Js/c9ZO9T8mOoz0HdLMbA==",
"license": "MIT"
},
"node_modules/@tootallnate/once": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
@@ -5670,8 +5307,7 @@
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
@@ -5687,9 +5323,9 @@
}
},
"node_modules/@types/babel__generator": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
"integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
"version": "7.6.8",
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz",
"integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==",
"license": "MIT",
"dependencies": {
"@babel/types": "^7.0.0"
@@ -5981,9 +5617,10 @@
"license": "MIT"
},
"node_modules/@types/lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==",
"version": "4.17.16",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz",
"integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/mime": {
@@ -6006,12 +5643,12 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.15.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.2.tgz",
"integrity": "sha512-uKXqKN9beGoMdBfcaTY1ecwz6ctxuJAcUlwE55938g0ZJ8lRxwAZqRz2AJ4pzpt5dHdTPMB863UZ0ESiFUcP7A==",
"version": "22.13.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz",
"integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
"undici-types": "~6.20.0"
}
},
"node_modules/@types/node-forge": {
@@ -6061,25 +5698,15 @@
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.3.23",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz",
"integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==",
"version": "18.3.20",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz",
"integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==",
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/react-dom": {
"version": "18.3.7",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
"devOptional": true,
"license": "MIT",
"peerDependencies": {
"@types/react": "^18.0.0"
}
},
"node_modules/@types/react-redux": {
"version": "7.1.34",
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz",
@@ -6177,9 +5804,9 @@
"license": "MIT"
},
"node_modules/@types/ws": {
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.0.tgz",
"integrity": "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
@@ -6437,9 +6064,9 @@
}
},
"node_modules/@unrs/resolver-binding-darwin-arm64": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.2.tgz",
"integrity": "sha512-vxtBno4xvowwNmO/ASL0Y45TpHqmNkAaDtz4Jqb+clmcVSSl8XCG/PNFFkGsXXXS6AMjP+ja/TtNCFFa1QwLRg==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.3.2.tgz",
"integrity": "sha512-ddnlXgRi0Fog5+7U5Q1qY62wl95Q1lB4tXQX1UIA9YHmRCHN2twaQW0/4tDVGCvTVEU3xEayU7VemEr7GcBYUw==",
"cpu": [
"arm64"
],
@@ -6450,9 +6077,9 @@
]
},
"node_modules/@unrs/resolver-binding-darwin-x64": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.2.tgz",
"integrity": "sha512-qhVa8ozu92C23Hsmv0BF4+5Dyyd5STT1FolV4whNgbY6mj3kA0qsrGPe35zNR3wAN7eFict3s4Rc2dDTPBTuFQ==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.3.2.tgz",
"integrity": "sha512-tnl9xoEeg503jis+LW5cuq4hyLGQyqaoBL8VdPSqcewo/FL1C8POHbzl+AL25TidWYJD+R6bGUTE381kA1sT9w==",
"cpu": [
"x64"
],
@@ -6463,9 +6090,9 @@
]
},
"node_modules/@unrs/resolver-binding-freebsd-x64": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.2.tgz",
"integrity": "sha512-zKKdm2uMXqLFX6Ac7K5ElnnG5VIXbDlFWzg4WJ8CGUedJryM5A3cTgHuGMw1+P5ziV8CRhnSEgOnurTI4vpHpg==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.3.2.tgz",
"integrity": "sha512-zyPn9LFCCjhKPeCtECZaiMUgkYN/VpLb4a9Xv7QriJmTaQxsuDtXqOHifrzUXIhorJTyS+5MOKDuNL0X9I4EHA==",
"cpu": [
"x64"
],
@@ -6476,9 +6103,9 @@
]
},
"node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.2.tgz",
"integrity": "sha512-8N1z1TbPnHH+iDS/42GJ0bMPLiGK+cUqOhNbMKtWJ4oFGzqSJk/zoXFzcQkgtI63qMcUI7wW1tq2usZQSb2jxw==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.3.2.tgz",
"integrity": "sha512-UWx56Wh59Ro69fe+Wfvld4E1n9KG0e3zeouWLn8eSasyi/yVH/7ZW3CLTVFQ81oMKSpXwr5u6RpzttDXZKiO4g==",
"cpu": [
"arm"
],
@@ -6489,9 +6116,9 @@
]
},
"node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.2.tgz",
"integrity": "sha512-tjYzI9LcAXR9MYd9rO45m1s0B/6bJNuZ6jeOxo1pq1K6OBuRMMmfyvJYval3s9FPPGmrldYA3mi4gWDlWuTFGA==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.3.2.tgz",
"integrity": "sha512-VYGQXsOEJtfaoY2fOm8Z9ii5idFaHFYlrq3yMFZPaFKo8ufOXYm8hnfru7qetbM9MX116iWaPC0ZX5sK+1Dr+g==",
"cpu": [
"arm"
],
@@ -6502,9 +6129,9 @@
]
},
"node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.2.tgz",
"integrity": "sha512-jon9M7DKRLGZ9VYSkFMflvNqu9hDtOCEnO2QAryFWgT6o6AXU8du56V7YqnaLKr6rAbZBWYsYpikF226v423QA==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.3.2.tgz",
"integrity": "sha512-3zP420zxJfYPD1rGp2/OTIBxF8E3+/6VqCG+DEO6kkDgBiloa7Y8pw1o7N9BfgAC+VC8FPZsFXhV2lpx+lLRMQ==",
"cpu": [
"arm64"
],
@@ -6515,9 +6142,9 @@
]
},
"node_modules/@unrs/resolver-binding-linux-arm64-musl": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.2.tgz",
"integrity": "sha512-c8Cg4/h+kQ63pL43wBNaVMmOjXI/X62wQmru51qjfTvI7kmCy5uHTJvK/9LrF0G8Jdx8r34d019P1DVJmhXQpA==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.3.2.tgz",
"integrity": "sha512-ZWjSleUgr88H4Kei7yT4PlPqySTuWN1OYDDcdbmMCtLWFly3ed+rkrcCb3gvqXdDbYrGOtzv3g2qPEN+WWNv5Q==",
"cpu": [
"arm64"
],
@@ -6528,9 +6155,9 @@
]
},
"node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.2.tgz",
"integrity": "sha512-A+lcwRFyrjeJmv3JJvhz5NbcCkLQL6Mk16kHTNm6/aGNc4FwPHPE4DR9DwuCvCnVHvF5IAd9U4VIs/VvVir5lg==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.3.2.tgz",
"integrity": "sha512-p+5OvYJ2UOlpjes3WfBlxyvQok2u26hLyPxLFHkYlfzhZW0juhvBf/tvewz1LDFe30M7zL9cF4OOO5dcvtk+cw==",
"cpu": [
"ppc64"
],
@@ -6540,36 +6167,10 @@
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.2.tgz",
"integrity": "sha512-hQQ4TJQrSQW8JlPm7tRpXN8OCNP9ez7PajJNjRD1ZTHQAy685OYqPrKjfaMw/8LiHCt8AZ74rfUVHP9vn0N69Q==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.2.tgz",
"integrity": "sha512-NoAGbiqrxtY8kVooZ24i70CjLDlUFI7nDj3I9y54U94p+3kPxwd2L692YsdLa+cqQ0VoqMWoehDFp21PKRUoIQ==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.2.tgz",
"integrity": "sha512-KaZByo8xuQZbUhhreBTW+yUnOIHUsv04P8lKjQ5otiGoSJ17ISGYArc+4vKdLEpGaLbemGzr4ZeUbYQQsLWFjA==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.3.2.tgz",
"integrity": "sha512-yweY7I6SqNn3kvj6vE4PQRo7j8Oz6+NiUhmgciBNAUOuI3Jq0bnW29hbHJdxZRSN1kYkQnSkbbA1tT8VnK816w==",
"cpu": [
"s390x"
],
@@ -6580,9 +6181,9 @@
]
},
"node_modules/@unrs/resolver-binding-linux-x64-gnu": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.2.tgz",
"integrity": "sha512-dEidzJDubxxhUCBJ/SHSMJD/9q7JkyfBMT77Px1npl4xpg9t0POLvnWywSk66BgZS/b2Hy9Y1yFaoMTFJUe9yg==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.3.2.tgz",
"integrity": "sha512-fNIvtzJcGN9hzWTIayrTSk2+KHQrqKbbY+I88xMVMOFV9t4AXha4veJdKaIuuks+2JNr6GuuNdsL7+exywZ32w==",
"cpu": [
"x64"
],
@@ -6593,9 +6194,9 @@
]
},
"node_modules/@unrs/resolver-binding-linux-x64-musl": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.2.tgz",
"integrity": "sha512-RvP+Ux3wDjmnZDT4XWFfNBRVG0fMsc+yVzNFUqOflnDfZ9OYujv6nkh+GOr+watwrW4wdp6ASfG/e7bkDradsw==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.3.2.tgz",
"integrity": "sha512-OaFEw8WAjiwBGxutQgkWhoAGB5BQqZJ8Gjt/mW+m6DWNjimcxU22uWCuEtfw1CIwLlKPOzsgH0429fWmZcTGkg==",
"cpu": [
"x64"
],
@@ -6606,25 +6207,25 @@
]
},
"node_modules/@unrs/resolver-binding-wasm32-wasi": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.2.tgz",
"integrity": "sha512-y797JBmO9IsvXVRCKDXOxjyAE4+CcZpla2GSoBQ33TVb3ILXuFnMrbR/QQZoauBYeOFuu4w3ifWLw52sdHGz6g==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.3.2.tgz",
"integrity": "sha512-u+sumtO7M0AGQ9bNQrF4BHNpUyxo23FM/yXZfmVAicTQ+mXtG06O7pm5zQUw3Mr4jRs2I84uh4O0hd8bdouuvQ==",
"cpu": [
"wasm32"
],
"license": "MIT",
"optional": true,
"dependencies": {
"@napi-rs/wasm-runtime": "^0.2.9"
"@napi-rs/wasm-runtime": "^0.2.7"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.2.tgz",
"integrity": "sha512-gtYTh4/VREVSLA+gHrfbWxaMO/00y+34htY7XpioBTy56YN2eBjkPrY1ML1Zys89X3RJDKVaogzwxlM1qU7egg==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.3.2.tgz",
"integrity": "sha512-ZAJKy95vmDIHsRFuPNqPQRON8r2mSMf3p9DoX+OMOhvu2c8OXGg8MvhGRf3PNg45ozRrPdXDnngURKgaFfpGoQ==",
"cpu": [
"arm64"
],
@@ -6635,9 +6236,9 @@
]
},
"node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.2.tgz",
"integrity": "sha512-Ywv20XHvHTDRQs12jd3MY8X5C8KLjDbg/jyaal/QLKx3fAShhJyD4blEANInsjxW3P7isHx1Blt56iUDDJO3jg==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.3.2.tgz",
"integrity": "sha512-nQG4YFAS2BLoKVQFK/FrWJvFATI5DQUWQrcPcsWG9Ve5BLLHZuPOrJ2SpAJwLXQrRv6XHSFAYGI8wQpBg/CiFA==",
"cpu": [
"ia32"
],
@@ -6648,9 +6249,9 @@
]
},
"node_modules/@unrs/resolver-binding-win32-x64-msvc": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.2.tgz",
"integrity": "sha512-friS8NEQfHaDbkThxopGk+LuE5v3iY0StruifjQEt7SLbA46OnfgMO15sOTkbpJkol6RB+1l1TYPXh0sCddpvA==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.3.2.tgz",
"integrity": "sha512-XBWpUP0mHya6yGBwNefhyEa6V7HgYKCxEAY4qhTm/PcAQyBPNmjj97VZJOJkVdUsyuuii7xmq0pXWX/c2aToHQ==",
"cpu": [
"x64"
],
@@ -6862,23 +6463,6 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"license": "Apache-2.0"
},
"node_modules/@yarnpkg/lockfile": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
"license": "BSD-2-Clause"
},
"node_modules/@zip.js/zip.js": {
"version": "2.7.60",
"resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.7.60.tgz",
"integrity": "sha512-vA3rLyqdxBrVo1FWSsbyoecaqWTV+vgPRf0QKeM7kVDG0r+lHUqd7zQDv1TO9k4BcAoNzNDSNrrel24Mk6addA==",
"license": "BSD-3-Clause",
"engines": {
"bun": ">=0.7.0",
"deno": ">=1.0.0",
"node": ">=16.5.0"
}
},
"node_modules/abab": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -7329,19 +6913,6 @@
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
"license": "MIT"
},
"node_modules/assert": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz",
"integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.2",
"is-nan": "^1.3.2",
"object-is": "^1.1.5",
"object.assign": "^4.1.4",
"util": "^0.12.5"
}
},
"node_modules/assert-ok": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-ok/-/assert-ok-1.0.0.tgz",
@@ -7358,6 +6929,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -7464,9 +7036,9 @@
}
},
"node_modules/axios": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
"integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
"version": "1.8.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
"integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
@@ -7475,9 +7047,9 @@
}
},
"node_modules/axios-cache-interceptor": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-1.8.0.tgz",
"integrity": "sha512-cTNnPGJyQkxnWp0EWvE3NRvgURU5cWw/Qx3dIhXyHSM4Ip0c7EEe0I3an0Jwa549m1CAOg57ibj27YRNLmQCcg==",
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-1.6.2.tgz",
"integrity": "sha512-YLbAODIHZZIcD4b3WYFVQOa5W2TY/WnJ6sBHqAg6Z+hx+RVj8/OcjQyRopO6awn7/kOkGL5X9TP16AucnlJ/lw==",
"license": "MIT",
"dependencies": {
"cache-parser": "1.2.5",
@@ -7495,10 +7067,9 @@
}
},
"node_modules/axios-mock-adapter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-2.1.0.tgz",
"integrity": "sha512-AZUe4OjECGCNNssH8SOdtneiQELsqTsat3SQQCWLPjN436/H+L9AjWfV7bF+Zg/YL9cgbhrz5671hoh+Tbn98w==",
"dev": true,
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.22.0.tgz",
"integrity": "sha512-dmI0KbkyAhntUR05YY96qg2H6gg0XMl2+qTW0xmYg6Up+BFBAJYRLROMXRdDEL06/Wqwa0TJThAYvFtSFdRCZw==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
@@ -7681,15 +7252,6 @@
"node": ">=10"
}
},
"node_modules/babel-plugin-macros/node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"license": "ISC",
"engines": {
"node": ">= 6"
}
},
"node_modules/babel-plugin-polyfill-corejs2": {
"version": "0.4.13",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz",
@@ -7844,9 +7406,9 @@
"optional": true
},
"node_modules/bare-fs": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.3.tgz",
"integrity": "sha512-OeEZYIg+2qepaWLyphaOXHAHKo3xkM8y3BeGAvHdMN8GNWvEAU1Yw6rYpGzu/wDDbKxgEjVeVDpgGhDzaeMpjg==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.0.2.tgz",
"integrity": "sha512-S5mmkMesiduMqnz51Bfh0Et9EX0aTCJxhsI4bvzFFLs8Z1AV8RDHadfY5CyLwdoLHgXbNBEN1gQcbEtGwuvixw==",
"license": "Apache-2.0",
"optional": true,
"dependencies": {
@@ -8056,9 +7618,9 @@
}
},
"node_modules/brace-expansion": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@@ -8298,9 +7860,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001737",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001737.tgz",
"integrity": "sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==",
"version": "1.0.30001715",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz",
"integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==",
"funding": [
{
"type": "opencollective",
@@ -8348,12 +7910,6 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/change-case": {
"version": "5.4.4",
"resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz",
"integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==",
"license": "MIT"
},
"node_modules/char-regex": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
@@ -8369,20 +7925,6 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"license": "MIT"
},
"node_modules/chevrotain": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz",
"integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==",
"license": "Apache-2.0",
"dependencies": {
"@chevrotain/cst-dts-gen": "11.0.3",
"@chevrotain/gast": "11.0.3",
"@chevrotain/regexp-to-ast": "11.0.3",
"@chevrotain/types": "11.0.3",
"@chevrotain/utils": "11.0.3",
"lodash-es": "4.17.21"
}
},
"node_modules/child_process": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
@@ -8419,12 +7961,6 @@
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
"license": "ISC"
},
"node_modules/chroma-js": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.6.0.tgz",
"integrity": "sha512-BLHvCB9s8Z1EV4ethr6xnkl/P2YRFOGqfgvuMG/MyCbZPrTA+NeiByY6XvgF0zP4/2deU2CXnWyMa3zu1LqQ3A==",
"license": "(BSD-3-Clause AND Apache-2.0)"
},
"node_modules/chrome-trace-event": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
@@ -8509,18 +8045,6 @@
"node": ">=8"
}
},
"node_modules/cli-progress": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz",
"integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==",
"license": "MIT",
"dependencies": {
"string-width": "^4.2.3"
},
"engines": {
"node": ">=4"
}
},
"node_modules/cli-spinners": {
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
@@ -8616,9 +8140,9 @@
}
},
"node_modules/codemirror": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz",
"integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
"license": "MIT",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
@@ -8689,12 +8213,6 @@
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
"license": "MIT"
},
"node_modules/colorjs.io": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz",
"integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==",
"license": "MIT"
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -8723,13 +8241,10 @@
"license": "ISC"
},
"node_modules/component-emitter": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-2.0.0.tgz",
"integrity": "sha512-4m5s3Me2xxlVKG9PkZpQqHQR7bgpnN7joDMJ4yvVkVXngjoITG76IaZmzmywSeRTeTpc6N6r3H3+KyUurV8OYw==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
"integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
@@ -8747,16 +8262,16 @@
}
},
"node_modules/compression": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
"integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz",
"integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"compressible": "~2.0.18",
"debug": "2.6.9",
"negotiator": "~0.6.4",
"on-headers": "~1.1.0",
"on-headers": "~1.0.2",
"safe-buffer": "5.2.1",
"vary": "~1.1.2"
},
@@ -9836,8 +9351,7 @@
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/dom-converter": {
"version": "0.2.0",
@@ -9998,12 +9512,6 @@
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
"license": "MIT"
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"license": "MIT"
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -10026,9 +9534,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.143",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.143.tgz",
"integrity": "sha512-QqklJMOFBMqe46k8iIOwA9l2hz57V2OKMmP5eSWcUvwx+mASAsbU+wkF1pHjn9ZVSBPrsYWr4/W/95y5SwYg2g==",
"version": "1.5.126",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.126.tgz",
"integrity": "sha512-AtH1uLcTC72LA4vfYcEJJkrMk/MY/X0ub8Hv7QGAePW2JkeUFHEL/QfS4J77R6M87Sss8O0OcqReSaN1bpyA+Q==",
"license": "ISC"
},
"node_modules/email-prop-type": {
@@ -10066,15 +9574,6 @@
"integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
"license": "MIT"
},
"node_modules/emoji-regex-xs": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-2.0.1.tgz",
"integrity": "sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
@@ -10269,9 +9768,9 @@
}
},
"node_modules/es-module-lexer": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz",
"integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==",
"license": "MIT"
},
"node_modules/es-object-atoms": {
@@ -10521,23 +10020,23 @@
}
},
"node_modules/eslint-import-resolver-typescript": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.3.4.tgz",
"integrity": "sha512-buzw5z5VtiQMysYLH9iW9BV04YyZebsw+gPi+c4FCjfS9i6COYOrEWw9t3m3wA9PFBfqcBCqWf32qrXLbwafDw==",
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.2.5.tgz",
"integrity": "sha512-VtSNsVbyDlubDcx5Lb1K1Y8G4MxUuC9XVALX1z2EIXaLobCedvFPQ2XRemobQStn04G9MRi3iu1JFLKI4/8fig==",
"license": "ISC",
"dependencies": {
"debug": "^4.4.0",
"get-tsconfig": "^4.10.0",
"is-bun-module": "^2.0.0",
"stable-hash": "^0.0.5",
"tinyglobby": "^0.2.13",
"unrs-resolver": "^1.6.3"
"tinyglobby": "^0.2.12",
"unrs-resolver": "^1.3.2"
},
"engines": {
"node": "^16.17.0 || >=18.6.0"
},
"funding": {
"url": "https://opencollective.com/eslint-import-resolver-typescript"
"url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts"
},
"peerDependencies": {
"eslint": "*",
@@ -10835,9 +10334,9 @@
}
},
"node_modules/eslint-plugin-formatjs/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -10889,9 +10388,9 @@
"license": "0BSD"
},
"node_modules/eslint-plugin-formatjs/node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"version": "5.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
@@ -11388,12 +10887,6 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/expr-eval-fork": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/expr-eval-fork/-/expr-eval-fork-2.0.2.tgz",
"integrity": "sha512-NaAnObPVwHEYrODd7Jzp3zzT9pgTAlUUL4MZiZu9XAYPDpx89cPsfyEImFb2XY0vQNbrqg2CG7CLiI+Rs3seaQ==",
"license": "MIT"
},
"node_modules/express": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
@@ -11763,9 +11256,9 @@
}
},
"node_modules/filelist/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -11881,15 +11374,6 @@
"node": ">=8"
}
},
"node_modules/find-yarn-workspace-root": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
"integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
"license": "Apache-2.0",
"dependencies": {
"micromatch": "^4.0.2"
}
},
"node_modules/flat": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
@@ -11967,6 +11451,15 @@
}
}
},
"node_modules/font-awesome": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
"integrity": "sha512-U6kGnykA/6bFmg1M/oT9EkFeIYv7JlX3bozwQJWiiLz6L0w3F5vBVPxHlwyX/vtNq1ckcpRKOB9f2Qal/VtFpg==",
"license": "(OFL-1.1 AND MIT)",
"engines": {
"node": ">=0.10.3"
}
},
"node_modules/for-each": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
@@ -11982,34 +11475,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"license": "ISC",
"dependencies": {
"cross-spawn": "^7.0.6",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/foreground-child/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==",
"license": "ISC",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"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",
@@ -12104,25 +11569,15 @@
"node": ">=6"
}
},
"node_modules/fork-ts-checker-webpack-plugin/node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"license": "ISC",
"engines": {
"node": ">= 6"
}
},
"node_modules/form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
@@ -12136,18 +11591,15 @@
"license": "MIT"
},
"node_modules/formidable": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz",
"integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==",
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.2.tgz",
"integrity": "sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==",
"license": "MIT",
"dependencies": {
"@paralleldrive/cuid2": "^2.2.2",
"dezalgo": "^1.0.4",
"hexoid": "^2.0.0",
"once": "^1.4.0"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"url": "https://ko-fi.com/tunnckoCore/commissions"
}
@@ -12741,6 +12193,15 @@
"he": "bin/he"
}
},
"node_modules/hexoid": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-2.0.0.tgz",
"integrity": "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
@@ -12822,9 +12283,9 @@
}
},
"node_modules/html-entities": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz",
"integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.3.tgz",
"integrity": "sha512-D3AfvN7SjhTgBSA8L1BN4FpPzuEd06uy4lHwSoRWr0lndi9BKaNzPLKGOWZ2ocSGguozr08TTb2jhCLHaemruw==",
"funding": [
{
"type": "github",
@@ -12978,9 +12439,9 @@
}
},
"node_modules/http-parser-js": {
"version": "0.5.10",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
"integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
"version": "0.5.9",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz",
"integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==",
"license": "MIT"
},
"node_modules/http-proxy": {
@@ -13012,9 +12473,9 @@
}
},
"node_modules/http-proxy-middleware": {
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz",
"integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==",
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz",
"integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==",
"license": "MIT",
"dependencies": {
"@types/http-proxy": "^1.17.8",
@@ -13069,15 +12530,6 @@
"node": ">=10.17.0"
}
},
"node_modules/hyperdyperid": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz",
"integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==",
"license": "MIT",
"engines": {
"node": ">=10.18"
}
},
"node_modules/hyphenate-style-name": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz",
@@ -13458,22 +12910,6 @@
"node": ">= 0.10"
}
},
"node_modules/is-arguments": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
"integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-array-buffer": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
@@ -13563,7 +12999,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
"dev": true,
"funding": [
{
"type": "github",
@@ -13805,28 +13240,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-mergeable-object": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-mergeable-object/-/is-mergeable-object-1.1.1.tgz",
"integrity": "sha512-CPduJfuGg8h8vW74WOxHtHmtQutyQBzR+3MjQ6iDHIYdbOnm1YC7jv43SqCoU8OPGTJD4nibmiryA4kmogbGrA==",
"license": "MIT"
},
"node_modules/is-nan": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
"integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -13895,15 +13308,13 @@
}
},
"node_modules/is-plain-obj": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
"integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
"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==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
"node": ">=0.10.0"
}
},
"node_modules/is-plain-object": {
@@ -14262,21 +13673,6 @@
"node": ">= 0.4"
}
},
"node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/jake": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
@@ -15308,16 +14704,6 @@
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"license": "MIT"
},
"node_modules/js-toml": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/js-toml/-/js-toml-1.0.2.tgz",
"integrity": "sha512-/7IQ//bzn2a/5IDazPUNzlW7bsjxS51cxciYZDR+Z+3Le60yzT0YfI8KOWqTtBcZkXXVklhWd2OuGd8ZksB0wQ==",
"license": "MIT",
"dependencies": {
"chevrotain": "^11.0.3",
"xregexp": "^5.1.1"
}
},
"node_modules/js-yaml": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
@@ -15432,13 +14818,13 @@
"license": "MIT"
},
"node_modules/json-stable-stringify": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
"integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.2.1.tgz",
"integrity": "sha512-Lp6HbbBgosLmJbjx0pBLbgvx68FaFU1sdkmBuckmhhJ88kL13OA51CDtR2yJB50eCNMH9wRqtQNNiAqQH4YXnA==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.4",
"call-bound": "^1.0.3",
"isarray": "^2.0.5",
"jsonify": "^0.0.1",
"object-keys": "^1.1.1"
@@ -15540,15 +14926,6 @@
"node": ">=0.10.0"
}
},
"node_modules/klaw-sync": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
"integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.1.11"
}
},
"node_modules/kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -15799,24 +15176,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/log-update": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
"integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
"license": "MIT",
"dependencies": {
"ansi-escapes": "^4.3.0",
"cli-cursor": "^3.1.0",
"slice-ansi": "^4.0.0",
"wrap-ansi": "^6.2.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -15851,6 +15210,7 @@
"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,
"license": "MIT",
"bin": {
"lz-string": "bin/bin.js"
@@ -16285,25 +15645,6 @@
"node": ">= 6"
}
},
"node_modules/minimist-options/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==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/mkdirp-classic": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
@@ -16376,12 +15717,6 @@
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
"license": "ISC"
},
"node_modules/nanoclone": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
"integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==",
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
@@ -16406,21 +15741,6 @@
"integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
"license": "MIT"
},
"node_modules/napi-postinstall": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.2.tgz",
"integrity": "sha512-Wy1VI/hpKHwy1MsnFxHCJxqFwmmxD0RA/EKPL7e6mfbsY01phM2SZyJnRdU0bLvhu0Quby1DCcAZti3ghdl4/A==",
"license": "MIT",
"bin": {
"napi-postinstall": "lib/cli.js"
},
"engines": {
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/napi-postinstall"
}
},
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -16599,6 +15919,166 @@
"node": ">=0.10.0"
}
},
"node_modules/npm": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/npm/-/npm-10.9.2.tgz",
"integrity": "sha512-iriPEPIkoMYUy3F6f3wwSZAU93E0Eg6cHwIR6jzzOXWSy+SD/rOODEs74cVONHKSx2obXtuUoyidVEhISrisgQ==",
"bundleDependencies": [
"@isaacs/string-locale-compare",
"@npmcli/arborist",
"@npmcli/config",
"@npmcli/fs",
"@npmcli/map-workspaces",
"@npmcli/package-json",
"@npmcli/promise-spawn",
"@npmcli/redact",
"@npmcli/run-script",
"@sigstore/tuf",
"abbrev",
"archy",
"cacache",
"chalk",
"ci-info",
"cli-columns",
"fastest-levenshtein",
"fs-minipass",
"glob",
"graceful-fs",
"hosted-git-info",
"ini",
"init-package-json",
"is-cidr",
"json-parse-even-better-errors",
"libnpmaccess",
"libnpmdiff",
"libnpmexec",
"libnpmfund",
"libnpmhook",
"libnpmorg",
"libnpmpack",
"libnpmpublish",
"libnpmsearch",
"libnpmteam",
"libnpmversion",
"make-fetch-happen",
"minimatch",
"minipass",
"minipass-pipeline",
"ms",
"node-gyp",
"nopt",
"normalize-package-data",
"npm-audit-report",
"npm-install-checks",
"npm-package-arg",
"npm-pick-manifest",
"npm-profile",
"npm-registry-fetch",
"npm-user-validate",
"p-map",
"pacote",
"parse-conflict-json",
"proc-log",
"qrcode-terminal",
"read",
"semver",
"spdx-expression-parse",
"ssri",
"supports-color",
"tar",
"text-table",
"tiny-relative-date",
"treeverse",
"validate-npm-package-name",
"which",
"write-file-atomic"
],
"license": "Artistic-2.0",
"workspaces": [
"docs",
"smoke-tests",
"mock-globals",
"mock-registry",
"workspaces/*"
],
"dependencies": {
"@isaacs/string-locale-compare": "^1.1.0",
"@npmcli/arborist": "^8.0.0",
"@npmcli/config": "^9.0.0",
"@npmcli/fs": "^4.0.0",
"@npmcli/map-workspaces": "^4.0.2",
"@npmcli/package-json": "^6.1.0",
"@npmcli/promise-spawn": "^8.0.2",
"@npmcli/redact": "^3.0.0",
"@npmcli/run-script": "^9.0.1",
"@sigstore/tuf": "^3.0.0",
"abbrev": "^3.0.0",
"archy": "~1.0.0",
"cacache": "^19.0.1",
"chalk": "^5.3.0",
"ci-info": "^4.1.0",
"cli-columns": "^4.0.0",
"fastest-levenshtein": "^1.0.16",
"fs-minipass": "^3.0.3",
"glob": "^10.4.5",
"graceful-fs": "^4.2.11",
"hosted-git-info": "^8.0.2",
"ini": "^5.0.0",
"init-package-json": "^7.0.2",
"is-cidr": "^5.1.0",
"json-parse-even-better-errors": "^4.0.0",
"libnpmaccess": "^9.0.0",
"libnpmdiff": "^7.0.0",
"libnpmexec": "^9.0.0",
"libnpmfund": "^6.0.0",
"libnpmhook": "^11.0.0",
"libnpmorg": "^7.0.0",
"libnpmpack": "^8.0.0",
"libnpmpublish": "^10.0.1",
"libnpmsearch": "^8.0.0",
"libnpmteam": "^7.0.0",
"libnpmversion": "^7.0.0",
"make-fetch-happen": "^14.0.3",
"minimatch": "^9.0.5",
"minipass": "^7.1.1",
"minipass-pipeline": "^1.2.4",
"ms": "^2.1.2",
"node-gyp": "^11.0.0",
"nopt": "^8.0.0",
"normalize-package-data": "^7.0.0",
"npm-audit-report": "^6.0.0",
"npm-install-checks": "^7.1.1",
"npm-package-arg": "^12.0.0",
"npm-pick-manifest": "^10.0.0",
"npm-profile": "^11.0.1",
"npm-registry-fetch": "^18.0.2",
"npm-user-validate": "^3.0.0",
"p-map": "^4.0.0",
"pacote": "^19.0.1",
"parse-conflict-json": "^4.0.0",
"proc-log": "^5.0.0",
"qrcode-terminal": "^0.12.0",
"read": "^4.0.0",
"semver": "^7.6.3",
"spdx-expression-parse": "^4.0.0",
"ssri": "^12.0.0",
"supports-color": "^9.4.0",
"tar": "^6.2.1",
"text-table": "~0.2.0",
"tiny-relative-date": "^1.3.0",
"treeverse": "^3.0.0",
"validate-npm-package-name": "^6.0.0",
"which": "^5.0.0",
"write-file-atomic": "^6.0.0"
},
"bin": {
"npm": "bin/npm-cli.js",
"npx": "bin/npx-cli.js"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -16611,6 +16091,2391 @@
"node": ">=8"
}
},
"node_modules/npm/node_modules/@isaacs/cliui": {
"version": "8.0.2",
"inBundle": true,
"license": "ISC",
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": {
"version": "6.1.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": {
"version": "9.2.2",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"inBundle": true,
"license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": {
"version": "7.1.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/npm/node_modules/@isaacs/fs-minipass": {
"version": "4.0.1",
"inBundle": true,
"license": "ISC",
"dependencies": {
"minipass": "^7.0.4"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/npm/node_modules/@isaacs/string-locale-compare": {
"version": "1.1.0",
"inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/@npmcli/agent": {
"version": "3.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"agent-base": "^7.1.0",
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.1",
"lru-cache": "^10.0.1",
"socks-proxy-agent": "^8.0.3"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/arborist": {
"version": "8.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@isaacs/string-locale-compare": "^1.1.0",
"@npmcli/fs": "^4.0.0",
"@npmcli/installed-package-contents": "^3.0.0",
"@npmcli/map-workspaces": "^4.0.1",
"@npmcli/metavuln-calculator": "^8.0.0",
"@npmcli/name-from-folder": "^3.0.0",
"@npmcli/node-gyp": "^4.0.0",
"@npmcli/package-json": "^6.0.1",
"@npmcli/query": "^4.0.0",
"@npmcli/redact": "^3.0.0",
"@npmcli/run-script": "^9.0.1",
"bin-links": "^5.0.0",
"cacache": "^19.0.1",
"common-ancestor-path": "^1.0.1",
"hosted-git-info": "^8.0.0",
"json-parse-even-better-errors": "^4.0.0",
"json-stringify-nice": "^1.1.4",
"lru-cache": "^10.2.2",
"minimatch": "^9.0.4",
"nopt": "^8.0.0",
"npm-install-checks": "^7.1.0",
"npm-package-arg": "^12.0.0",
"npm-pick-manifest": "^10.0.0",
"npm-registry-fetch": "^18.0.1",
"pacote": "^19.0.0",
"parse-conflict-json": "^4.0.0",
"proc-log": "^5.0.0",
"proggy": "^3.0.0",
"promise-all-reject-late": "^1.0.0",
"promise-call-limit": "^3.0.1",
"read-package-json-fast": "^4.0.0",
"semver": "^7.3.7",
"ssri": "^12.0.0",
"treeverse": "^3.0.0",
"walk-up-path": "^3.0.1"
},
"bin": {
"arborist": "bin/index.js"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/config": {
"version": "9.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/map-workspaces": "^4.0.1",
"@npmcli/package-json": "^6.0.1",
"ci-info": "^4.0.0",
"ini": "^5.0.0",
"nopt": "^8.0.0",
"proc-log": "^5.0.0",
"semver": "^7.3.5",
"walk-up-path": "^3.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/fs": {
"version": "4.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"semver": "^7.3.5"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/git": {
"version": "6.0.1",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/promise-spawn": "^8.0.0",
"ini": "^5.0.0",
"lru-cache": "^10.0.1",
"npm-pick-manifest": "^10.0.0",
"proc-log": "^5.0.0",
"promise-inflight": "^1.0.1",
"promise-retry": "^2.0.1",
"semver": "^7.3.5",
"which": "^5.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/installed-package-contents": {
"version": "3.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"npm-bundled": "^4.0.0",
"npm-normalize-package-bin": "^4.0.0"
},
"bin": {
"installed-package-contents": "bin/index.js"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/map-workspaces": {
"version": "4.0.2",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/name-from-folder": "^3.0.0",
"@npmcli/package-json": "^6.0.0",
"glob": "^10.2.2",
"minimatch": "^9.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/metavuln-calculator": {
"version": "8.0.1",
"inBundle": true,
"license": "ISC",
"dependencies": {
"cacache": "^19.0.0",
"json-parse-even-better-errors": "^4.0.0",
"pacote": "^20.0.0",
"proc-log": "^5.0.0",
"semver": "^7.3.5"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/metavuln-calculator/node_modules/pacote": {
"version": "20.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/git": "^6.0.0",
"@npmcli/installed-package-contents": "^3.0.0",
"@npmcli/package-json": "^6.0.0",
"@npmcli/promise-spawn": "^8.0.0",
"@npmcli/run-script": "^9.0.0",
"cacache": "^19.0.0",
"fs-minipass": "^3.0.0",
"minipass": "^7.0.2",
"npm-package-arg": "^12.0.0",
"npm-packlist": "^9.0.0",
"npm-pick-manifest": "^10.0.0",
"npm-registry-fetch": "^18.0.0",
"proc-log": "^5.0.0",
"promise-retry": "^2.0.1",
"sigstore": "^3.0.0",
"ssri": "^12.0.0",
"tar": "^6.1.11"
},
"bin": {
"pacote": "bin/index.js"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/name-from-folder": {
"version": "3.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/node-gyp": {
"version": "4.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/package-json": {
"version": "6.1.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/git": "^6.0.0",
"glob": "^10.2.2",
"hosted-git-info": "^8.0.0",
"json-parse-even-better-errors": "^4.0.0",
"normalize-package-data": "^7.0.0",
"proc-log": "^5.0.0",
"semver": "^7.5.3"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/promise-spawn": {
"version": "8.0.2",
"inBundle": true,
"license": "ISC",
"dependencies": {
"which": "^5.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/query": {
"version": "4.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"postcss-selector-parser": "^6.1.2"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/redact": {
"version": "3.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@npmcli/run-script": {
"version": "9.0.2",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/node-gyp": "^4.0.0",
"@npmcli/package-json": "^6.0.0",
"@npmcli/promise-spawn": "^8.0.0",
"node-gyp": "^11.0.0",
"proc-log": "^5.0.0",
"which": "^5.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"inBundle": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">=14"
}
},
"node_modules/npm/node_modules/@sigstore/protobuf-specs": {
"version": "0.3.2",
"inBundle": true,
"license": "Apache-2.0",
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/@sigstore/tuf": {
"version": "3.0.0",
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
"@sigstore/protobuf-specs": "^0.3.2",
"tuf-js": "^3.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/@tufjs/canonical-json": {
"version": "2.0.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/abbrev": {
"version": "3.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/agent-base": {
"version": "7.1.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/npm/node_modules/aggregate-error": {
"version": "3.1.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"clean-stack": "^2.0.0",
"indent-string": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/ansi-regex": {
"version": "5.0.1",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/ansi-styles": {
"version": "6.2.1",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/npm/node_modules/aproba": {
"version": "2.0.0",
"inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/archy": {
"version": "1.0.0",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/balanced-match": {
"version": "1.0.2",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/bin-links": {
"version": "5.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"cmd-shim": "^7.0.0",
"npm-normalize-package-bin": "^4.0.0",
"proc-log": "^5.0.0",
"read-cmd-shim": "^5.0.0",
"write-file-atomic": "^6.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/binary-extensions": {
"version": "2.3.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm/node_modules/brace-expansion": {
"version": "2.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/npm/node_modules/cacache": {
"version": "19.0.1",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/fs": "^4.0.0",
"fs-minipass": "^3.0.0",
"glob": "^10.2.2",
"lru-cache": "^10.0.1",
"minipass": "^7.0.3",
"minipass-collect": "^2.0.1",
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.4",
"p-map": "^7.0.2",
"ssri": "^12.0.0",
"tar": "^7.4.3",
"unique-filename": "^4.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/cacache/node_modules/chownr": {
"version": "3.0.0",
"inBundle": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/npm/node_modules/cacache/node_modules/minizlib": {
"version": "3.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"minipass": "^7.0.4",
"rimraf": "^5.0.5"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/npm/node_modules/cacache/node_modules/mkdirp": {
"version": "3.0.1",
"inBundle": true,
"license": "MIT",
"bin": {
"mkdirp": "dist/cjs/src/bin.js"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/cacache/node_modules/p-map": {
"version": "7.0.2",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm/node_modules/cacache/node_modules/tar": {
"version": "7.4.3",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@isaacs/fs-minipass": "^4.0.0",
"chownr": "^3.0.0",
"minipass": "^7.1.2",
"minizlib": "^3.0.1",
"mkdirp": "^3.0.1",
"yallist": "^5.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/npm/node_modules/cacache/node_modules/yallist": {
"version": "5.0.0",
"inBundle": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/npm/node_modules/chalk": {
"version": "5.3.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/npm/node_modules/chownr": {
"version": "2.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": ">=10"
}
},
"node_modules/npm/node_modules/ci-info": {
"version": "4.1.0",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/sibiraj-s"
}
],
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/cidr-regex": {
"version": "4.1.1",
"inBundle": true,
"license": "BSD-2-Clause",
"dependencies": {
"ip-regex": "^5.0.0"
},
"engines": {
"node": ">=14"
}
},
"node_modules/npm/node_modules/clean-stack": {
"version": "2.2.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/npm/node_modules/cli-columns": {
"version": "4.0.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/npm/node_modules/cmd-shim": {
"version": "7.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/color-convert": {
"version": "2.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/npm/node_modules/color-name": {
"version": "1.1.4",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/common-ancestor-path": {
"version": "1.0.1",
"inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/cross-spawn": {
"version": "7.0.6",
"inBundle": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/npm/node_modules/cross-spawn/node_modules/which": {
"version": "2.0.2",
"inBundle": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/npm/node_modules/cssesc": {
"version": "3.0.0",
"inBundle": true,
"license": "MIT",
"bin": {
"cssesc": "bin/cssesc"
},
"engines": {
"node": ">=4"
}
},
"node_modules/npm/node_modules/debug": {
"version": "4.3.7",
"inBundle": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/npm/node_modules/diff": {
"version": "5.2.0",
"inBundle": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/npm/node_modules/eastasianwidth": {
"version": "0.2.0",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/emoji-regex": {
"version": "8.0.0",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/encoding": {
"version": "0.1.13",
"inBundle": true,
"license": "MIT",
"optional": true,
"dependencies": {
"iconv-lite": "^0.6.2"
}
},
"node_modules/npm/node_modules/env-paths": {
"version": "2.2.1",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/npm/node_modules/err-code": {
"version": "2.0.3",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/exponential-backoff": {
"version": "3.1.1",
"inBundle": true,
"license": "Apache-2.0"
},
"node_modules/npm/node_modules/fastest-levenshtein": {
"version": "1.0.16",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">= 4.9.1"
}
},
"node_modules/npm/node_modules/foreground-child": {
"version": "3.3.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/fs-minipass": {
"version": "3.0.3",
"inBundle": true,
"license": "ISC",
"dependencies": {
"minipass": "^7.0.3"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/glob": {
"version": "10.4.5",
"inBundle": true,
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/graceful-fs": {
"version": "4.2.11",
"inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/hosted-git-info": {
"version": "8.0.2",
"inBundle": true,
"license": "ISC",
"dependencies": {
"lru-cache": "^10.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/http-cache-semantics": {
"version": "4.1.1",
"inBundle": true,
"license": "BSD-2-Clause"
},
"node_modules/npm/node_modules/http-proxy-agent": {
"version": "7.0.2",
"inBundle": true,
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.0",
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/npm/node_modules/https-proxy-agent": {
"version": "7.0.5",
"inBundle": true,
"license": "MIT",
"dependencies": {
"agent-base": "^7.0.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/npm/node_modules/iconv-lite": {
"version": "0.6.3",
"inBundle": true,
"license": "MIT",
"optional": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/npm/node_modules/ignore-walk": {
"version": "7.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"minimatch": "^9.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/imurmurhash": {
"version": "0.1.4",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=0.8.19"
}
},
"node_modules/npm/node_modules/indent-string": {
"version": "4.0.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/ini": {
"version": "5.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/init-package-json": {
"version": "7.0.2",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/package-json": "^6.0.0",
"npm-package-arg": "^12.0.0",
"promzard": "^2.0.0",
"read": "^4.0.0",
"semver": "^7.3.5",
"validate-npm-package-license": "^3.0.4",
"validate-npm-package-name": "^6.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/ip-address": {
"version": "9.0.5",
"inBundle": true,
"license": "MIT",
"dependencies": {
"jsbn": "1.1.0",
"sprintf-js": "^1.1.3"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/npm/node_modules/ip-regex": {
"version": "5.0.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm/node_modules/is-cidr": {
"version": "5.1.0",
"inBundle": true,
"license": "BSD-2-Clause",
"dependencies": {
"cidr-regex": "^4.1.1"
},
"engines": {
"node": ">=14"
}
},
"node_modules/npm/node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/isexe": {
"version": "2.0.0",
"inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/jackspeak": {
"version": "3.4.3",
"inBundle": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/npm/node_modules/jsbn": {
"version": "1.1.0",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/json-parse-even-better-errors": {
"version": "4.0.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/json-stringify-nice": {
"version": "1.1.4",
"inBundle": true,
"license": "ISC",
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/jsonparse": {
"version": "1.3.1",
"engines": [
"node >= 0.2.0"
],
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/just-diff": {
"version": "6.0.2",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/just-diff-apply": {
"version": "5.5.0",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/libnpmaccess": {
"version": "9.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"npm-package-arg": "^12.0.0",
"npm-registry-fetch": "^18.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/libnpmdiff": {
"version": "7.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/arborist": "^8.0.0",
"@npmcli/installed-package-contents": "^3.0.0",
"binary-extensions": "^2.3.0",
"diff": "^5.1.0",
"minimatch": "^9.0.4",
"npm-package-arg": "^12.0.0",
"pacote": "^19.0.0",
"tar": "^6.2.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/libnpmexec": {
"version": "9.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/arborist": "^8.0.0",
"@npmcli/run-script": "^9.0.1",
"ci-info": "^4.0.0",
"npm-package-arg": "^12.0.0",
"pacote": "^19.0.0",
"proc-log": "^5.0.0",
"read": "^4.0.0",
"read-package-json-fast": "^4.0.0",
"semver": "^7.3.7",
"walk-up-path": "^3.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/libnpmfund": {
"version": "6.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/arborist": "^8.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/libnpmhook": {
"version": "11.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"aproba": "^2.0.0",
"npm-registry-fetch": "^18.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/libnpmorg": {
"version": "7.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"aproba": "^2.0.0",
"npm-registry-fetch": "^18.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/libnpmpack": {
"version": "8.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/arborist": "^8.0.0",
"@npmcli/run-script": "^9.0.1",
"npm-package-arg": "^12.0.0",
"pacote": "^19.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/libnpmpublish": {
"version": "10.0.1",
"inBundle": true,
"license": "ISC",
"dependencies": {
"ci-info": "^4.0.0",
"normalize-package-data": "^7.0.0",
"npm-package-arg": "^12.0.0",
"npm-registry-fetch": "^18.0.1",
"proc-log": "^5.0.0",
"semver": "^7.3.7",
"sigstore": "^3.0.0",
"ssri": "^12.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/libnpmsearch": {
"version": "8.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"npm-registry-fetch": "^18.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/libnpmteam": {
"version": "7.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"aproba": "^2.0.0",
"npm-registry-fetch": "^18.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/libnpmversion": {
"version": "7.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/git": "^6.0.1",
"@npmcli/run-script": "^9.0.1",
"json-parse-even-better-errors": "^4.0.0",
"proc-log": "^5.0.0",
"semver": "^7.3.7"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/lru-cache": {
"version": "10.4.3",
"inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/make-fetch-happen": {
"version": "14.0.3",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/agent": "^3.0.0",
"cacache": "^19.0.1",
"http-cache-semantics": "^4.1.1",
"minipass": "^7.0.2",
"minipass-fetch": "^4.0.0",
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.4",
"negotiator": "^1.0.0",
"proc-log": "^5.0.0",
"promise-retry": "^2.0.1",
"ssri": "^12.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator": {
"version": "1.0.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/npm/node_modules/minimatch": {
"version": "9.0.5",
"inBundle": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/minipass": {
"version": "7.1.2",
"inBundle": true,
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/npm/node_modules/minipass-collect": {
"version": "2.0.1",
"inBundle": true,
"license": "ISC",
"dependencies": {
"minipass": "^7.0.3"
},
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/npm/node_modules/minipass-fetch": {
"version": "4.0.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"minipass": "^7.0.3",
"minipass-sized": "^1.0.3",
"minizlib": "^3.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
},
"optionalDependencies": {
"encoding": "^0.1.13"
}
},
"node_modules/npm/node_modules/minipass-fetch/node_modules/minizlib": {
"version": "3.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"minipass": "^7.0.4",
"rimraf": "^5.0.5"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/npm/node_modules/minipass-flush": {
"version": "1.0.5",
"inBundle": true,
"license": "ISC",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/npm/node_modules/minipass-flush/node_modules/minipass": {
"version": "3.3.6",
"inBundle": true,
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/minipass-pipeline": {
"version": "1.2.4",
"inBundle": true,
"license": "ISC",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": {
"version": "3.3.6",
"inBundle": true,
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/minipass-sized": {
"version": "1.0.3",
"inBundle": true,
"license": "ISC",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/minipass-sized/node_modules/minipass": {
"version": "3.3.6",
"inBundle": true,
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/minizlib": {
"version": "2.1.2",
"inBundle": true,
"license": "MIT",
"dependencies": {
"minipass": "^3.0.0",
"yallist": "^4.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/npm/node_modules/minizlib/node_modules/minipass": {
"version": "3.3.6",
"inBundle": true,
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/mkdirp": {
"version": "1.0.4",
"inBundle": true,
"license": "MIT",
"bin": {
"mkdirp": "bin/cmd.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/npm/node_modules/ms": {
"version": "2.1.3",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/mute-stream": {
"version": "2.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/node-gyp": {
"version": "11.0.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"env-paths": "^2.2.0",
"exponential-backoff": "^3.1.1",
"glob": "^10.3.10",
"graceful-fs": "^4.2.6",
"make-fetch-happen": "^14.0.3",
"nopt": "^8.0.0",
"proc-log": "^5.0.0",
"semver": "^7.3.5",
"tar": "^7.4.3",
"which": "^5.0.0"
},
"bin": {
"node-gyp": "bin/node-gyp.js"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/node-gyp/node_modules/chownr": {
"version": "3.0.0",
"inBundle": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/npm/node_modules/node-gyp/node_modules/minizlib": {
"version": "3.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"minipass": "^7.0.4",
"rimraf": "^5.0.5"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/npm/node_modules/node-gyp/node_modules/mkdirp": {
"version": "3.0.1",
"inBundle": true,
"license": "MIT",
"bin": {
"mkdirp": "dist/cjs/src/bin.js"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/node-gyp/node_modules/tar": {
"version": "7.4.3",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@isaacs/fs-minipass": "^4.0.0",
"chownr": "^3.0.0",
"minipass": "^7.1.2",
"minizlib": "^3.0.1",
"mkdirp": "^3.0.1",
"yallist": "^5.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/npm/node_modules/node-gyp/node_modules/yallist": {
"version": "5.0.0",
"inBundle": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/npm/node_modules/nopt": {
"version": "8.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"abbrev": "^2.0.0"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/nopt/node_modules/abbrev": {
"version": "2.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/normalize-package-data": {
"version": "7.0.0",
"inBundle": true,
"license": "BSD-2-Clause",
"dependencies": {
"hosted-git-info": "^8.0.0",
"semver": "^7.3.5",
"validate-npm-package-license": "^3.0.4"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/npm-audit-report": {
"version": "6.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/npm-bundled": {
"version": "4.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"npm-normalize-package-bin": "^4.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/npm-install-checks": {
"version": "7.1.1",
"inBundle": true,
"license": "BSD-2-Clause",
"dependencies": {
"semver": "^7.1.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/npm-normalize-package-bin": {
"version": "4.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/npm-package-arg": {
"version": "12.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"hosted-git-info": "^8.0.0",
"proc-log": "^5.0.0",
"semver": "^7.3.5",
"validate-npm-package-name": "^6.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/npm-packlist": {
"version": "9.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"ignore-walk": "^7.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/npm-pick-manifest": {
"version": "10.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"npm-install-checks": "^7.1.0",
"npm-normalize-package-bin": "^4.0.0",
"npm-package-arg": "^12.0.0",
"semver": "^7.3.5"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/npm-profile": {
"version": "11.0.1",
"inBundle": true,
"license": "ISC",
"dependencies": {
"npm-registry-fetch": "^18.0.0",
"proc-log": "^5.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/npm-registry-fetch": {
"version": "18.0.2",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/redact": "^3.0.0",
"jsonparse": "^1.3.1",
"make-fetch-happen": "^14.0.0",
"minipass": "^7.0.2",
"minipass-fetch": "^4.0.0",
"minizlib": "^3.0.1",
"npm-package-arg": "^12.0.0",
"proc-log": "^5.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/npm-registry-fetch/node_modules/minizlib": {
"version": "3.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"minipass": "^7.0.4",
"rimraf": "^5.0.5"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/npm/node_modules/npm-user-validate": {
"version": "3.0.0",
"inBundle": true,
"license": "BSD-2-Clause",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/p-map": {
"version": "4.0.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"aggregate-error": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm/node_modules/package-json-from-dist": {
"version": "1.0.1",
"inBundle": true,
"license": "BlueOak-1.0.0"
},
"node_modules/npm/node_modules/pacote": {
"version": "19.0.1",
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/git": "^6.0.0",
"@npmcli/installed-package-contents": "^3.0.0",
"@npmcli/package-json": "^6.0.0",
"@npmcli/promise-spawn": "^8.0.0",
"@npmcli/run-script": "^9.0.0",
"cacache": "^19.0.0",
"fs-minipass": "^3.0.0",
"minipass": "^7.0.2",
"npm-package-arg": "^12.0.0",
"npm-packlist": "^9.0.0",
"npm-pick-manifest": "^10.0.0",
"npm-registry-fetch": "^18.0.0",
"proc-log": "^5.0.0",
"promise-retry": "^2.0.1",
"sigstore": "^3.0.0",
"ssri": "^12.0.0",
"tar": "^6.1.11"
},
"bin": {
"pacote": "bin/index.js"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/parse-conflict-json": {
"version": "4.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"json-parse-even-better-errors": "^4.0.0",
"just-diff": "^6.0.0",
"just-diff-apply": "^5.2.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/path-key": {
"version": "3.1.1",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/path-scurry": {
"version": "1.11.1",
"inBundle": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/postcss-selector-parser": {
"version": "6.1.2",
"inBundle": true,
"license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
},
"engines": {
"node": ">=4"
}
},
"node_modules/npm/node_modules/proc-log": {
"version": "5.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/proggy": {
"version": "3.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/promise-all-reject-late": {
"version": "1.0.1",
"inBundle": true,
"license": "ISC",
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/promise-call-limit": {
"version": "3.0.2",
"inBundle": true,
"license": "ISC",
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/promise-inflight": {
"version": "1.0.1",
"inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/promise-retry": {
"version": "2.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"err-code": "^2.0.2",
"retry": "^0.12.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/npm/node_modules/promzard": {
"version": "2.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"read": "^4.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/qrcode-terminal": {
"version": "0.12.0",
"inBundle": true,
"bin": {
"qrcode-terminal": "bin/qrcode-terminal.js"
}
},
"node_modules/npm/node_modules/read": {
"version": "4.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"mute-stream": "^2.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/read-cmd-shim": {
"version": "5.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/read-package-json-fast": {
"version": "4.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"json-parse-even-better-errors": "^4.0.0",
"npm-normalize-package-bin": "^4.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/retry": {
"version": "0.12.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/npm/node_modules/rimraf": {
"version": "5.0.10",
"inBundle": true,
"license": "ISC",
"dependencies": {
"glob": "^10.3.7"
},
"bin": {
"rimraf": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/safer-buffer": {
"version": "2.1.2",
"inBundle": true,
"license": "MIT",
"optional": true
},
"node_modules/npm/node_modules/semver": {
"version": "7.6.3",
"inBundle": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/npm/node_modules/shebang-command": {
"version": "2.0.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/shebang-regex": {
"version": "3.0.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/signal-exit": {
"version": "4.1.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/sigstore": {
"version": "3.0.0",
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
"@sigstore/bundle": "^3.0.0",
"@sigstore/core": "^2.0.0",
"@sigstore/protobuf-specs": "^0.3.2",
"@sigstore/sign": "^3.0.0",
"@sigstore/tuf": "^3.0.0",
"@sigstore/verify": "^2.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/sigstore/node_modules/@sigstore/bundle": {
"version": "3.0.0",
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
"@sigstore/protobuf-specs": "^0.3.2"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/sigstore/node_modules/@sigstore/core": {
"version": "2.0.0",
"inBundle": true,
"license": "Apache-2.0",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/sigstore/node_modules/@sigstore/sign": {
"version": "3.0.0",
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
"@sigstore/bundle": "^3.0.0",
"@sigstore/core": "^2.0.0",
"@sigstore/protobuf-specs": "^0.3.2",
"make-fetch-happen": "^14.0.1",
"proc-log": "^5.0.0",
"promise-retry": "^2.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/sigstore/node_modules/@sigstore/verify": {
"version": "2.0.0",
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
"@sigstore/bundle": "^3.0.0",
"@sigstore/core": "^2.0.0",
"@sigstore/protobuf-specs": "^0.3.2"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/smart-buffer": {
"version": "4.2.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/npm/node_modules/socks": {
"version": "2.8.3",
"inBundle": true,
"license": "MIT",
"dependencies": {
"ip-address": "^9.0.5",
"smart-buffer": "^4.2.0"
},
"engines": {
"node": ">= 10.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/npm/node_modules/socks-proxy-agent": {
"version": "8.0.4",
"inBundle": true,
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.1",
"debug": "^4.3.4",
"socks": "^2.8.3"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/npm/node_modules/spdx-correct": {
"version": "3.2.0",
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
"spdx-expression-parse": "^3.0.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": {
"version": "3.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/npm/node_modules/spdx-exceptions": {
"version": "2.5.0",
"inBundle": true,
"license": "CC-BY-3.0"
},
"node_modules/npm/node_modules/spdx-expression-parse": {
"version": "4.0.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/npm/node_modules/spdx-license-ids": {
"version": "3.0.20",
"inBundle": true,
"license": "CC0-1.0"
},
"node_modules/npm/node_modules/sprintf-js": {
"version": "1.1.3",
"inBundle": true,
"license": "BSD-3-Clause"
},
"node_modules/npm/node_modules/ssri": {
"version": "12.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"minipass": "^7.0.3"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/string-width": {
"version": "4.2.3",
"inBundle": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/string-width-cjs": {
"name": "string-width",
"version": "4.2.3",
"inBundle": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/strip-ansi": {
"version": "6.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/supports-color": {
"version": "9.4.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/npm/node_modules/tar": {
"version": "6.2.1",
"inBundle": true,
"license": "ISC",
"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/npm/node_modules/tar/node_modules/fs-minipass": {
"version": "2.1.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": {
"version": "3.3.6",
"inBundle": true,
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/tar/node_modules/minipass": {
"version": "5.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": ">=8"
}
},
"node_modules/npm/node_modules/text-table": {
"version": "0.2.0",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/tiny-relative-date": {
"version": "1.3.0",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/treeverse": {
"version": "3.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/tuf-js": {
"version": "3.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"@tufjs/models": "3.0.1",
"debug": "^4.3.6",
"make-fetch-happen": "^14.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/tuf-js/node_modules/@tufjs/models": {
"version": "3.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"@tufjs/canonical-json": "2.0.0",
"minimatch": "^9.0.5"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/unique-filename": {
"version": "4.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"unique-slug": "^5.0.0"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/unique-slug": {
"version": "5.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"imurmurhash": "^0.1.4"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/util-deprecate": {
"version": "1.0.2",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/validate-npm-package-license": {
"version": "3.0.4",
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
"spdx-correct": "^3.0.0",
"spdx-expression-parse": "^3.0.0"
}
},
"node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": {
"version": "3.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/npm/node_modules/validate-npm-package-name": {
"version": "6.0.0",
"inBundle": true,
"license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/walk-up-path": {
"version": "3.0.1",
"inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/which": {
"version": "5.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"isexe": "^3.1.1"
},
"bin": {
"node-which": "bin/which.js"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/which/node_modules/isexe": {
"version": "3.1.1",
"inBundle": true,
"license": "ISC",
"engines": {
"node": ">=16"
}
},
"node_modules/npm/node_modules/wrap-ansi": {
"version": "8.1.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/npm/node_modules/wrap-ansi-cjs": {
"name": "wrap-ansi",
"version": "7.0.0",
"inBundle": true,
"license": "MIT",
"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/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
"version": "4.3.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": {
"version": "6.1.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": {
"version": "9.2.2",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": {
"version": "5.1.2",
"inBundle": true,
"license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": {
"version": "7.1.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/npm/node_modules/write-file-atomic": {
"version": "6.0.0",
"inBundle": true,
"license": "ISC",
"dependencies": {
"imurmurhash": "^0.1.4",
"signal-exit": "^4.0.1"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/npm/node_modules/yallist": {
"version": "4.0.0",
"inBundle": true,
"license": "ISC"
},
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
@@ -16624,9 +18489,9 @@
}
},
"node_modules/nwsapi": {
"version": "2.2.20",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz",
"integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==",
"version": "2.2.19",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.19.tgz",
"integrity": "sha512-94bcyI3RsqiZufXjkr3ltkI86iEl+I7uiHVDtcq9wJUTwYQJ5odHDeSzkkrRzi80jJ8MaeZgqKjH1bAWAFw9bA==",
"license": "MIT"
},
"node_modules/object-assign": {
@@ -16662,22 +18527,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-is": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1"
},
"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",
@@ -16808,9 +18657,9 @@
}
},
"node_modules/on-headers": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
"integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
"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==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -17005,12 +18854,6 @@
"node": ">=6"
}
},
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"license": "BlueOak-1.0.0"
},
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
@@ -17088,74 +18931,6 @@
"tslib": "^2.0.3"
}
},
"node_modules/patch-package": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz",
"integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==",
"license": "MIT",
"dependencies": {
"@yarnpkg/lockfile": "^1.1.0",
"chalk": "^4.1.2",
"ci-info": "^3.7.0",
"cross-spawn": "^7.0.3",
"find-yarn-workspace-root": "^2.0.0",
"fs-extra": "^9.0.0",
"json-stable-stringify": "^1.0.2",
"klaw-sync": "^6.0.0",
"minimist": "^1.2.6",
"open": "^7.4.2",
"rimraf": "^2.6.3",
"semver": "^7.5.3",
"slash": "^2.0.0",
"tmp": "^0.0.33",
"yaml": "^2.2.2"
},
"bin": {
"patch-package": "index.js"
},
"engines": {
"node": ">=14",
"npm": ">5"
}
},
"node_modules/patch-package/node_modules/open": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
"integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
"license": "MIT",
"dependencies": {
"is-docker": "^2.0.0",
"is-wsl": "^2.1.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/patch-package/node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/path": {
"version": "0.12.7",
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
"integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==",
"license": "MIT",
"dependencies": {
"process": "^0.11.1",
"util": "^0.10.3"
}
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -17195,28 +18970,6 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"license": "MIT"
},
"node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
},
"node_modules/path-to-regexp": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
@@ -17232,27 +18985,6 @@
"node": ">=8"
}
},
"node_modules/path-unified": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/path-unified/-/path-unified-0.2.0.tgz",
"integrity": "sha512-MNKqvrKbbbb5p7XHXV6ZAsf/1f/yJQa13S/fcX0uua8ew58Tgc6jXV+16JyAbnR/clgCH+euKDxrF2STxMHdrg==",
"license": "MIT"
},
"node_modules/path/node_modules/inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
"license": "ISC"
},
"node_modules/path/node_modules/util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
"license": "MIT",
"dependencies": {
"inherits": "2.0.3"
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -17545,24 +19277,6 @@
"postcss": "^8.2.2"
}
},
"node_modules/postcss-calc-ast-parser": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/postcss-calc-ast-parser/-/postcss-calc-ast-parser-0.1.4.tgz",
"integrity": "sha512-CebpbHc96zgFjGgdQ6BqBy6XIUgRx1xXWCAAk6oke02RZ5nxwo9KQejTg8y7uYEeI9kv8jKQPYjoe6REsY23vw==",
"license": "MIT",
"dependencies": {
"postcss-value-parser": "^3.3.1"
},
"engines": {
"node": ">=6.5"
}
},
"node_modules/postcss-calc-ast-parser/node_modules/postcss-value-parser": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
"license": "MIT"
},
"node_modules/postcss-colormin": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz",
@@ -17581,21 +19295,6 @@
"postcss": "^8.4.31"
}
},
"node_modules/postcss-combine-duplicated-selectors": {
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/postcss-combine-duplicated-selectors/-/postcss-combine-duplicated-selectors-10.0.3.tgz",
"integrity": "sha512-IP0BmwFloCskv7DV7xqvzDXqMHpwdczJa6ZvIW8abgHdcIHs9mCJX2ltFhu3EwA51ozp13DByng30+Ke+eIExA==",
"license": "MIT",
"dependencies": {
"postcss-selector-parser": "^6.0.4"
},
"engines": {
"node": "^10.0.0 || ^12.0.0 || >=14.0.0"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/postcss-convert-values": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz",
@@ -17688,23 +19387,6 @@
"postcss": "^8.4.31"
}
},
"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==",
"license": "MIT",
"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/postcss-loader": {
"version": "7.3.4",
"resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz",
@@ -17739,52 +19421,6 @@
"node": ">=10"
}
},
"node_modules/postcss-map": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/postcss-map/-/postcss-map-0.11.0.tgz",
"integrity": "sha512-cgHYZrH9aAMds90upYUPhYz8xnAcRD45SwuNns/nQHONIrPQDhpwk3JLsAQGOndQxnRVXfB6nB+3WqSMy8fqlA==",
"license": "Unlicense",
"dependencies": {
"js-yaml": "^3.12.0",
"postcss": "^7.0.2",
"reduce-function-call": "^1.0.1"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/postcss-map/node_modules/picocolors": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
"integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
"license": "ISC"
},
"node_modules/postcss-map/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==",
"license": "MIT",
"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/postcss-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==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postcss-media-query-parser": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
@@ -17826,19 +19462,6 @@
"postcss": "^8.4.31"
}
},
"node_modules/postcss-minify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/postcss-minify/-/postcss-minify-1.1.0.tgz",
"integrity": "sha512-9D64ueIW0DL2FdLajQTlXrnTN8Ox9NjuXqigKMmB819RhdClNPYx5Zp3i5x0ghjjy3vGrLBBYEYvJjY/1eMNbw==",
"license": "MIT",
"dependencies": {
"postcss-selector-parser": "^6.0",
"postcss-value-parser": "^4.1"
},
"peerDependencies": {
"postcss": "^8.0"
}
},
"node_modules/postcss-minify-font-values": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz",
@@ -18311,9 +19934,9 @@
}
},
"node_modules/prebuild-install/node_modules/detect-libc": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"license": "Apache-2.0",
"engines": {
"node": ">=8"
@@ -18334,9 +19957,9 @@
}
},
"node_modules/prebuild-install/node_modules/tar-fs": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz",
"integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==",
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz",
"integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==",
"license": "MIT",
"dependencies": {
"chownr": "^1.1.1",
@@ -18370,21 +19993,6 @@
"node": ">= 0.8.0"
}
},
"node_modules/prettier": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/pretty-error": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
@@ -18401,7 +20009,6 @@
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
@@ -18417,7 +20024,6 @@
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=10"
},
@@ -18430,17 +20036,7 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true,
"license": "MIT",
"peer": true
},
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"license": "MIT",
"engines": {
"node": ">= 0.6.0"
}
"license": "MIT"
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
@@ -18579,9 +20175,9 @@
}
},
"node_modules/purgecss/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -19181,9 +20777,9 @@
}
},
"node_modules/react-onclickoutside": {
"version": "6.13.2",
"resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.2.tgz",
"integrity": "sha512-h6Hbf1c8b7tIYY4u90mDdBLY4+AGQVMFtIE89HgC0DtVCh/JfKl477gYqUtGLmjZBKK3MJxomP/lFiLbz4sq9A==",
"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==",
"license": "MIT",
"funding": {
"type": "individual",
@@ -19347,12 +20943,12 @@
}
},
"node_modules/react-router": {
"version": "6.30.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz",
"integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==",
"version": "6.27.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz",
"integrity": "sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.23.0"
"@remix-run/router": "1.20.0"
},
"engines": {
"node": ">=14.0.0"
@@ -19362,13 +20958,13 @@
}
},
"node_modules/react-router-dom": {
"version": "6.30.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz",
"integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==",
"version": "6.27.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.27.0.tgz",
"integrity": "sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.23.0",
"react-router": "6.30.1"
"@remix-run/router": "1.20.0",
"react-router": "6.27.0"
},
"engines": {
"node": ">=14.0.0"
@@ -19379,9 +20975,9 @@
}
},
"node_modules/react-select": {
"version": "5.10.2",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.2.tgz",
"integrity": "sha512-Z33nHdEFWq9tfnfVXaiM12rbJmk+QjFEztWLtmXqQhz6Al4UZZ9xc0wiatmGtUOCCnHN0WizL3tCMYRENX4rVQ==",
"version": "5.8.0",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.0.tgz",
"integrity": "sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.0",
@@ -19392,11 +20988,11 @@
"memoize-one": "^6.0.0",
"prop-types": "^15.6.0",
"react-transition-group": "^4.3.0",
"use-isomorphic-layout-effect": "^1.2.0"
"use-isomorphic-layout-effect": "^1.1.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.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-shallow-renderer": {
@@ -19480,9 +21076,9 @@
"license": "MIT"
},
"node_modules/react-textarea-autosize": {
"version": "8.5.9",
"resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz",
"integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==",
"version": "8.5.8",
"resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.8.tgz",
"integrity": "sha512-iUiIj70JefrTuSJ4LbVFiSqWiHHss5L63L717bqaWHMgkm9sz6eEvro4vZ3uQfGJbevzwT6rHOszHKA8RkhRMg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.20.13",
@@ -19512,24 +21108,6 @@
"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==",
"license": "MIT",
"dependencies": {
"pify": "^2.3.0"
}
},
"node_modules/read-cache/node_modules/pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/read-pkg": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz",
@@ -19719,22 +21297,14 @@
"node": ">=8"
}
},
"node_modules/reduce-function-call": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.3.tgz",
"integrity": "sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"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==",
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz",
"integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.9.2"
"loose-envify": "^1.4.0",
"symbol-observable": "^1.2.0"
}
},
"node_modules/redux-logger": {
@@ -20339,9 +21909,9 @@
}
},
"node_modules/schema-utils": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz",
"integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
"integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
"license": "MIT",
"dependencies": {
"@types/json-schema": "^7.0.9",
@@ -20669,9 +22239,9 @@
}
},
"node_modules/sharp/node_modules/detect-libc": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"license": "Apache-2.0",
"engines": {
"node": ">=8"
@@ -20899,6 +22469,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
"integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
@@ -21145,6 +22716,16 @@
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
"license": "MIT"
},
"node_modules/start": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/start/-/start-5.1.0.tgz",
"integrity": "sha512-lirwWQmvBC65bnxU3HzKx5m7vfZJZTx/FrKyPWbtobcvujGbinQQRrNodtcgkp4mTZ00umzDeg7lraN351l0aA==",
"deprecated": "Deprecated in favor of https://github.com/deepsweet/start",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
@@ -21154,15 +22735,6 @@
"node": ">= 0.8"
}
},
"node_modules/stream": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/stream/-/stream-0.0.3.tgz",
"integrity": "sha512-aMsbn7VKrl4A2T7QAQQbzgN7NVc70vgF5INQrBXqn4dCXN1zy3L9HGgLO5s7PExmdrzTJ8uR/27aviW8or8/+A==",
"license": "MIT",
"dependencies": {
"component-emitter": "^2.0.0"
}
},
"node_modules/streamx": {
"version": "2.22.0",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz",
@@ -21227,27 +22799,6 @@
"node": ">=8"
}
},
"node_modules/string-width-cjs": {
"name": "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==",
"license": "MIT",
"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-cjs/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==",
"license": "MIT"
},
"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",
@@ -21349,19 +22900,6 @@
"node": ">=8"
}
},
"node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"license": "MIT",
"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",
@@ -21417,55 +22955,6 @@
],
"license": "MIT"
},
"node_modules/style-dictionary": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/style-dictionary/-/style-dictionary-4.4.0.tgz",
"integrity": "sha512-+xU0IA1StzqAqFs/QtXkK+XJa7wpS4X5H+JQccRKsRCElgeLGocFU1U/UMvMUylKFw6vwGV+Y/a2wb2pm5rFFQ==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@bundled-es-modules/deepmerge": "^4.3.1",
"@bundled-es-modules/glob": "^10.4.2",
"@bundled-es-modules/memfs": "^4.9.4",
"@zip.js/zip.js": "^2.7.44",
"chalk": "^5.3.0",
"change-case": "^5.3.0",
"commander": "^12.1.0",
"is-plain-obj": "^4.1.0",
"json5": "^2.2.2",
"patch-package": "^8.0.0",
"path-unified": "^0.2.0",
"prettier": "^3.3.3",
"tinycolor2": "^1.6.0"
},
"bin": {
"style-dictionary": "bin/style-dictionary.js"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/style-dictionary/node_modules/chalk": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
"integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
"license": "MIT",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/style-dictionary/node_modules/commander": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/style-loader": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz",
@@ -21703,15 +23192,6 @@
"node": ">=14.18.0"
}
},
"node_modules/superagent/node_modules/component-emitter": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
"integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/superagent/node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
@@ -21870,6 +23350,15 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/symbol-observable": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/symbol-tree": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
@@ -21934,9 +23423,9 @@
}
},
"node_modules/tar-fs": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz",
"integrity": "sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==",
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz",
"integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==",
"license": "MIT",
"dependencies": {
"pump": "^3.0.0",
@@ -22093,18 +23582,6 @@
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"license": "MIT"
},
"node_modules/thingies": {
"version": "1.21.0",
"resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz",
"integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==",
"license": "Unlicense",
"engines": {
"node": ">=10.18"
},
"peerDependencies": {
"tslib": "^2"
}
},
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@@ -22129,19 +23606,13 @@
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
"license": "MIT"
},
"node_modules/tinycolor2": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
"integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
"license": "MIT"
},
"node_modules/tinyglobby": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
"version": "0.2.12",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz",
"integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==",
"license": "MIT",
"dependencies": {
"fdir": "^6.4.4",
"fdir": "^6.4.3",
"picomatch": "^4.0.2"
},
"engines": {
@@ -22152,9 +23623,9 @@
}
},
"node_modules/tinyglobby/node_modules/fdir": {
"version": "6.4.4",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
"version": "6.4.3",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz",
"integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==",
"license": "MIT",
"peerDependencies": {
"picomatch": "^3 || ^4"
@@ -22271,22 +23742,6 @@
"punycode": "^2.1.0"
}
},
"node_modules/tree-dump": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz",
"integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==",
"license": "Apache-2.0",
"engines": {
"node": ">=10.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/streamich"
},
"peerDependencies": {
"tslib": "2"
}
},
"node_modules/trim-newlines": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz",
@@ -22313,9 +23768,9 @@
}
},
"node_modules/ts-jest": {
"version": "29.3.2",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.2.tgz",
"integrity": "sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug==",
"version": "29.3.0",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.0.tgz",
"integrity": "sha512-4bfGBX7Gd1Aqz3SyeDS9O276wEU/BInZxskPrbhZLyv+c1wskDCqDFMJQJLWrIr/fKoAH4GE5dKUlrdyvo+39A==",
"license": "MIT",
"dependencies": {
"bs-logger": "^0.2.6",
@@ -22326,7 +23781,7 @@
"lodash.memoize": "^4.1.2",
"make-error": "^1.3.6",
"semver": "^7.7.1",
"type-fest": "^4.39.1",
"type-fest": "^4.37.0",
"yargs-parser": "^21.1.1"
},
"bin": {
@@ -22374,9 +23829,9 @@
}
},
"node_modules/ts-jest/node_modules/type-fest": {
"version": "4.40.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.1.tgz",
"integrity": "sha512-9YvLNnORDpI+vghLU/Nf+zSv0kL47KbVJ1o3sKgoTefl6i+zebxbiDQWoe/oWWqPhIgQdRZRT1KA9sCPL810SA==",
"version": "4.38.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.38.0.tgz",
"integrity": "sha512-2dBz5D5ycHIoliLYLi0Q2V7KRaDlH0uWIvmk7TYlAg5slqwiPv1ezJdZm1QEM0xgk29oYWMCbIG7E6gHpvChlg==",
"license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=16"
@@ -22693,9 +24148,9 @@
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
"license": "MIT"
},
"node_modules/unicode-canonical-property-names-ecmascript": {
@@ -22708,14 +24163,20 @@
}
},
"node_modules/unicode-emoji-utils": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/unicode-emoji-utils/-/unicode-emoji-utils-1.3.1.tgz",
"integrity": "sha512-6PiQxmnlsOsqzZCZz0sykSyMy/r1HiJiOWWXV98+BDva583DU4CtBeyDNsi4wMYUIbjUtMs4RgAuyft0EKLoVw==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/unicode-emoji-utils/-/unicode-emoji-utils-1.2.0.tgz",
"integrity": "sha512-djUB91p/6oYpgps4W5K/MAvM+UspoAANHSUW495BrxeLRoned3iNPEDQgrKx9LbLq93VhNz0NWvI61vcfrwYoA==",
"license": "MIT",
"dependencies": {
"emoji-regex-xs": "^2.0.0"
"emoji-regex": "10.3.0"
}
},
"node_modules/unicode-emoji-utils/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==",
"license": "MIT"
},
"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",
@@ -22785,35 +24246,29 @@
}
},
"node_modules/unrs-resolver": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.2.tgz",
"integrity": "sha512-BBKpaylOW8KbHsu378Zky/dGh4ckT/4NW/0SHRABdqRLcQJ2dAOjDo9g97p04sWflm0kqPqpUatxReNV/dqI5A==",
"hasInstallScript": true,
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.3.2.tgz",
"integrity": "sha512-ZKQBC351Ubw0PY8xWhneIfb6dygTQeUHtCcNGd0QB618zabD/WbFMYdRyJ7xeVT+6G82K5v/oyZO0QSHFtbIuw==",
"license": "MIT",
"dependencies": {
"napi-postinstall": "^0.2.2"
},
"funding": {
"url": "https://github.com/sponsors/JounQin"
},
"optionalDependencies": {
"@unrs/resolver-binding-darwin-arm64": "1.7.2",
"@unrs/resolver-binding-darwin-x64": "1.7.2",
"@unrs/resolver-binding-freebsd-x64": "1.7.2",
"@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.2",
"@unrs/resolver-binding-linux-arm-musleabihf": "1.7.2",
"@unrs/resolver-binding-linux-arm64-gnu": "1.7.2",
"@unrs/resolver-binding-linux-arm64-musl": "1.7.2",
"@unrs/resolver-binding-linux-ppc64-gnu": "1.7.2",
"@unrs/resolver-binding-linux-riscv64-gnu": "1.7.2",
"@unrs/resolver-binding-linux-riscv64-musl": "1.7.2",
"@unrs/resolver-binding-linux-s390x-gnu": "1.7.2",
"@unrs/resolver-binding-linux-x64-gnu": "1.7.2",
"@unrs/resolver-binding-linux-x64-musl": "1.7.2",
"@unrs/resolver-binding-wasm32-wasi": "1.7.2",
"@unrs/resolver-binding-win32-arm64-msvc": "1.7.2",
"@unrs/resolver-binding-win32-ia32-msvc": "1.7.2",
"@unrs/resolver-binding-win32-x64-msvc": "1.7.2"
"@unrs/resolver-binding-darwin-arm64": "1.3.2",
"@unrs/resolver-binding-darwin-x64": "1.3.2",
"@unrs/resolver-binding-freebsd-x64": "1.3.2",
"@unrs/resolver-binding-linux-arm-gnueabihf": "1.3.2",
"@unrs/resolver-binding-linux-arm-musleabihf": "1.3.2",
"@unrs/resolver-binding-linux-arm64-gnu": "1.3.2",
"@unrs/resolver-binding-linux-arm64-musl": "1.3.2",
"@unrs/resolver-binding-linux-ppc64-gnu": "1.3.2",
"@unrs/resolver-binding-linux-s390x-gnu": "1.3.2",
"@unrs/resolver-binding-linux-x64-gnu": "1.3.2",
"@unrs/resolver-binding-linux-x64-musl": "1.3.2",
"@unrs/resolver-binding-wasm32-wasi": "1.3.2",
"@unrs/resolver-binding-win32-arm64-msvc": "1.3.2",
"@unrs/resolver-binding-win32-ia32-msvc": "1.3.2",
"@unrs/resolver-binding-win32-x64-msvc": "1.3.2"
}
},
"node_modules/update-browserslist-db": {
@@ -22855,19 +24310,6 @@
"punycode": "^2.1.0"
}
},
"node_modules/url": {
"version": "0.11.4",
"resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz",
"integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==",
"license": "MIT",
"dependencies": {
"punycode": "^1.4.1",
"qs": "^6.12.3"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/url-loader": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz",
@@ -22923,12 +24365,6 @@
"requires-port": "^1.0.0"
}
},
"node_modules/url/node_modules/punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==",
"license": "MIT"
},
"node_modules/use-callback-ref": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
@@ -23018,27 +24454,14 @@
}
},
"node_modules/use-sync-external-store": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
"integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz",
"integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/util": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"is-typed-array": "^1.1.3",
"which-typed-array": "^1.1.2"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -23061,16 +24484,13 @@
}
},
"node_modules/uuid": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"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.",
"license": "MIT",
"bin": {
"uuid": "dist/esm/bin/uuid"
"uuid": "bin/uuid"
}
},
"node_modules/v8-to-istanbul": {
@@ -23190,14 +24610,13 @@
}
},
"node_modules/webpack": {
"version": "5.99.7",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.7.tgz",
"integrity": "sha512-CNqKBRMQjwcmKR0idID5va1qlhrqVUKpovi+Ec79ksW8ux7iS1+A6VqzfZXgVYCFRKl7XL5ap3ZoMpwBJxcg0w==",
"version": "5.98.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz",
"integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==",
"license": "MIT",
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.6",
"@types/json-schema": "^7.0.15",
"@webassemblyjs/ast": "^1.14.1",
"@webassemblyjs/wasm-edit": "^1.14.1",
"@webassemblyjs/wasm-parser": "^1.14.1",
@@ -23214,7 +24633,7 @@
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
"schema-utils": "^4.3.2",
"schema-utils": "^4.3.0",
"tapable": "^2.1.1",
"terser-webpack-plugin": "^5.3.11",
"watchpack": "^2.4.1",
@@ -23749,24 +25168,6 @@
"node": ">=8"
}
},
"node_modules/wrap-ansi-cjs": {
"name": "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==",
"license": "MIT",
"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",
@@ -23831,15 +25232,6 @@
"node": ">=0.10.0"
}
},
"node_modules/xregexp": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.2.tgz",
"integrity": "sha512-6hGgEMCGhqCTFEJbqmWrNIPqfpdirdGWkqshu7fFZddmTSfgv5Sn9D2SaKloR79s5VUiUlpwzg3CM3G6D3VIlw==",
"license": "MIT",
"dependencies": {
"@babel/runtime-corejs3": "^7.26.9"
}
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@@ -23856,15 +25248,12 @@
"license": "ISC"
},
"node_modules/yaml": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz",
"integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==",
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14"
"node": ">= 6"
}
},
"node_modules/yargs": {
@@ -23907,16 +25296,14 @@
}
},
"node_modules/yup": {
"version": "0.32.11",
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
"integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
"version": "0.31.1",
"resolved": "https://registry.npmjs.org/yup/-/yup-0.31.1.tgz",
"integrity": "sha512-Lf6648jDYOWR75IlWkVfwesPyW6oj+50NpxlKvsQlpPsB8eI+ndI7b4S1VrwbmeV9hIZDu1MzrlIL4W+gK1jPw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.15.4",
"@types/lodash": "^4.14.175",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"nanoclone": "^0.2.1",
"@babel/runtime": "^7.10.5",
"lodash": "^4.17.20",
"lodash-es": "^4.17.11",
"property-expr": "^2.0.4",
"toposort": "^2.0.2"
},

View File

@@ -11,10 +11,11 @@
],
"scripts": {
"build": "fedx-scripts webpack",
"i18n_extract": "fedx-scripts formatjs extract --include=plugins",
"i18n_extract": "fedx-scripts formatjs extract",
"stylelint": "stylelint \"plugins/**/*.scss\" \"src/**/*.scss\" \"scss/**/*.scss\" --config .stylelintrc.json",
"lint": "npm run stylelint && fedx-scripts eslint --ext .js --ext .jsx --ext .ts --ext .tsx .",
"lint:fix": "npm run stylelint -- --fix && fedx-scripts eslint --fix --ext .js --ext .jsx --ext .ts --ext .tsx .",
"snapshot": "TZ=UTC fedx-scripts jest --updateSnapshot",
"start": "fedx-scripts webpack-dev-server --progress",
"start:with-theme": "paragon install-theme && npm start && npm install",
"dev": "PUBLIC_PATH=/authoring/ MFE_CONFIG_API_URL='http://localhost:8000/api/mfe_config/v1' fedx-scripts webpack-dev-server --progress --host apps.local.openedx.io",
@@ -33,7 +34,6 @@
},
"dependencies": {
"@codemirror/lang-html": "^6.0.0",
"@codemirror/lang-markdown": "^6.0.0",
"@codemirror/lang-xml": "^6.0.0",
"@codemirror/lint": "^6.2.1",
"@codemirror/state": "^6.0.0",
@@ -43,12 +43,12 @@
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.3",
"@edx/browserslist-config": "1.5.0",
"@edx/frontend-component-footer": "^14.9.0",
"@edx/browserslist-config": "1.2.0",
"@edx/frontend-component-footer": "^14.3.0",
"@edx/frontend-component-header": "^6.2.0",
"@edx/frontend-enterprise-hotjar": "^7.2.0",
"@edx/frontend-platform": "^8.4.0",
"@edx/openedx-atlas": "^0.7.0",
"@edx/frontend-platform": "^8.3.1",
"@edx/openedx-atlas": "^0.6.0",
"@openedx-plugins/course-app-calculator": "file:plugins/course-apps/calculator",
"@openedx-plugins/course-app-edxnotes": "file:plugins/course-apps/edxnotes",
"@openedx-plugins/course-app-learning_assistant": "file:plugins/course-apps/learning_assistant",
@@ -59,12 +59,13 @@
"@openedx-plugins/course-app-teams": "file:plugins/course-apps/teams",
"@openedx-plugins/course-app-wiki": "file:plugins/course-apps/wiki",
"@openedx-plugins/course-app-xpert_unit_summary": "file:plugins/course-apps/xpert_unit_summary",
"@openedx/frontend-build": "^14.5.0",
"@openedx/frontend-plugin-framework": "^1.7.0",
"@openedx/paragon": "^23.5.0",
"@openedx/frontend-build": "^14.3.3",
"@openedx/frontend-plugin-framework": "^1.6.0",
"@openedx/frontend-slot-footer": "^1.2.0",
"@openedx/paragon": "^22.16.0",
"@redux-devtools/extension": "^3.3.0",
"@reduxjs/toolkit": "1.9.7",
"@tanstack/react-query": "4.40.1",
"@tanstack/react-query": "4.36.1",
"@tinymce/tinymce-react": "^3.14.0",
"classnames": "2.5.1",
"codemirror": "^6.0.0",
@@ -78,6 +79,7 @@
"meilisearch": "^0.41.0",
"moment": "2.30.1",
"moment-shortformat": "^2.1.0",
"npm": "^10.8.1",
"prop-types": "^15.8.1",
"react": "^18.3.1",
"react-datepicker": "^4.13.0",
@@ -87,31 +89,31 @@
"react-onclickoutside": "^6.13.0",
"react-redux": "7.2.9",
"react-responsive": "9.0.2",
"react-router": "6.30.1",
"react-router-dom": "6.30.1",
"react-select": "5.10.2",
"react-router": "6.27.0",
"react-router-dom": "6.27.0",
"react-select": "5.8.0",
"react-textarea-autosize": "^8.5.3",
"react-transition-group": "4.4.5",
"redux": "4.2.1",
"redux": "4.0.5",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.4.1",
"reselect": "^4.1.5",
"start": "^5.1.0",
"tinymce": "^5.10.4",
"universal-cookie": "^4.0.4",
"uuid": "^11.1.0",
"uuid": "^3.4.0",
"xmlchecker": "^0.1.0",
"yup": "0.32.11"
"yup": "0.31.1"
},
"devDependencies": {
"@edx/react-unit-test-utils": "^4.0.0",
"@edx/stylelint-config-edx": "2.3.3",
"@edx/typescript-config": "^1.0.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.1",
"@types/lodash": "^4.17.17",
"@types/react": "^18",
"@types/react-dom": "^18",
"axios-mock-adapter": "2.1.0",
"@testing-library/user-event": "^13.2.1",
"@types/lodash": "^4.17.7",
"axios-mock-adapter": "1.22.0",
"eslint-import-resolver-webpack": "^0.13.8",
"fetch-mock-jest": "^1.5.1",
"jest-canvas-mock": "^2.5.2",

View File

@@ -2,12 +2,16 @@ import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import { RequestStatus } from 'CourseAuthoring/data/constants';
import { initializeMocks, render } from 'CourseAuthoring/testUtils';
import { render } from 'CourseAuthoring/pages-and-resources/utils.test';
import LearningAssistantSettings from './Settings';
const onClose = () => { };
describe('Learning Assistant Settings', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('renders', async () => {
const initialState = {
models: {
@@ -34,8 +38,14 @@ describe('Learning Assistant Settings', () => {
},
};
initializeMocks({ initialState });
render(<LearningAssistantSettings onClose={onClose} />);
render(
<LearningAssistantSettings
onClose={onClose}
/>,
{
preloadedState: initialState,
},
);
const toggleDescription = 'Reinforce learning concepts by sharing text-based course content '
+ 'with OpenAI (via API) to power an in-course Learning Assistant. Learners can leave feedback about the quality '

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import { getConfig } from '@edx/frontend-platform';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Form, Hyperlink } from '@openedx/paragon';
import PropTypes from 'prop-types';
import AppConfigFormDivider from 'CourseAuthoring/pages-and-resources/discussions/app-config-form/apps/shared/AppConfigFormDivider';
@@ -11,10 +11,10 @@ import LiveCommonFields from './LiveCommonFields';
import messages from './messages';
const BbbSettings = ({
intl,
values,
setFieldValue,
}) => {
const intl = useIntl();
const [bbbPlan, setBbbPlan] = useState(values.tierType);
useEffect(() => {
@@ -107,10 +107,12 @@ const BbbSettings = ({
)}
</>
</>
);
};
BbbSettings.propTypes = {
intl: intlShape.isRequired,
values: PropTypes.shape({
consumerKey: PropTypes.string,
consumerSecret: PropTypes.string,
@@ -125,4 +127,4 @@ BbbSettings.propTypes = {
setFieldValue: PropTypes.func.isRequired,
};
export default BbbSettings;
export default injectIntl(BbbSettings);

View File

@@ -124,13 +124,12 @@ describe('BBB Settings', () => {
);
test('free plans message is visible when free plan is selected', async () => {
const user = userEvent.setup();
await mockStore({ emailSharing: true, isFreeTier: true });
renderComponent();
const spinner = getByRole(container, 'status');
await waitForElementToBeRemoved(spinner);
const dropDown = container.querySelector('select[name="tierType"]');
await user.selectOptions(
userEvent.selectOptions(
dropDown,
getByRole(dropDown, 'option', { name: 'Free' }),
);

View File

@@ -1,43 +1,42 @@
import React from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import FormikControl from 'CourseAuthoring/generic/FormikControl';
import messages from './messages';
const LiveCommonFields = ({
intl,
values,
}) => {
const intl = useIntl();
return (
<>
<p className="pb-2">{intl.formatMessage(messages.formInstructions)}</p>
<FormikControl
name="consumerKey"
value={values.consumerKey}
floatingLabel={intl.formatMessage(messages.consumerKey)}
className="pb-1"
type="input"
/>
<FormikControl
name="consumerSecret"
value={values.consumerSecret}
floatingLabel={intl.formatMessage(messages.consumerSecret)}
className="pb-1"
type="password"
/>
<FormikControl
name="launchUrl"
value={values.launchUrl}
floatingLabel={intl.formatMessage(messages.launchUrl)}
className="pb-1"
type="input"
/>
</>
);
};
}) => (
<>
<p className="pb-2">{intl.formatMessage(messages.formInstructions)}</p>
<FormikControl
name="consumerKey"
value={values.consumerKey}
floatingLabel={intl.formatMessage(messages.consumerKey)}
className="pb-1"
type="input"
/>
<FormikControl
name="consumerSecret"
value={values.consumerSecret}
floatingLabel={intl.formatMessage(messages.consumerSecret)}
className="pb-1"
type="password"
/>
<FormikControl
name="launchUrl"
value={values.launchUrl}
floatingLabel={intl.formatMessage(messages.launchUrl)}
className="pb-1"
type="input"
/>
</>
);
LiveCommonFields.propTypes = {
intl: intlShape.isRequired,
values: PropTypes.shape({
consumerKey: PropTypes.string,
consumerSecret: PropTypes.string,
@@ -46,4 +45,4 @@ LiveCommonFields.propTypes = {
}).isRequired,
};
export default LiveCommonFields;
export default injectIntl(LiveCommonFields);

View File

@@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { camelCase } from 'lodash';
import { Icon } from '@openedx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import * as Yup from 'yup';
import { useNavigate } from 'react-router-dom';
@@ -20,9 +20,9 @@ import ZoomSettings from './ZoomSettings';
import BBBSettings from './BBBSettings';
const LiveSettings = ({
intl,
onClose,
}) => {
const intl = useIntl();
const navigate = useNavigate();
const dispatch = useDispatch();
const courseId = useSelector(state => state.courseDetail.courseId);
@@ -130,7 +130,8 @@ const LiveSettings = ({
};
LiveSettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
export default LiveSettings;
export default injectIntl(LiveSettings);

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import FormikControl from 'CourseAuthoring/generic/FormikControl';
@@ -8,38 +8,37 @@ import { providerNames } from './constants';
import LiveCommonFields from './LiveCommonFields';
const ZoomSettings = ({
intl,
values,
}) => {
const intl = useIntl();
return (
// eslint-disable-next-line react/jsx-no-useless-fragment
<>
{!values.piiSharingEnable ? (
<p data-testid="request-pii-sharing">
{intl.formatMessage(messages.requestPiiSharingEnable, { provider: providerNames[values.provider] })}
</p>
) : (
<>
{(values.piiSharingEmail || values.piiSharingUsername)
&& (
<p data-testid="helper-text">
{intl.formatMessage(messages.providerHelperText, { providerName: providerNames[values.provider] })}
</p>
)}
<LiveCommonFields values={values} />
<FormikControl
name="launchEmail"
value={values.launchEmail}
floatingLabel={intl.formatMessage(messages.launchEmail)}
type="input"
/>
</>
)}
</>
);
};
}) => (
// eslint-disable-next-line react/jsx-no-useless-fragment
<>
{!values.piiSharingEnable ? (
<p data-testid="request-pii-sharing">
{intl.formatMessage(messages.requestPiiSharingEnable, { provider: providerNames[values.provider] })}
</p>
) : (
<>
{(values.piiSharingEmail || values.piiSharingUsername)
&& (
<p data-testid="helper-text">
{intl.formatMessage(messages.providerHelperText, { providerName: providerNames[values.provider] })}
</p>
)}
<LiveCommonFields values={values} />
<FormikControl
name="launchEmail"
value={values.launchEmail}
floatingLabel={intl.formatMessage(messages.launchEmail)}
type="input"
/>
</>
)}
</>
);
ZoomSettings.propTypes = {
intl: intlShape.isRequired,
values: PropTypes.shape({
consumerKey: PropTypes.string,
consumerSecret: PropTypes.string,
@@ -52,4 +51,4 @@ ZoomSettings.propTypes = {
}).isRequired,
};
export default ZoomSettings;
export default injectIntl(ZoomSettings);

View File

@@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
import {
ActionRow, Alert, Badge, Form, Hyperlink, ModalDialog, StatefulButton,
} from '@openedx/paragon';
@@ -25,8 +25,7 @@ import { PagesAndResourcesContext } from 'CourseAuthoring/pages-and-resources/Pa
import messages from './messages';
const ProctoringSettings = ({ onClose }) => {
const intl = useIntl();
const ProctoringSettings = ({ intl, onClose }) => {
const initialFormValues = {
enableProctoredExams: false,
proctoringProvider: false,
@@ -653,9 +652,10 @@ const ProctoringSettings = ({ onClose }) => {
};
ProctoringSettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
ProctoringSettings.defaultProps = {};
export default ProctoringSettings;
export default injectIntl(ProctoringSettings);

View File

@@ -1,4 +1,4 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import React from 'react';
import * as Yup from 'yup';
@@ -8,8 +8,7 @@ import { useAppSetting } from 'CourseAuthoring/utils';
import AppSettingsModal from 'CourseAuthoring/pages-and-resources/app-settings-modal/AppSettingsModal';
import messages from './messages';
const ProgressSettings = ({ onClose }) => {
const intl = useIntl();
const ProgressSettings = ({ intl, onClose }) => {
const [disableProgressGraph, saveSetting] = useAppSetting('disableProgressGraph');
const showProgressGraphSetting = getConfig().ENABLE_PROGRESS_GRAPH_SETTINGS.toString().toLowerCase() === 'true';
@@ -49,7 +48,8 @@ const ProgressSettings = ({ onClose }) => {
};
ProgressSettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
export default ProgressSettings;
export default injectIntl(ProgressSettings);

View File

@@ -1,4 +1,4 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Button, Form, TransitionReplace } from '@openedx/paragon';
import PropTypes from 'prop-types';
import React, { useState } from 'react';
@@ -30,9 +30,8 @@ const TeamTypeNameMessage = {
};
const GroupEditor = ({
group, onDelete, onChange, onBlur, fieldNameCommonBase, errors,
intl, group, onDelete, onChange, onBlur, fieldNameCommonBase, errors,
}) => {
const intl = useIntl();
const [isDeleting, setDeleting] = useState(false);
const [isOpen, setOpen] = useState(group.id === null);
const initiateDeletion = () => setDeleting(true);
@@ -150,6 +149,7 @@ export const groupShape = PropTypes.shape({
});
GroupEditor.propTypes = {
intl: intlShape.isRequired,
fieldNameCommonBase: PropTypes.string.isRequired,
errors: PropTypes.shape({
name: PropTypes.string,
@@ -170,4 +170,4 @@ GroupEditor.defaultProps = {
},
};
export default GroupEditor;
export default injectIntl(GroupEditor);

View File

@@ -1,4 +1,4 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Button, Form } from '@openedx/paragon';
import { Add } from '@openedx/paragon/icons';
@@ -17,9 +17,9 @@ import messages from './messages';
setupYupExtensions();
const TeamSettings = ({
intl,
onClose,
}) => {
const intl = useIntl();
const [teamsConfiguration, saveSettings] = useAppSetting('teamsConfiguration');
const blankNewGroup = {
name: '',
@@ -166,7 +166,8 @@ const TeamSettings = ({
};
TeamSettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
export default TeamSettings;
export default injectIntl(TeamSettings);

View File

@@ -1,4 +1,4 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import React from 'react';
import * as Yup from 'yup';
@@ -8,8 +8,7 @@ import { useAppSetting } from 'CourseAuthoring/utils';
import AppSettingsModal from 'CourseAuthoring/pages-and-resources/app-settings-modal/AppSettingsModal';
import messages from './messages';
const WikiSettings = ({ onClose }) => {
const intl = useIntl();
const WikiSettings = ({ intl, onClose }) => {
const [enablePublicWiki, saveSetting] = useAppSetting('allowPublicWikiAccess');
const handleSettingsSave = (values) => saveSetting(values.enablePublicWiki);
@@ -33,7 +32,7 @@ const WikiSettings = ({ onClose }) => {
label={intl.formatMessage(messages.enablePublicWikiLabel)}
helpText={intl.formatMessage(messages.enablePublicWikiHelp)}
onChange={handleChange}
onBlur={handleBlur}
onBlue={handleBlur}
checked={values.enablePublicWiki}
/>
)
@@ -43,7 +42,8 @@ const WikiSettings = ({ onClose }) => {
};
WikiSettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
export default WikiSettings;
export default injectIntl(WikiSettings);

View File

@@ -1,6 +1,7 @@
import React, { useCallback, useContext, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { PagesAndResourcesContext } from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
import { useNavigate } from 'react-router-dom';
@@ -9,8 +10,7 @@ import messages from './messages';
import { fetchXpertSettings } from './data/thunks';
const XpertUnitSummarySettings = () => {
const intl = useIntl();
const XpertUnitSummarySettings = ({ intl }) => {
const { path: pagesAndResourcesPath, courseId } = useContext(PagesAndResourcesContext);
const dispatch = useDispatch();
const navigate = useNavigate();
@@ -38,4 +38,8 @@ const XpertUnitSummarySettings = () => {
);
};
export default XpertUnitSummarySettings;
XpertUnitSummarySettings.propTypes = {
intl: intlShape.isRequired,
};
export default injectIntl(XpertUnitSummarySettings);

View File

@@ -1,4 +1,4 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import {
ActionRow,
Alert,
@@ -70,40 +70,38 @@ AppSettingsForm.defaultProps = {
};
const SettingsModalBase = ({
title, onClose, variant, isMobile, children, footer,
}) => {
const intl = useIntl();
return (
<ModalDialog
title={title}
isOpen
onClose={onClose}
size="lg"
variant={variant}
hasCloseButton={isMobile}
isFullscreenOnMobile
>
<ModalDialog.Header>
<ModalDialog.Title data-testid="modal-title">
{title}
</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body>
{children}
</ModalDialog.Body>
<ModalDialog.Footer className="p-4">
<ActionRow>
<ModalDialog.CloseButton variant="tertiary">
{intl.formatMessage(messages.cancel)}
</ModalDialog.CloseButton>
{footer}
</ActionRow>
</ModalDialog.Footer>
</ModalDialog>
);
};
intl, title, onClose, variant, isMobile, children, footer,
}) => (
<ModalDialog
title={title}
isOpen
onClose={onClose}
size="lg"
variant={variant}
hasCloseButton={isMobile}
isFullscreenOnMobile
>
<ModalDialog.Header>
<ModalDialog.Title data-testid="modal-title">
{title}
</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body>
{children}
</ModalDialog.Body>
<ModalDialog.Footer className="p-4">
<ActionRow>
<ModalDialog.CloseButton variant="tertiary">
{intl.formatMessage(messages.cancel)}
</ModalDialog.CloseButton>
{footer}
</ActionRow>
</ModalDialog.Footer>
</ModalDialog>
);
SettingsModalBase.propTypes = {
intl: intlShape.isRequired,
title: PropTypes.string.isRequired,
onClose: PropTypes.func.isRequired,
variant: PropTypes.oneOf(['default', 'dark']).isRequired,
@@ -117,11 +115,11 @@ SettingsModalBase.defaultProps = {
};
const ResetUnitsButton = ({
intl,
courseId,
checked,
visible,
}) => {
const intl = useIntl();
const resetStatusRequestStatus = useSelector(getResetStatus);
const dispatch = useDispatch();
@@ -187,6 +185,7 @@ const ResetUnitsButton = ({
};
ResetUnitsButton.propTypes = {
intl: intlShape.isRequired,
courseId: PropTypes.string.isRequired,
checked: PropTypes.oneOf(['true', 'false']).isRequired,
visible: PropTypes.bool,
@@ -197,6 +196,7 @@ ResetUnitsButton.defaultProps = {
};
const SettingsModal = ({
intl,
appId,
title,
children,
@@ -213,7 +213,6 @@ const SettingsModal = ({
allUnitsEnabledText,
noUnitsEnabledText,
}) => {
const intl = useIntl();
const { courseId } = useContext(PagesAndResourcesContext);
const loadingStatus = useSelector(getLoadingStatus);
const updateSettingsRequestStatus = useSelector(getSavingStatus);
@@ -373,6 +372,7 @@ const SettingsModal = ({
>
{allUnitsEnabledText}
<ResetUnitsButton
intl={intl}
courseId={courseId}
checked={formikProps.values.checked}
visible={formikProps.values.checked === 'true'}
@@ -385,6 +385,7 @@ const SettingsModal = ({
>
{noUnitsEnabledText}
<ResetUnitsButton
intl={intl}
courseId={courseId}
checked={formikProps.values.checked}
visible={formikProps.values.checked === 'false'}
@@ -422,6 +423,7 @@ const SettingsModal = ({
};
SettingsModal.propTypes = {
intl: intlShape.isRequired,
title: PropTypes.string.isRequired,
appId: PropTypes.string.isRequired,
children: PropTypes.func,
@@ -448,4 +450,4 @@ SettingsModal.defaultProps = {
enableReinitialize: false,
};
export default SettingsModal;
export default injectIntl(SettingsModal);

View File

@@ -1,4 +1,5 @@
@import "~@openedx/paragon/styles/scss/core/utilities-only";
@import "~@edx/brand/paragon/variables";
@import "~@openedx/paragon/scss/core/utilities-only";
.summary-radio {
display: flex;

View File

@@ -5,9 +5,9 @@ import { useDispatch, useSelector } from 'react-redux';
import {
useLocation,
} from 'react-router-dom';
import { StudioFooterSlot } from '@edx/frontend-component-footer';
import { StudioFooterSlot } from '@openedx/frontend-slot-footer';
import Header from './header';
import { fetchCourseDetail } from './data/thunks';
import { fetchCourseDetail, fetchWaffleFlags } from './data/thunks';
import { useModel } from './generic/model-store';
import NotFoundAlert from './generic/NotFoundAlert';
import PermissionDeniedAlert from './generic/PermissionDeniedAlert';
@@ -21,6 +21,7 @@ const CourseAuthoringPage = ({ courseId, children }) => {
useEffect(() => {
dispatch(fetchCourseDetail(courseId));
dispatch(fetchWaffleFlags(courseId));
}, [courseId]);
useEffect(() => {

View File

@@ -4,7 +4,7 @@ import CourseAuthoringPage from './CourseAuthoringPage';
import PagesAndResources from './pages-and-resources/PagesAndResources';
import { executeThunk } from './utils';
import { fetchCourseApps } from './pages-and-resources/data/thunks';
import { fetchCourseDetail } from './data/thunks';
import { fetchCourseDetail, fetchWaffleFlags } from './data/thunks';
import { getApiWaffleFlagsUrl } from './data/api';
import { initializeMocks, render } from './testUtils';
@@ -26,6 +26,7 @@ beforeEach(async () => {
axiosMock
.onGet(getApiWaffleFlagsUrl(courseId))
.reply(200, {});
await executeThunk(fetchWaffleFlags(courseId), store.dispatch);
});
describe('Editor Pages Load no header', () => {
@@ -101,20 +102,4 @@ describe('Course authoring page', () => {
expect(await wrapper.findByTestId(contentTestId)).toBeInTheDocument();
expect(wrapper.queryByTestId('notFoundAlert')).not.toBeInTheDocument();
});
const mockStoreDenied = async () => {
const studioApiBaseUrl = getConfig().STUDIO_BASE_URL;
const courseAppsApiUrl = `${studioApiBaseUrl}/api/course_apps/v1/apps`;
axiosMock.onGet(
`${courseAppsApiUrl}/${courseId}`,
).reply(403);
await executeThunk(fetchCourseApps(courseId), store.dispatch);
};
test('renders PermissionDeniedAlert when courseAppsApiStatus is DENIED', async () => {
mockPathname = '/editor/';
await mockStoreDenied();
const wrapper = render(<CourseAuthoringPage courseId={courseId} />);
expect(await wrapper.findByTestId('permissionDeniedAlert')).toBeInTheDocument();
});
});

View File

@@ -4,7 +4,7 @@ import {
} from 'react-router-dom';
import { getConfig } from '@edx/frontend-platform';
import { PageWrap } from '@edx/frontend-platform/react';
import { Textbooks } from './textbooks';
import { Textbooks } from 'CourseAuthoring/textbooks';
import CourseAuthoringPage from './CourseAuthoringPage';
import { PagesAndResources } from './pages-and-resources';
import EditorContainer from './editors/EditorContainer';
@@ -17,7 +17,7 @@ import ScheduleAndDetails from './schedule-and-details';
import { GradingSettings } from './grading-settings';
import CourseTeam from './course-team/CourseTeam';
import { CourseUpdates } from './course-updates';
import { CourseUnit, SubsectionUnitRedirect } from './course-unit';
import { CourseUnit } from './course-unit';
import { Certificates } from './certificates';
import CourseExportPage from './export-page/CourseExportPage';
import CourseOptimizerPage from './optimizer-page/CourseOptimizerPage';
@@ -82,10 +82,6 @@ const CourseAuthoringRoutes = () => {
path="custom-pages/*"
element={<PageWrap><CustomPages courseId={courseId} /></PageWrap>}
/>
<Route
path="/subsection/:subsectionId"
element={<PageWrap><SubsectionUnitRedirect courseId={courseId} /></PageWrap>}
/>
{DECODED_ROUTES.COURSE_UNIT.map((path) => (
<Route
key={path}

View File

@@ -1,5 +1,7 @@
import CourseAuthoringRoutes from './CourseAuthoringRoutes';
import { executeThunk } from './utils';
import { getApiWaffleFlagsUrl } from './data/api';
import { fetchWaffleFlags } from './data/thunks';
import {
screen, initializeMocks, render, waitFor,
} from './testUtils';
@@ -9,6 +11,7 @@ const pagesAndResourcesMockText = 'Pages And Resources';
const editorContainerMockText = 'Editor Container';
const videoSelectorContainerMockText = 'Video Selector Container';
const customPagesMockText = 'Custom Pages';
let store;
const mockComponentFn = jest.fn();
jest.mock('react-router-dom', () => ({
@@ -48,10 +51,12 @@ jest.mock('./custom-pages/CustomPages', () => (props) => {
describe('<CourseAuthoringRoutes>', () => {
beforeEach(async () => {
const { axiosMock } = initializeMocks();
const { axiosMock, reduxStore } = initializeMocks();
store = reduxStore;
axiosMock
.onGet(getApiWaffleFlagsUrl(courseId))
.reply(200, {});
await executeThunk(fetchWaffleFlags(courseId), store.dispatch);
});
it('renders the PagesAndResources component when the pages and resources route is active', async () => {

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { injectIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import { Hyperlink, MailtoLink, Stack } from '@openedx/paragon';
import messages from './messages';
@@ -95,4 +95,4 @@ AccessibilityBody.propTypes = {
email: PropTypes.string.isRequired,
};
export default AccessibilityBody;
export default injectIntl(AccessibilityBody);

View File

@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
FormattedMessage, FormattedDate, FormattedTime, useIntl,
injectIntl, FormattedMessage, intlShape, FormattedDate, FormattedTime,
} from '@edx/frontend-platform/i18n';
import {
ActionRow, Alert, Form, Stack, StatefulButton,
@@ -15,8 +15,9 @@ import messages from './messages';
const AccessibilityForm = ({
accessibilityEmail,
// injected
intl,
}) => {
const intl = useIntl();
const {
errors,
values,
@@ -138,6 +139,8 @@ const AccessibilityForm = ({
AccessibilityForm.propTypes = {
accessibilityEmail: PropTypes.string.isRequired,
// injected
intl: intlShape.isRequired,
};
export default AccessibilityForm;
export default injectIntl(AccessibilityForm);

View File

@@ -1,5 +1,6 @@
import {
render,
act,
screen,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
@@ -73,24 +74,22 @@ describe('<AccessibilityPolicyForm />', () => {
describe('statusAlert', () => {
let formSections;
let submitButton;
let user;
beforeEach(async () => {
user = userEvent.setup();
renderComponent();
formSections = screen.getAllByRole('textbox');
await user.type(formSections[0], 'email@email.com');
await user.type(formSections[1], 'test name');
await user.type(formSections[2], 'feedback message');
await act(async () => {
userEvent.type(formSections[0], 'email@email.com');
userEvent.type(formSections[1], 'test name');
userEvent.type(formSections[2], 'feedback message');
});
submitButton = screen.getByText(messages.accessibilityPolicyFormSubmitLabel.defaultMessage);
});
it('shows correct success message', async () => {
axiosMock.onPost(getZendeskrUrl()).reply(200);
await user.click(submitButton);
await act(async () => {
userEvent.click(submitButton);
});
const { savingStatus } = store.getState().accessibilityPage;
expect(savingStatus).toEqual(RequestStatus.SUCCESSFUL);
@@ -105,9 +104,9 @@ describe('<AccessibilityPolicyForm />', () => {
it('shows correct rate limiting message', async () => {
axiosMock.onPost(getZendeskrUrl()).reply(429);
await user.click(submitButton);
await act(async () => {
userEvent.click(submitButton);
});
const { savingStatus } = store.getState().accessibilityPage;
expect(savingStatus).toEqual(RequestStatus.FAILED);
@@ -124,24 +123,23 @@ describe('<AccessibilityPolicyForm />', () => {
describe('input validation', () => {
let formSections;
let submitButton;
let user;
beforeEach(async () => {
user = userEvent.setup();
renderComponent();
formSections = screen.getAllByRole('textbox');
await user.type(formSections[0], 'email@email.com');
await user.type(formSections[1], 'test name');
await user.type(formSections[2], 'feedback message');
await act(async () => {
userEvent.type(formSections[0], 'email@email.com');
userEvent.type(formSections[1], 'test name');
userEvent.type(formSections[2], 'feedback message');
});
submitButton = screen.getByText(messages.accessibilityPolicyFormSubmitLabel.defaultMessage);
});
it('adds validation checking on each input field', async () => {
await user.clear(formSections[0]);
await user.clear(formSections[1]);
await user.clear(formSections[2]);
await act(async () => {
userEvent.clear(formSections[0]);
userEvent.clear(formSections[1]);
userEvent.clear(formSections[2]);
});
const emailError = screen.getByTestId('error-feedback-email');
expect(emailError).toBeVisible();
@@ -153,10 +151,12 @@ describe('<AccessibilityPolicyForm />', () => {
});
it('sumbit button is disabled when trying to submit with all empty fields', async () => {
await user.clear(formSections[0]);
await user.clear(formSections[1]);
await user.clear(formSections[2]);
await user.click(submitButton);
await act(async () => {
userEvent.clear(formSections[0]);
userEvent.clear(formSections[1]);
userEvent.clear(formSections[2]);
userEvent.click(submitButton);
});
expect(submitButton.closest('button')).toBeDisabled();
});

View File

@@ -1,18 +1,20 @@
import React from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Helmet } from 'react-helmet';
import { Container } from '@openedx/paragon';
import { StudioFooterSlot } from '@edx/frontend-component-footer';
import { StudioFooterSlot } from '@openedx/frontend-slot-footer';
import Header from '../header';
import messages from './messages';
import AccessibilityBody from './AccessibilityBody';
import AccessibilityForm from './AccessibilityForm';
import { COMMUNITY_ACCESSIBILITY_LINK, ACCESSIBILITY_EMAIL } from './constants';
const AccessibilityPage = () => {
const intl = useIntl();
const AccessibilityPage = ({
// injected
intl,
}) => {
const communityAccessibilityLink = 'https://www.edx.org/accessibility';
const email = 'accessibility@edx.org';
return (
<>
<Helmet>
@@ -24,16 +26,17 @@ const AccessibilityPage = () => {
</Helmet>
<Header isHiddenMainMenu />
<Container size="xl" classNamae="px-4">
<AccessibilityBody
{...{ email: ACCESSIBILITY_EMAIL, communityAccessibilityLink: COMMUNITY_ACCESSIBILITY_LINK }}
/>
<AccessibilityForm accessibilityEmail={ACCESSIBILITY_EMAIL} />
<AccessibilityBody {...{ email, communityAccessibilityLink }} />
<AccessibilityForm accessibilityEmail={email} />
</Container>
<StudioFooterSlot />
</>
);
};
AccessibilityPage.propTypes = {};
AccessibilityPage.propTypes = {
// injected
intl: intlShape.isRequired,
};
export default AccessibilityPage;
export default injectIntl(AccessibilityPage);

View File

@@ -1,13 +1,42 @@
// @ts-check
import { initializeMocks, render, screen } from '../testUtils';
import {
render,
screen,
} from '@testing-library/react';
import { AppProvider } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { initializeMockApp } from '@edx/frontend-platform';
import initializeStore from '../store';
import AccessibilityPage from './index';
const renderComponent = () => render(<AccessibilityPage />);
const initialState = {
accessibilityPage: {
status: {},
},
};
let store;
const renderComponent = () => {
render(
<IntlProvider locale="en">
<AppProvider store={store}>
<AccessibilityPage />
</AppProvider>
</IntlProvider>,
);
};
describe('<AccessibilityPolicyPage />', () => {
describe('renders', () => {
beforeEach(async () => {
initializeMocks();
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: false,
roles: [],
},
});
store = initializeStore(initialState);
});
it('contains the policy body', () => {
renderComponent();

View File

@@ -1,2 +0,0 @@
export const COMMUNITY_ACCESSIBILITY_LINK = 'https://www.edx.org/accessibility';
export const ACCESSIBILITY_EMAIL = 'accessibility@edx.org';

View File

@@ -10,11 +10,9 @@ function submitAccessibilityForm({ email, name, message }) {
await postAccessibilityForm({ email, name, message });
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
} catch (error) {
/* istanbul ignore else */
if (error.response && error.response.status === 429) {
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
} else {
/* istanbul ignore next */
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
}
}

View File

@@ -5,7 +5,7 @@ import {
Container, Button, Layout, StatefulButton, TransitionReplace,
} from '@openedx/paragon';
import { CheckCircle, Info, Warning } from '@openedx/paragon/icons';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import Placeholder from '../editors/Placeholder';
import AlertProctoringError from '../generic/AlertProctoringError';
@@ -26,8 +26,7 @@ import messages from './messages';
import ModalError from './modal-error/ModalError';
import getPageHeadTitle from '../generic/utils';
const AdvancedSettings = ({ courseId }) => {
const intl = useIntl();
const AdvancedSettings = ({ intl, courseId }) => {
const dispatch = useDispatch();
const [saveSettingsPrompt, showSaveSettingsPrompt] = useState(false);
const [showDeprecated, setShowDeprecated] = useState(false);
@@ -279,7 +278,8 @@ const AdvancedSettings = ({ courseId }) => {
};
AdvancedSettings.propTypes = {
intl: intlShape.isRequired,
courseId: PropTypes.string.isRequired,
};
export default AdvancedSettings;
export default injectIntl(AdvancedSettings);

View File

@@ -1,9 +1,12 @@
import {
render as baseRender,
fireEvent,
initializeMocks,
waitFor,
} from '../testUtils';
import React from 'react';
import { initializeMockApp } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
import { AppProvider } from '@edx/frontend-platform/react';
import { render, fireEvent, waitFor } from '@testing-library/react';
import MockAdapter from 'axios-mock-adapter';
import initializeStore from '../store';
import { executeThunk } from '../utils';
import { advancedSettingsMock } from './__mocks__';
import { getCourseAdvancedSettingsApiUrl } from './data/api';
@@ -25,22 +28,39 @@ jest.mock('react-textarea-autosize', () => jest.fn((props) => (
/>
)));
const render = () => baseRender(
<AdvancedSettings courseId={courseId} />,
{ path: mockPathname },
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: () => ({
pathname: mockPathname,
}),
}));
const RootWrapper = () => (
<AppProvider store={store}>
<IntlProvider locale="en" messages={{}}>
<AdvancedSettings intl={injectIntl} courseId={courseId} />
</IntlProvider>
</AppProvider>
);
describe('<AdvancedSettings />', () => {
beforeEach(() => {
const mocks = initializeMocks();
store = mocks.reduxStore;
axiosMock = mocks.axiosMock;
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: true,
roles: [],
},
});
store = initializeStore();
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
axiosMock
.onGet(`${getCourseAdvancedSettingsApiUrl(courseId)}?fetch_all=0`)
.reply(200, advancedSettingsMock);
});
it('should render without errors', async () => {
const { getByText } = render();
const { getByText } = render(<RootWrapper />);
await waitFor(() => {
expect(getByText(messages.headingSubtitle.defaultMessage)).toBeInTheDocument();
const advancedSettingsElement = getByText(messages.headingTitle.defaultMessage, {
@@ -52,7 +72,7 @@ describe('<AdvancedSettings />', () => {
});
});
it('should render setting element', async () => {
const { getByText, queryByText } = render();
const { getByText, queryByText } = render(<RootWrapper />);
await waitFor(() => {
const advancedModuleListTitle = getByText(/Advanced Module List/i);
expect(advancedModuleListTitle).toBeInTheDocument();
@@ -60,7 +80,7 @@ describe('<AdvancedSettings />', () => {
});
});
it('should change to onСhange', async () => {
const { getByLabelText } = render();
const { getByLabelText } = render(<RootWrapper />);
await waitFor(() => {
const textarea = getByLabelText(/Advanced Module List/i);
expect(textarea).toBeInTheDocument();
@@ -69,7 +89,7 @@ describe('<AdvancedSettings />', () => {
});
});
it('should display a warning alert', async () => {
const { getByLabelText, getByText } = render();
const { getByLabelText, getByText } = render(<RootWrapper />);
await waitFor(() => {
const textarea = getByLabelText(/Advanced Module List/i);
fireEvent.change(textarea, { target: { value: '[3, 2, 1]' } });
@@ -80,7 +100,7 @@ describe('<AdvancedSettings />', () => {
});
});
it('should display a tooltip on clicking on the icon', async () => {
const { getByLabelText, getByText } = render();
const { getByLabelText, getByText } = render(<RootWrapper />);
await waitFor(() => {
const button = getByLabelText(/Show help text/i);
fireEvent.click(button);
@@ -88,7 +108,7 @@ describe('<AdvancedSettings />', () => {
});
});
it('should change deprecated button text ', async () => {
const { getByText } = render();
const { getByText } = render(<RootWrapper />);
await waitFor(() => {
const showDeprecatedItemsBtn = getByText(/Show Deprecated Settings/i);
expect(showDeprecatedItemsBtn).toBeInTheDocument();
@@ -98,7 +118,7 @@ describe('<AdvancedSettings />', () => {
expect(getByText('Certificate web/html view enabled')).toBeInTheDocument();
});
it('should reset to default value on click on Cancel button', async () => {
const { getByLabelText, getByText } = render();
const { getByLabelText, getByText } = render(<RootWrapper />);
let textarea;
await waitFor(() => {
textarea = getByLabelText(/Advanced Module List/i);
@@ -109,7 +129,7 @@ describe('<AdvancedSettings />', () => {
expect(textarea.value).toBe('[]');
});
it('should update the textarea value and display the updated value after clicking "Change manually"', async () => {
const { getByLabelText, getByText } = render();
const { getByLabelText, getByText } = render(<RootWrapper />);
let textarea;
await waitFor(() => {
textarea = getByLabelText(/Advanced Module List/i);
@@ -121,7 +141,7 @@ describe('<AdvancedSettings />', () => {
expect(textarea.value).toBe('[3, 2, 1,');
});
it('should show success alert after save', async () => {
const { getByLabelText, getByText } = render();
const { getByLabelText, getByText } = render(<RootWrapper />);
let textarea;
await waitFor(() => {
textarea = getByLabelText(/Advanced Module List/i);

View File

@@ -1,10 +1,5 @@
/* eslint-disable import/prefer-default-export */
import {
camelCaseObject,
getConfig,
} from '@edx/frontend-platform';
import { camelCaseObject, getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { camelCase } from 'lodash';
import { convertObjectToSnakeCase } from '../../utils';
const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
@@ -19,19 +14,7 @@ const getProctoringErrorsApiUrl = () => `${getApiBaseUrl()}/api/contentstore/v1/
export async function getCourseAdvancedSettings(courseId) {
const { data } = await getAuthenticatedHttpClient()
.get(`${getCourseAdvancedSettingsApiUrl(courseId)}?fetch_all=0`);
const keepValues = {};
Object.keys(data).forEach((key) => {
keepValues[camelCase(key)] = { value: data[key].value };
});
const formattedData = {};
const formattedCamelCaseData = camelCaseObject(data);
Object.keys(formattedCamelCaseData).forEach((key) => {
formattedData[key] = {
...formattedCamelCaseData[key],
value: keepValues[key]?.value,
};
});
return formattedData;
return camelCaseObject(data);
}
/**
@@ -43,19 +26,7 @@ export async function getCourseAdvancedSettings(courseId) {
export async function updateCourseAdvancedSettings(courseId, settings) {
const { data } = await getAuthenticatedHttpClient()
.patch(`${getCourseAdvancedSettingsApiUrl(courseId)}`, convertObjectToSnakeCase(settings));
const keepValues = {};
Object.keys(data).forEach((key) => {
keepValues[camelCase(key)] = { value: data[key].value };
});
const formattedData = {};
const formattedCamelCaseData = camelCaseObject(data);
Object.keys(formattedCamelCaseData).forEach((key) => {
formattedData[key] = {
...formattedCamelCaseData[key],
value: keepValues[key]?.value,
};
});
return formattedData;
return camelCaseObject(data);
}
/**
@@ -65,17 +36,5 @@ export async function updateCourseAdvancedSettings(courseId, settings) {
*/
export async function getProctoringExamErrors(courseId) {
const { data } = await getAuthenticatedHttpClient().get(`${getProctoringErrorsApiUrl()}${courseId}`);
const keepValues = {};
Object.keys(data).forEach((key) => {
keepValues[camelCase(key)] = { value: data[key].value };
});
const formattedData = {};
const formattedCamelCaseData = camelCaseObject(data);
Object.keys(formattedCamelCaseData).forEach((key) => {
formattedData[key] = {
...formattedCamelCaseData[key],
value: keepValues[key]?.value,
};
});
return formattedData;
return camelCaseObject(data);
}

View File

@@ -1,236 +0,0 @@
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import {
getCourseAdvancedSettings,
updateCourseAdvancedSettings,
getProctoringExamErrors,
} from './api';
jest.mock('@edx/frontend-platform/auth', () => ({
getAuthenticatedHttpClient: jest.fn(),
}));
describe('courseSettings API', () => {
const mockHttpClient = {
get: jest.fn(),
patch: jest.fn(),
};
beforeEach(() => {
jest.clearAllMocks();
getAuthenticatedHttpClient.mockReturnValue(mockHttpClient);
});
describe('getCourseAdvancedSettings', () => {
it('should fetch and unformat course advanced settings', async () => {
const fakeData = {
key_snake_case: {
display_name: 'To come camelCase',
testCamelCase: 'This key must not be formatted',
PascalCase: 'To come camelCase',
'kebab-case': 'To come camelCase',
UPPER_CASE: 'To come camelCase',
lowercase: 'This key must not be formatted',
UPPERCASE: 'To come lowercase',
'Title Case': 'To come camelCase',
'dot.case': 'To come camelCase',
SCREAMING_SNAKE_CASE: 'To come camelCase',
MixedCase: 'To come camelCase',
'Train-Case': 'To come camelCase',
nestedOption: {
anotherOption: 'To come camelCase',
},
// value is an object with various cases
// this contain must not be formatted to camelCase
value: {
snake_case: 'snake_case',
camelCase: 'camelCase',
PascalCase: 'PascalCase',
'kebab-case': 'kebab-case',
UPPER_CASE: 'UPPER_CASE',
lowercase: 'lowercase',
UPPERCASE: 'UPPERCASE',
'Title Case': 'Title Case',
'dot.case': 'dot.case',
SCREAMING_SNAKE_CASE: 'SCREAMING_SNAKE_CASE',
MixedCase: 'MixedCase',
'Train-Case': 'Train-Case',
nestedOption: {
anotherOption: 'nestedContent',
},
},
},
};
const expected = {
keySnakeCase: {
displayName: 'To come camelCase',
testCamelCase: 'This key must not be formatted',
pascalCase: 'To come camelCase',
kebabCase: 'To come camelCase',
upperCase: 'To come camelCase',
lowercase: 'This key must not be formatted',
uppercase: 'To come lowercase',
titleCase: 'To come camelCase',
dotCase: 'To come camelCase',
screamingSnakeCase: 'To come camelCase',
mixedCase: 'To come camelCase',
trainCase: 'To come camelCase',
nestedOption: {
anotherOption: 'To come camelCase',
},
value: fakeData.key_snake_case.value,
},
};
mockHttpClient.get.mockResolvedValue({ data: fakeData });
const result = await getCourseAdvancedSettings('course-v1:Test+T101+2024');
expect(mockHttpClient.get).toHaveBeenCalledWith(
`${process.env.STUDIO_BASE_URL}/api/contentstore/v0/advanced_settings/course-v1:Test+T101+2024?fetch_all=0`,
);
expect(result).toEqual(expected);
});
});
describe('updateCourseAdvancedSettings', () => {
it('should update and unformat course advanced settings', async () => {
const fakeData = {
key_snake_case: {
display_name: 'To come camelCase',
testCamelCase: 'This key must not be formatted', // because already be camelCase
PascalCase: 'To come camelCase',
'kebab-case': 'To come camelCase',
UPPER_CASE: 'To come camelCase',
lowercase: 'This key must not be formatted', // because camelCase in lowercase not formatted
UPPERCASE: 'To come lowercase', // because camelCase in UPPERCASE format to lowercase
'Title Case': 'To come camelCase',
'dot.case': 'To come camelCase',
SCREAMING_SNAKE_CASE: 'To come camelCase',
MixedCase: 'To come camelCase',
'Train-Case': 'To come camelCase',
nestedOption: {
anotherOption: 'To come camelCase',
},
// value is an object with various cases
// this contain must not be formatted to camelCase
value: {
snake_case: 'snake_case',
camelCase: 'camelCase',
PascalCase: 'PascalCase',
'kebab-case': 'kebab-case',
UPPER_CASE: 'UPPER_CASE',
lowercase: 'lowercase',
UPPERCASE: 'UPPERCASE',
'Title Case': 'Title Case',
'dot.case': 'dot.case',
SCREAMING_SNAKE_CASE: 'SCREAMING_SNAKE_CASE',
MixedCase: 'MixedCase',
'Train-Case': 'Train-Case',
nestedOption: {
anotherOption: 'nestedContent',
},
},
},
};
const expected = {
keySnakeCase: {
displayName: 'To come camelCase',
testCamelCase: 'This key must not be formatted',
pascalCase: 'To come camelCase',
kebabCase: 'To come camelCase',
upperCase: 'To come camelCase',
lowercase: 'This key must not be formatted',
uppercase: 'To come lowercase',
titleCase: 'To come camelCase',
dotCase: 'To come camelCase',
screamingSnakeCase: 'To come camelCase',
mixedCase: 'To come camelCase',
trainCase: 'To come camelCase',
nestedOption: {
anotherOption: 'To come camelCase',
},
value: fakeData.key_snake_case.value,
},
};
mockHttpClient.patch.mockResolvedValue({ data: fakeData });
const result = await updateCourseAdvancedSettings('course-v1:Test+T101+2024', {});
expect(mockHttpClient.patch).toHaveBeenCalledWith(
`${process.env.STUDIO_BASE_URL}/api/contentstore/v0/advanced_settings/course-v1:Test+T101+2024`,
{},
);
expect(result).toEqual(expected);
});
});
describe('getProctoringExamErrors', () => {
it('should fetch proctoring errors and return unformat object', async () => {
const fakeData = {
key_snake_case: {
display_name: 'To come camelCase',
testCamelCase: 'This key must not be formatted',
PascalCase: 'To come camelCase',
'kebab-case': 'To come camelCase',
UPPER_CASE: 'To come camelCase',
lowercase: 'This key must not be formatted',
UPPERCASE: 'To come lowercase',
'Title Case': 'To come camelCase',
'dot.case': 'To come camelCase',
SCREAMING_SNAKE_CASE: 'To come camelCase',
MixedCase: 'To come camelCase',
'Train-Case': 'To come camelCase',
nestedOption: {
anotherOption: 'To come camelCase',
},
// value is an object with various cases
// this contain must not be formatted to camelCase
value: {
snake_case: 'snake_case',
camelCase: 'camelCase',
PascalCase: 'PascalCase',
'kebab-case': 'kebab-case',
UPPER_CASE: 'UPPER_CASE',
lowercase: 'lowercase',
UPPERCASE: 'UPPERCASE',
'Title Case': 'Title Case',
'dot.case': 'dot.case',
SCREAMING_SNAKE_CASE: 'SCREAMING_SNAKE_CASE',
MixedCase: 'MixedCase',
'Train-Case': 'Train-Case',
nestedOption: {
anotherOption: 'nestedContent',
},
},
},
};
const expected = {
keySnakeCase: {
displayName: 'To come camelCase',
testCamelCase: 'This key must not be formatted',
pascalCase: 'To come camelCase',
kebabCase: 'To come camelCase',
upperCase: 'To come camelCase',
lowercase: 'This key must not be formatted',
uppercase: 'To come lowercase',
titleCase: 'To come camelCase',
dotCase: 'To come camelCase',
screamingSnakeCase: 'To come camelCase',
mixedCase: 'To come camelCase',
trainCase: 'To come camelCase',
nestedOption: {
anotherOption: 'To come camelCase',
},
value: fakeData.key_snake_case.value,
},
};
mockHttpClient.get.mockResolvedValue({ data: fakeData });
const result = await getProctoringExamErrors('course-v1:Test+T101+2024');
expect(mockHttpClient.get).toHaveBeenCalledWith(
`${process.env.STUDIO_BASE_URL}/api/contentstore/v1/proctoring_errors/course-v1:Test+T101+2024`,
);
expect(result).toEqual(expected);
});
});
});

View File

@@ -1,57 +1,55 @@
import React from 'react';
import PropTypes from 'prop-types';
import { ActionRow, AlertModal, Button } from '@openedx/paragon';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import ModalErrorListItem from './ModalErrorListItem';
import messages from './messages';
const ModalError = ({
isError, handleUndoChanges, showErrorModal, errorList, settingsData,
}) => {
const intl = useIntl();
return (
<AlertModal
title={intl.formatMessage(messages.modalErrorTitle)}
isOpen={isError}
variant="danger"
footerNode={(
<ActionRow>
<Button
variant="tertiary"
onClick={() => showErrorModal(!isError)}
>
{intl.formatMessage(messages.modalErrorButtonChangeManually)}
</Button>
<Button onClick={handleUndoChanges}>
{intl.formatMessage(messages.modalErrorButtonUndoChanges)}
</Button>
</ActionRow>
intl, isError, handleUndoChanges, showErrorModal, errorList, settingsData,
}) => (
<AlertModal
title={intl.formatMessage(messages.modalErrorTitle)}
isOpen={isError}
variant="danger"
footerNode={(
<ActionRow>
<Button
variant="tertiary"
onClick={() => showErrorModal(!isError)}
>
{intl.formatMessage(messages.modalErrorButtonChangeManually)}
</Button>
<Button onClick={handleUndoChanges}>
{intl.formatMessage(messages.modalErrorButtonUndoChanges)}
</Button>
</ActionRow>
)}
>
<p>
<FormattedMessage
id="course-authoring.advanced-settings.modal.error.description"
defaultMessage="There was {errorCounter} while trying to save the course settings in the database.
>
<p>
<FormattedMessage
id="course-authoring.advanced-settings.modal.error.description"
defaultMessage="There was {errorCounter} while trying to save the course settings in the database.
Please check the following validation feedbacks and reflect them in your course settings:"
values={{ errorCounter: <strong>{errorList.length} validation error </strong> }}
values={{ errorCounter: <strong>{errorList.length} validation error </strong> }}
/>
</p>
<hr />
<ul className="p-0">
{errorList.map((settingName) => (
<ModalErrorListItem
key={settingName.key}
settingName={settingName}
settingsData={settingsData}
/>
</p>
<hr />
<ul className="p-0">
{errorList.map((settingName) => (
<ModalErrorListItem
key={settingName.key}
settingName={settingName}
settingsData={settingsData}
/>
))}
</ul>
</AlertModal>
);
};
))}
</ul>
</AlertModal>
);
ModalError.propTypes = {
intl: intlShape.isRequired,
isError: PropTypes.bool.isRequired,
handleUndoChanges: PropTypes.func.isRequired,
showErrorModal: PropTypes.func.isRequired,
@@ -62,4 +60,4 @@ ModalError.propTypes = {
settingsData: PropTypes.shape({}).isRequired,
};
export default ModalError;
export default injectIntl(ModalError);

View File

@@ -32,7 +32,7 @@
bottom: 0;
width: 100%;
padding: 0 .625rem;
z-index: var(--pgn-elevation-modal-zindex);
z-index: $zindex-modal;
}
.alert-proctoring-error {
@@ -66,13 +66,13 @@
.setting-sidebar-supplementary {
.setting-sidebar-supplementary-about {
.setting-sidebar-supplementary-about-title {
font: normal var(--pgn-typography-font-weight-bold) 1.125rem/1.5rem var(--pgn-typography-font-family-base);
color: var(--pgn-color-headings-base);
font: normal $font-weight-bold 1.125rem/1.5rem $font-family-base;
color: $headings-color;
margin-bottom: 1.25rem;
}
.setting-sidebar-supplementary-about-descriptions {
font: normal var(--pgn-typography-font-weight-normal) .875rem/1.5rem var(--pgn-typography-font-family-base);
font: normal $font-weight-normal .875rem/1.5rem $font-family-base;
color: $text-color-base;
}
}
@@ -81,16 +81,16 @@
list-style: none;
.setting-sidebar-supplementary-other-link {
font: normal var(--pgn-typography-font-weight-normal) .875rem/1.5rem var(--pgn-typography-font-family-base);
font: normal $font-weight-normal .875rem/1.5rem $font-family-base;
line-height: 1.5rem;
color: var(--pgn-color-info-500);
color: $info-500;
margin-bottom: .5rem;
}
}
.setting-sidebar-supplementary-other-title {
font: normal var(--pgn-typography-font-weight-bold) 1.125rem/1.5rem var(--pgn-typography-font-family-base);
color: var(--pgn-color-headings-base);
font: normal $font-weight-bold 1.125rem/1.5rem $font-family-base;
color: $headings-color;
margin-bottom: 1.25rem;
}
}
@@ -102,7 +102,7 @@
display: inline-block;
margin-right: 5px;
margin-bottom: 5px;
color: var(--pgn-color-danger-base);
color: $danger;
}
.modal-error-item-title {
@@ -113,12 +113,12 @@
.modal-popup-content {
max-width: 200px;
color: var(--pgn-color-white);
background-color: var(--pgn-color-black);
color: $white;
background-color: $black;
filter: drop-shadow(0 2px 4px rgba(0 0 0 / .15));
font-weight: 400;
}
.pgn__modal-popup__arrow::after {
border-top-color: var(--pgn-color-black);
border-top-color: $black;
}

View File

@@ -1 +1 @@
$text-color-base: var(--pgn-color-gray-700);
$text-color-base: $gray-700;

View File

@@ -11,7 +11,7 @@ import {
import { InfoOutline, Warning } from '@openedx/paragon/icons';
import PropTypes from 'prop-types';
import { capitalize } from 'lodash';
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import TextareaAutosize from 'react-textarea-autosize';
import messages from './messages';
@@ -25,8 +25,9 @@ const SettingCard = ({
saveSettingsPrompt,
isEditableState,
setIsEditableState,
// injected
intl,
}) => {
const intl = useIntl();
const { deprecated, help, displayName } = settingData;
const initialValue = JSON.stringify(settingData.value, null, 4);
const [isOpen, open, close] = useToggle(false);
@@ -114,6 +115,7 @@ const SettingCard = ({
};
SettingCard.propTypes = {
intl: intlShape.isRequired,
settingData: PropTypes.shape({
deprecated: PropTypes.bool,
help: PropTypes.string,
@@ -135,4 +137,4 @@ SettingCard.propTypes = {
setIsEditableState: PropTypes.func.isRequired,
};
export default SettingCard;
export default injectIntl(SettingCard);

View File

@@ -29,6 +29,7 @@ jest.mock('react-textarea-autosize', () => jest.fn((props) => (
const RootWrapper = () => (
<IntlProvider locale="en">
<SettingCard
intl={{}}
isOn
name="settingName"
setEdited={setEdited}
@@ -57,6 +58,7 @@ describe('<SettingCard />', () => {
const { getByText } = render(
<IntlProvider locale="en">
<SettingCard
intl={{}}
isOn
name="settingName"
setEdited={setEdited}
@@ -77,12 +79,11 @@ describe('<SettingCard />', () => {
expect(queryByText(messages.deprecated.defaultMessage)).toBeNull();
});
it('calls setEdited on blur', async () => {
const user = userEvent.setup();
const { getByLabelText } = render(<RootWrapper />);
const inputBox = getByLabelText(/Setting Name/i);
fireEvent.focus(inputBox);
await user.clear(inputBox);
await user.type(inputBox, '3, 2, 1');
userEvent.clear(inputBox);
userEvent.type(inputBox, '3, 2, 1');
await waitFor(() => {
expect(inputBox).toHaveValue('3, 2, 1');
});

View File

@@ -1,25 +1,28 @@
// @ts-check
import React from 'react';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import {
FormattedMessage,
injectIntl,
intlShape,
} from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import { HelpSidebar } from '../../generic/help-sidebar';
import messages from './messages';
const SettingsSidebar = ({ courseId, proctoredExamSettingsUrl = '' }) => (
const SettingsSidebar = ({ intl, courseId, proctoredExamSettingsUrl }) => (
<HelpSidebar
courseId={courseId}
proctoredExamSettingsUrl={proctoredExamSettingsUrl}
showOtherSettings
>
<h4 className="help-sidebar-about-title">
<FormattedMessage {...messages.about} />
{intl.formatMessage(messages.about)}
</h4>
<p className="help-sidebar-about-descriptions">
<FormattedMessage {...messages.aboutDescription1} />
{intl.formatMessage(messages.aboutDescription1)}
</p>
<p className="help-sidebar-about-descriptions">
<FormattedMessage {...messages.aboutDescription2} />
{intl.formatMessage(messages.aboutDescription2)}
</p>
<p className="help-sidebar-about-descriptions">
<FormattedMessage
@@ -31,9 +34,14 @@ const SettingsSidebar = ({ courseId, proctoredExamSettingsUrl = '' }) => (
</HelpSidebar>
);
SettingsSidebar.defaultProps = {
proctoredExamSettingsUrl: '',
};
SettingsSidebar.propTypes = {
intl: intlShape.isRequired,
courseId: PropTypes.string.isRequired,
proctoredExamSettingsUrl: PropTypes.string,
};
export default SettingsSidebar;
export default injectIntl(SettingsSidebar);

View File

@@ -1,21 +1,43 @@
// @ts-check
import { initializeMocks, render } from '../../testUtils';
import React from 'react';
import { render } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { initializeMockApp } from '@edx/frontend-platform';
import { AppProvider } from '@edx/frontend-platform/react';
import initializeStore from '../../store';
import SettingsSidebar from './SettingsSidebar';
import messages from './messages';
const courseId = 'course-123';
let store;
const RootWrapper = () => (
<AppProvider store={store}>
<IntlProvider locale="en" messages={{}}>
<SettingsSidebar intl={{ formatMessage: jest.fn() }} courseId={courseId} />
</IntlProvider>
</AppProvider>
);
describe('<SettingsSidebar />', () => {
beforeEach(() => {
initializeMocks();
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: true,
roles: [],
},
});
store = initializeStore();
});
it('renders about and other sidebar titles correctly', () => {
const { getByText } = render(<SettingsSidebar courseId={courseId} />);
const { getByText } = render(<RootWrapper />);
expect(getByText(messages.about.defaultMessage)).toBeInTheDocument();
expect(getByText(messages.other.defaultMessage)).toBeInTheDocument();
});
it('renders about descriptions correctly', () => {
const { getByText } = render(<SettingsSidebar courseId={courseId} />);
const { getByText } = render(<RootWrapper />);
const aboutThirtyDescription = getByText('When you enter strings as policy values, ensure that you use double quotation marks (“) around the string. Do not use single quotation marks ().');
expect(getByText(messages.aboutDescription1.defaultMessage)).toBeInTheDocument();
expect(getByText(messages.aboutDescription2.defaultMessage)).toBeInTheDocument();

View File

@@ -1,14 +1,14 @@
.form-group-custom {
.pgn__form-label {
font: normal var(--pgn-typography-font-weight-bold) .75rem/1.25rem var(--pgn-typography-font-family-base);
color: var(--pgn-color-gray-500);
font: normal $font-weight-bold .75rem/1.25rem $font-family-base;
color: $gray-500;
margin-bottom: .5rem;
}
.pgn__form-control-description,
.pgn__form-text {
font: normal var(--pgn-typography-font-weight-normal) .75rem/1.25rem var(--pgn-typography-font-family-base);
color: var(--pgn-color-gray-500);
font: normal $font-weight-normal .75rem/1.25rem $font-family-base;
color: $gray-500;
margin-top: .5rem;
}
@@ -19,12 +19,12 @@
.form-group-custom_isInvalid {
input {
border-color: var(--pgn-color-form-feedback-invalid);
border-color: $form-feedback-invalid-color;
}
}
.feedback-error {
color: var(--pgn-color-form-feedback-invalid);
color: $form-feedback-invalid-color;
}
}
@@ -34,40 +34,40 @@
.datepicker-custom-control {
display: block;
width: 100%;
font-size: var(--pgn-typography-form-input-font-size-base);
font-weight: var(--pgn-typography-form-input-font-weight);
line-height: var(--pgn-typography-form-input-line-height-base);
background: var(--pgn-color-form-input-bg-base);
border-color: var(--pgn-color-form-input-border);
border-width: var(--pgn-size-form-input-width-border);
box-shadow: var(--pgn-elevation-form-input-base);
border-radius: var(--pgn-size-form-input-radius-border-base);
color: var(--pgn-color-form-input-base);
padding: var(--pgn-spacing-form-input-padding-y-base) var(--pgn-spacing-form-input-padding-x-base);
height: var(--pgn-size-form-input-height-base);
font-size: $input-font-size;
font-weight: $input-font-weight;
line-height: $input-line-height;
background: $input-bg;
border-color: $input-border-color;
border-width: $input-border-width;
box-shadow: $input-box-shadow;
border-radius: $input-border-radius;
color: $input-color;
padding: $input-padding-y $input-padding-x;
height: $input-height;
resize: none;
&:focus,
:focus-visible {
color: var(--pgn-color-form-input-focus-base);
background-color: var(--pgn-color-form-input-bg-base);
border-color: var(--pgn-color-form-input-focus-border);
box-shadow: var(--pgn-elevation-form-input-focus);
color: $input-focus-color;
background-color: $input-bg;
border-color: $input-focus-border-color;
box-shadow: $input-focus-box-shadow;
outline: 0;
}
&::placeholder {
color: var(--pgn-color-form-input-placeholder);
color: $input-placeholder-color;
}
}
.datepicker-custom-control_readonly {
border-color: transparent;
background: var(--pgn-color-form-input-bg-disabled);
background: $input-disabled-bg;
}
.datepicker-custom-control_isInvalid {
border-color: var(--pgn-color-form-feedback-invalid);
border-color: $form-feedback-invalid-color;
}
.datepicker-custom-control-icon {
@@ -76,7 +76,7 @@
right: 1.188rem;
top: 50%;
transform: translateY(-50%);
color: var(--pgn-color-black);
color: $black;
}
}

View File

@@ -1,5 +1,5 @@
.text-black {
color: var(--pgn-color-black);
color: $black;
}
.h-200px {

View File

@@ -1,2 +1,2 @@
$text-color-base: var(--pgn-color-gray-700);
$text-color-base: $gray-700;
$text-color-weak: #3E3E3C;

View File

@@ -1,9 +1,14 @@
// @ts-check
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { initializeMockApp } from '@edx/frontend-platform';
import { AppProvider } from '@edx/frontend-platform/react';
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeMocks, render, waitFor } from '../testUtils';
import { RequestStatus } from '../data/constants';
import { executeThunk } from '../utils';
import initializeStore from '../store';
import { getCertificatesApiUrl } from './data/api';
import { fetchCertificates } from './data/thunks';
import { certificatesDataMock } from './__mocks__';
@@ -14,13 +19,26 @@ let axiosMock;
let store;
const courseId = 'course-123';
const renderComponent = (props) => render(<Certificates courseId={courseId} {...props} />);
const renderComponent = (props) => render(
<AppProvider store={store} messages={{}}>
<IntlProvider locale="en">
<Certificates courseId={courseId} {...props} />
</IntlProvider>
</AppProvider>,
);
describe('Certificates', () => {
beforeEach(async () => {
const mocks = initializeMocks();
store = mocks.reduxStore;
axiosMock = mocks.axiosMock;
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: true,
roles: [],
},
});
store = initializeStore();
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
});
it('renders WithoutModes when there are certificates but no certificate modes', async () => {
@@ -111,13 +129,11 @@ describe('Certificates', () => {
.reply(200, noCertificatesMock);
await executeThunk(fetchCertificates(courseId), store.dispatch);
const user = userEvent.setup();
const { queryByTestId, getByTestId, getByRole } = renderComponent();
await waitFor(async () => {
await waitFor(() => {
const addCertificateButton = getByRole('button', { name: messages.setupCertificateBtn.defaultMessage });
await user.click(addCertificateButton);
userEvent.click(addCertificateButton);
});
expect(getByTestId('certificates-create-form')).toBeInTheDocument();
@@ -133,13 +149,11 @@ describe('Certificates', () => {
.reply(200, certificatesDataMock);
await executeThunk(fetchCertificates(courseId), store.dispatch);
const user = userEvent.setup();
const { queryByTestId, getByTestId, getAllByLabelText } = renderComponent();
await waitFor(async () => {
await waitFor(() => {
const editCertificateButton = getAllByLabelText(messages.editTooltip.defaultMessage)[0];
await user.click(editCertificateButton);
userEvent.click(editCertificateButton);
});
expect(getByTestId('certificates-edit-form')).toBeInTheDocument();

View File

@@ -1,6 +1,4 @@
import {
render, waitFor, within,
} from '@testing-library/react';
import { render, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Provider } from 'react-redux';
import { IntlProvider } from '@edx/frontend-platform/i18n';
@@ -87,19 +85,17 @@ describe('CertificateCreateForm', () => {
}],
};
const user = userEvent.setup();
const { getByPlaceholderText, getByRole, getByDisplayValue } = renderComponent();
await user.type(
userEvent.type(
getByPlaceholderText(detailsMessages.detailsCourseTitleOverride.defaultMessage),
courseTitleOverrideValue,
);
await user.type(
userEvent.type(
getByPlaceholderText(signatoryMessages.namePlaceholder.defaultMessage),
signatoryNameValue,
);
await user.click(getByRole('button', { name: messages.cardCreate.defaultMessage }));
userEvent.click(getByRole('button', { name: messages.cardCreate.defaultMessage }));
axiosMock.onPost(
getCertificateApiUrl(courseId),
@@ -113,9 +109,8 @@ describe('CertificateCreateForm', () => {
});
it('cancel certificates creation', async () => {
const user = userEvent.setup();
const { getByRole } = renderComponent();
await user.click(getByRole('button', { name: messages.cardCancel.defaultMessage }));
userEvent.click(getByRole('button', { name: messages.cardCancel.defaultMessage }));
await waitFor(() => {
expect(store.getState().certificates.componentMode).toBe(MODE_STATES.noCertificates);
@@ -132,14 +127,13 @@ describe('CertificateCreateForm', () => {
});
it('add and delete signatory', async () => {
const user = userEvent.setup();
const {
getAllByRole, queryAllByRole, getByText, getByRole,
} = renderComponent();
const addSignatoryBtn = getByText(signatoryMessages.addSignatoryButton.defaultMessage);
await user.click(addSignatoryBtn);
userEvent.click(addSignatoryBtn);
const deleteIcons = getAllByRole('button', { name: messages.deleteTooltip.defaultMessage });
@@ -147,13 +141,13 @@ describe('CertificateCreateForm', () => {
expect(deleteIcons.length).toBe(2);
});
await user.click(deleteIcons[0]);
userEvent.click(deleteIcons[0]);
const confirModal = getByRole('dialog');
const deleteModalButton = within(confirModal).getByRole('button', { name: messages.deleteTooltip.defaultMessage });
await user.click(deleteIcons[0]);
await user.click(deleteModalButton);
userEvent.click(deleteIcons[0]);
userEvent.click(deleteModalButton);
await waitFor(() => {
expect(queryAllByRole('button', { name: messages.deleteTooltip.defaultMessage }).length).toBe(0);

View File

@@ -1,6 +1,6 @@
import { Provider, useDispatch } from 'react-redux';
import { useParams } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { initializeMockApp } from '@edx/frontend-platform';
@@ -86,24 +86,24 @@ describe('CertificateDetails', () => {
expect(getByText(defaultProps.detailsCourseTitle)).toBeInTheDocument();
});
it('opens confirm modal on delete button click', async () => {
const user = userEvent.setup();
it('opens confirm modal on delete button click', () => {
const { getByRole, getByText } = renderComponent(defaultProps);
const deleteButton = getByRole('button', { name: commonMessages.deleteTooltip.defaultMessage });
await user.click(deleteButton);
userEvent.click(deleteButton);
expect(getByText(messages.deleteCertificateConfirmationTitle.defaultMessage)).toBeInTheDocument();
});
it('dispatches delete action on confirm modal action', async () => {
const user = userEvent.setup();
const props = { ...defaultProps, courseId, certificateId };
const { getByRole } = renderComponent(props);
const deleteButton = getByRole('button', { name: commonMessages.deleteTooltip.defaultMessage });
await user.click(deleteButton);
userEvent.click(deleteButton);
const confirmActionButton = await screen.findByRole('button', { name: commonMessages.deleteTooltip.defaultMessage });
await user.click(confirmActionButton);
await waitFor(() => {
const confirmActionButton = getByRole('button', { name: commonMessages.deleteTooltip.defaultMessage });
userEvent.click(confirmActionButton);
});
expect(mockDispatch).toHaveBeenCalledWith(deleteCourseCertificate(courseId, certificateId));
});

View File

@@ -58,12 +58,11 @@ describe('CertificateDetails', () => {
});
it('handles input change in create mode', async () => {
const user = userEvent.setup();
const { getByPlaceholderText } = renderComponent(defaultProps);
const input = getByPlaceholderText(messages.detailsCourseTitleOverride.defaultMessage);
const newInputValue = 'New Title';
await user.type(input, newInputValue);
userEvent.type(input, newInputValue);
waitFor(() => {
expect(input.value).toBe(newInputValue);

View File

@@ -1,7 +1,5 @@
import { Provider } from 'react-redux';
import {
render, waitFor, within,
} from '@testing-library/react';
import { render, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { initializeMockApp } from '@edx/frontend-platform';
import { IntlProvider } from '@edx/frontend-platform/i18n';
@@ -70,15 +68,15 @@ describe('CertificateEditForm Component', () => {
}],
}],
};
const user = userEvent.setup();
const { getByDisplayValue, getByRole, getByPlaceholderText } = renderComponent();
await user.type(
userEvent.type(
getByPlaceholderText(messagesDetails.detailsCourseTitleOverride.defaultMessage),
courseTitleOverrideValue,
);
await user.click(getByRole('button', { name: messages.saveTooltip.defaultMessage }));
userEvent.click(getByRole('button', { name: messages.saveTooltip.defaultMessage }));
axiosMock.onPost(
getUpdateCertificateApiUrl(courseId, certificatesDataMock.certificates[0].id),
@@ -93,17 +91,16 @@ describe('CertificateEditForm Component', () => {
});
it('deletes a certificate and updates the store', async () => {
const user = userEvent.setup();
axiosMock.onDelete(
getUpdateCertificateApiUrl(courseId, certificatesDataMock.certificates[0].id),
).reply(200);
const { getByRole } = renderComponent();
await user.click(getByRole('button', { name: messages.deleteTooltip.defaultMessage }));
userEvent.click(getByRole('button', { name: messages.deleteTooltip.defaultMessage }));
const confirmDeleteModal = getByRole('dialog');
await user.click(within(confirmDeleteModal).getByRole('button', { name: messages.deleteTooltip.defaultMessage }));
userEvent.click(within(confirmDeleteModal).getByRole('button', { name: messages.deleteTooltip.defaultMessage }));
await executeThunk(deleteCourseCertificate(courseId, certificatesDataMock.certificates[0].id), store.dispatch);
@@ -113,17 +110,16 @@ describe('CertificateEditForm Component', () => {
});
it('updates loading status if delete fails', async () => {
const user = userEvent.setup();
axiosMock.onDelete(
getUpdateCertificateApiUrl(courseId, certificatesDataMock.certificates[0].id),
).reply(404);
const { getByRole } = renderComponent();
await user.click(getByRole('button', { name: messages.deleteTooltip.defaultMessage }));
userEvent.click(getByRole('button', { name: messages.deleteTooltip.defaultMessage }));
const confirmDeleteModal = getByRole('dialog');
await user.click(within(confirmDeleteModal).getByRole('button', { name: messages.deleteTooltip.defaultMessage }));
userEvent.click(within(confirmDeleteModal).getByRole('button', { name: messages.deleteTooltip.defaultMessage }));
await executeThunk(deleteCourseCertificate(courseId, certificatesDataMock.certificates[0].id), store.dispatch);
@@ -133,12 +129,11 @@ describe('CertificateEditForm Component', () => {
});
it('cancel edit form', async () => {
const user = userEvent.setup();
const { getByRole } = renderComponent();
expect(store.getState().certificates.componentMode).toBe(MODE_STATES.editAll);
await user.click(getByRole('button', { name: messages.cardCancel.defaultMessage }));
userEvent.click(getByRole('button', { name: messages.cardCancel.defaultMessage }));
expect(store.getState().certificates.componentMode).toBe(MODE_STATES.view);
});

View File

@@ -88,22 +88,20 @@ describe('CertificateSignatories', () => {
});
});
it('adds a new signatory when add button is clicked', async () => {
const user = userEvent.setup();
it('adds a new signatory when add button is clicked', () => {
const { getByText } = renderComponent({ ...defaultProps, isForm: true });
await user.click(getByText(messages.addSignatoryButton.defaultMessage));
userEvent.click(getByText(messages.addSignatoryButton.defaultMessage));
expect(useCreateSignatory().handleAddSignatory).toHaveBeenCalled();
});
it('calls remove for the correct signatory when delete icon is clicked', async () => {
const user = userEvent.setup();
const { getAllByRole } = renderComponent(defaultProps);
const deleteIcons = getAllByRole('button', { name: commonMessages.deleteTooltip.defaultMessage });
expect(deleteIcons.length).toBe(signatoriesMock.length);
await user.click(deleteIcons[0]);
userEvent.click(deleteIcons[0]);
waitFor(() => {
expect(mockArrayHelpers.remove).toHaveBeenCalledWith(0);

View File

@@ -34,12 +34,11 @@ describe('Signatory Component', () => {
expect(queryByText(messages.namePlaceholder.defaultMessage)).not.toBeInTheDocument();
});
it('calls handleEdit when the edit button is clicked', async () => {
const user = userEvent.setup();
it('calls handleEdit when the edit button is clicked', () => {
const { getByRole } = renderSignatory(defaultProps);
const editButton = getByRole('button', { name: commonMessages.editTooltip.defaultMessage });
await user.click(editButton);
userEvent.click(editButton);
expect(mockHandleEdit).toHaveBeenCalled();
});

View File

@@ -60,13 +60,12 @@ describe('Signatory Component', () => {
});
it('handles input change', async () => {
const user = userEvent.setup();
const handleChange = jest.fn();
const { getByPlaceholderText } = renderSignatory({ ...defaultProps, handleChange });
const input = getByPlaceholderText(messages.namePlaceholder.defaultMessage);
const newInputValue = 'Jane Doe';
await user.type(input, newInputValue, { name: 'signatories[0].name' });
userEvent.type(input, newInputValue, { name: 'signatories[0].name' });
waitFor(() => {
expect(handleChange).toHaveBeenCalledWith(expect.anything());
@@ -74,8 +73,7 @@ describe('Signatory Component', () => {
});
});
it('opens image upload modal on button click', async () => {
const user = userEvent.setup();
it('opens image upload modal on button click', () => {
const { getByRole, queryByRole } = renderSignatory(defaultProps);
const replaceButton = getByRole(
'button',
@@ -84,30 +82,28 @@ describe('Signatory Component', () => {
expect(queryByRole('presentation')).not.toBeInTheDocument();
await user.click(replaceButton);
userEvent.click(replaceButton);
expect(getByRole('presentation')).toBeInTheDocument();
});
it('shows confirm modal on delete icon click', async () => {
const user = userEvent.setup();
const { getByLabelText, getByText } = renderSignatory(defaultProps);
const deleteIcon = getByLabelText(commonMessages.deleteTooltip.defaultMessage);
await user.click(deleteIcon);
userEvent.click(deleteIcon);
expect(getByText(messages.deleteSignatoryConfirmationMessage.defaultMessage)).toBeInTheDocument();
});
it('cancels deletion of a signatory', async () => {
const user = userEvent.setup();
it('cancels deletion of a signatory', () => {
const { getByRole } = renderSignatory(defaultProps);
const deleteIcon = getByRole('button', { name: commonMessages.deleteTooltip.defaultMessage });
await user.click(deleteIcon);
userEvent.click(deleteIcon);
const cancelButton = getByRole('button', { name: commonMessages.cardCancel.defaultMessage });
await user.click(cancelButton);
userEvent.click(cancelButton);
expect(defaultProps.handleDeleteSignatory).not.toHaveBeenCalled();
});

View File

@@ -1,7 +1,5 @@
import { Provider } from 'react-redux';
import {
render, waitFor, within,
} from '@testing-library/react';
import { render, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { initializeMockApp } from '@edx/frontend-platform';
import { IntlProvider } from '@edx/frontend-platform/i18n';
@@ -64,7 +62,6 @@ describe('CertificatesList Component', () => {
});
it('update certificate', async () => {
const user = userEvent.setup();
const {
getByText, queryByText, getByPlaceholderText, getByRole, getAllByLabelText,
} = renderComponent();
@@ -83,13 +80,13 @@ describe('CertificatesList Component', () => {
const editButtons = getAllByLabelText(messages.editTooltip.defaultMessage);
await user.click(editButtons[1]);
userEvent.click(editButtons[1]);
const nameInput = getByPlaceholderText(signatoryMessages.namePlaceholder.defaultMessage);
await user.clear(nameInput);
await user.type(nameInput, signatoryNameValue);
userEvent.clear(nameInput);
userEvent.type(nameInput, signatoryNameValue);
await user.click(getByRole('button', { name: messages.saveTooltip.defaultMessage }));
userEvent.click(getByRole('button', { name: messages.saveTooltip.defaultMessage }));
axiosMock
.onPost(getUpdateCertificateApiUrl(courseId, certificatesMock.id))
@@ -103,7 +100,6 @@ describe('CertificatesList Component', () => {
});
it('toggle edit signatory', async () => {
const user = userEvent.setup();
const {
getAllByLabelText, queryByPlaceholderText, getByTestId, getByPlaceholderText,
} = renderComponent();
@@ -111,13 +107,13 @@ describe('CertificatesList Component', () => {
expect(editButtons.length).toBe(3);
await user.click(editButtons[1]);
userEvent.click(editButtons[1]);
await waitFor(() => {
expect(getByPlaceholderText(signatoryMessages.namePlaceholder.defaultMessage)).toBeInTheDocument();
});
await user.click(within(getByTestId('signatory-form')).getByRole('button', { name: messages.cardCancel.defaultMessage }));
userEvent.click(within(getByTestId('signatory-form')).getByRole('button', { name: messages.cardCancel.defaultMessage }));
await waitFor(() => {
expect(queryByPlaceholderText(signatoryMessages.namePlaceholder.defaultMessage)).not.toBeInTheDocument();
@@ -125,11 +121,10 @@ describe('CertificatesList Component', () => {
});
it('toggle certificate edit all', async () => {
const user = userEvent.setup();
const { getByTestId } = renderComponent();
const detailsSection = getByTestId('certificate-details');
const editButton = within(detailsSection).getByLabelText(messages.editTooltip.defaultMessage);
await user.click(editButton);
userEvent.click(editButton);
await waitFor(() => {
expect(store.getState().certificates.componentMode).toBe(MODE_STATES.editAll);

View File

@@ -35,7 +35,7 @@ export async function createCertificate(courseId, certificatesData) {
getCertificateApiUrl(courseId),
prepareCertificatePayload(certificatesData),
);
/* istanbul ignore next */
return camelCaseObject(data);
}
@@ -51,7 +51,6 @@ export async function updateCertificate(courseId, certificateData) {
getUpdateCertificateApiUrl(courseId, certificateData.id),
prepareCertificatePayload(certificateData),
);
/* istanbul ignore next */
return camelCaseObject(data);
}

View File

@@ -29,11 +29,12 @@ const slice = createSlice({
fetchCertificatesSuccess: (state, { payload }) => {
Object.assign(state.certificatesData, payload);
},
createCertificateSuccess: /* istanbul ignore next */ (state, action) => {
createCertificateSuccess: (state, action) => {
state.certificatesData.certificates.push(action.payload);
},
updateCertificateSuccess: /* istanbul ignore next */ (state, action) => {
updateCertificateSuccess: (state, action) => {
const index = state.certificatesData.certificates.findIndex(c => c.id === action.payload.id);
if (index !== -1) {
state.certificatesData.certificates[index] = action.payload;
}

View File

@@ -1,4 +1,3 @@
/* istanbul ignore file */
import { RequestStatus } from '../../data/constants';
import {
hideProcessingNotification,

View File

@@ -1,9 +1,14 @@
// @ts-check
import { render, waitFor } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { initializeMockApp } from '@edx/frontend-platform';
import { AppProvider } from '@edx/frontend-platform/react';
import initializeStore from '../../../store';
import CertificatesSidebar from './CertificatesSidebar';
import messages from './messages';
import { initializeMocks, render, waitFor } from '../../../testUtils';
const courseId = 'course-123';
let store;
jest.mock('@edx/frontend-platform/i18n', () => ({
...jest.requireActual('@edx/frontend-platform/i18n'),
@@ -12,11 +17,25 @@ jest.mock('@edx/frontend-platform/i18n', () => ({
}),
}));
const renderComponent = (props) => render(<CertificatesSidebar courseId={courseId} {...props} />);
const renderComponent = (props) => render(
<AppProvider store={store} messages={{}}>
<IntlProvider locale="en">
<CertificatesSidebar courseId={courseId} {...props} />
</IntlProvider>
</AppProvider>,
);
describe('CertificatesSidebar', () => {
beforeEach(() => {
initializeMocks();
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: true,
roles: [],
},
});
store = initializeStore();
});
it('renders correctly', async () => {

View File

@@ -53,17 +53,16 @@ describe('HeaderButtons Component', () => {
});
it('updates preview URL param based on selected dropdown item', async () => {
const user = userEvent.setup();
const { getByRole } = renderComponent();
const previewLink = getByRole('link', { name: messages.headingActionsPreview.defaultMessage });
expect(previewLink).toHaveAttribute('href', expect.stringContaining(certificatesDataMock.courseModes[0]));
const dropdownButton = getByRole('button', { name: certificatesDataMock.courseModes[0] });
await user.click(dropdownButton);
userEvent.click(dropdownButton);
const verifiedMode = await getByRole('button', { name: certificatesDataMock.courseModes[1] });
await user.click(verifiedMode);
userEvent.click(verifiedMode);
await waitFor(() => {
expect(previewLink).toHaveAttribute('href', expect.stringContaining(certificatesDataMock.courseModes[1]));
@@ -71,7 +70,6 @@ describe('HeaderButtons Component', () => {
});
it('activates certificate when button is clicked', async () => {
const user = userEvent.setup();
const newCertificateData = {
...certificatesDataMock,
isActive: true,
@@ -80,7 +78,7 @@ describe('HeaderButtons Component', () => {
const { getByRole, queryByRole } = renderComponent();
const activationButton = getByRole('button', { name: messages.headingActionsActivate.defaultMessage });
await user.click(activationButton);
userEvent.click(activationButton);
axiosMock.onPost(
getUpdateCertificateApiUrl(courseId, certificatesDataMock.certificates[0].id),
@@ -99,7 +97,6 @@ describe('HeaderButtons Component', () => {
});
it('deactivates certificate when button is clicked', async () => {
const user = userEvent.setup();
axiosMock
.onGet(getCertificatesApiUrl(courseId))
.reply(200, { ...certificatesDataMock, isActive: true });
@@ -113,7 +110,7 @@ describe('HeaderButtons Component', () => {
const { getByRole, queryByRole } = renderComponent();
const deactivateButton = getByRole('button', { name: messages.headingActionsDeactivate.defaultMessage });
await user.click(deactivateButton);
userEvent.click(deactivateButton);
axiosMock.onPost(
getUpdateCertificateApiUrl(courseId, certificatesDataMock.certificates[0].id),

View File

@@ -2,7 +2,7 @@
.certificates {
.section-title {
color: var(--pgn-color-black);
color: $black;
}
.sub-header-actions {
@@ -11,7 +11,7 @@
.certificate-details {
.certificate-details__info {
color: var(--pgn-color-black);
color: $black;
justify-content: space-between;
align-items: baseline;
}
@@ -22,7 +22,7 @@
.certificate-details__info-paragraph-course-number {
flex: 1;
color: var(--pgn-color-gray-700);
color: $gray-700;
text-align: right;
}
}
@@ -74,7 +74,7 @@
}
}
@media (--pgn-size-breakpoint-max-width-xl) {
@media (max-width: map-get($grid-breakpoints, "xl")) {
.signatory {
display: flex;
flex-direction: column;

View File

@@ -43,7 +43,7 @@ export const COURSE_CREATOR_STATES = {
granted: 'granted',
denied: 'denied',
disallowedForThisSite: 'disallowed_for_this_site',
} as const;
};
export const DECODED_ROUTES = {
COURSE_UNIT: [
@@ -105,5 +105,4 @@ export const iframeMessageTypes = {
resize: 'plugin.resize',
videoFullScreen: 'plugin.videoFullScreen',
xblockEvent: 'xblock-event',
xblockScroll: 'xblock-scroll',
};

View File

@@ -112,6 +112,7 @@ const CustomLoadingIndicator = () => {
return (
<Spinner
animation="border"
size="xl"
screenReaderText={intl.formatMessage(messages.loadingMessage)}
/>
);

View File

@@ -38,7 +38,7 @@
.add-tags-button:not([disabled]):hover {
background-color: transparent;
color: var(--pgn-color-info-900) !important;
color: $info-900 !important;
}
.react-select-add-tags__control {

View File

@@ -508,7 +508,6 @@ describe('<ContentTagsCollapsible />', () => {
});
it('should handle search term change', async () => {
const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
const {
getByText, getByRole, getByDisplayValue,
} = await getComponent();
@@ -524,7 +523,7 @@ describe('<ContentTagsCollapsible />', () => {
const searchTerm = 'memo';
// Trigger a change in the search field
await user.type(searchField, searchTerm);
userEvent.type(searchField, searchTerm);
await act(async () => {
// Fast-forward time by 500 milliseconds (for the debounce delay)
@@ -536,14 +535,14 @@ describe('<ContentTagsCollapsible />', () => {
expect(getByDisplayValue(searchTerm)).toBeInTheDocument();
// Clear search
fireEvent.change(searchField, { target: { value: '' } });
userEvent.clear(searchField);
// Check that the search term has been cleared
expect(searchField).toHaveValue('');
});
it('should close dropdown selector when clicking away', async () => {
const { container, getByText, queryByText } = await getComponent();
const { getByText, queryByText } = await getComponent();
// Click on "Add a tag" button to open dropdown
const addTagsButton = getByText(messages.collapsibleAddTagsPlaceholderText.defaultMessage);
@@ -555,9 +554,10 @@ describe('<ContentTagsCollapsible />', () => {
expect(queryByText('Tag 3')).toBeInTheDocument();
// Simulate clicking outside the dropdown remove focus
const outsideElement = container.querySelector('.taxonomy-tags-count-chip');
const selectElement = container.querySelector('.react-select-add-tags__input');
fireEvent.blur(selectElement, { relatedTarget: outsideElement });
userEvent.click(document.body);
// Simulate clicking outside the dropdown again to close it
userEvent.click(document.body);
// Wait for the dropdown selector for tags to close, Tag 3 is no longer on
// the page
@@ -565,7 +565,6 @@ describe('<ContentTagsCollapsible />', () => {
});
it('should test keyboard navigation of add tags widget', async () => {
const user = userEvent.setup({ delay: null });
const {
getByText,
queryByText,
@@ -599,61 +598,59 @@ describe('<ContentTagsCollapsible />', () => {
*/
// Press tab to focus on first element in dropdown, Tag 1 should be focused
await user.keyboard('{Tab}');
userEvent.tab();
const dropdownTag1Div = queryAllByText('Tag 1')[1].closest('.dropdown-selector-tag-actions');
expect(dropdownTag1Div).toHaveFocus();
// Press right arrow to expand Tag 1, Tag 1.1 & Tag 1.2 should now be visible
await user.keyboard('{arrowright}');
userEvent.keyboard('{arrowright}');
expect(queryAllByText('Tag 1.1').length).toBe(2);
expect(queryByText('Tag 1.2')).toBeInTheDocument();
// Press left arrow to collapse Tag 1, Tag 1.1 & Tag 1.2 should not be visible
await user.keyboard('{arrowleft}');
userEvent.keyboard('{arrowleft}');
expect(queryAllByText('Tag 1.1').length).toBe(1);
expect(queryByText('Tag 1.2')).not.toBeInTheDocument();
// Press enter key to expand Tag 1, Tag 1.1 & Tag 1.2 should now be visible
await user.keyboard('{enter}');
userEvent.keyboard('{enter}');
expect(queryAllByText('Tag 1.1').length).toBe(2);
expect(queryByText('Tag 1.2')).toBeInTheDocument();
// Press down arrow to navigate to Tag 1.1, it should be focused
await user.keyboard('{arrowdown}');
userEvent.keyboard('{arrowdown}');
const dropdownTag1pt1Div = queryAllByText('Tag 1.1')[1].closest('.dropdown-selector-tag-actions');
expect(dropdownTag1pt1Div).toHaveFocus();
// Press down arrow again to navigate to Tag 1.2, it should be fouced
await user.keyboard('{arrowdown}');
userEvent.keyboard('{arrowdown}');
const dropdownTag1pt2Div = queryAllByText('Tag 1.2')[0].closest('.dropdown-selector-tag-actions');
expect(dropdownTag1pt2Div).toHaveFocus();
// Press down arrow again to navigate to Tag 2, it should be fouced
await user.keyboard('{arrowdown}');
userEvent.keyboard('{arrowdown}');
const dropdownTag2Div = queryAllByText('Tag 2')[1].closest('.dropdown-selector-tag-actions');
expect(dropdownTag2Div).toHaveFocus();
// Press up arrow to navigate back to Tag 1.2, it should be focused
await user.keyboard('{arrowup}');
userEvent.keyboard('{arrowup}');
expect(dropdownTag1pt2Div).toHaveFocus();
// Press up arrow to navigate back to Tag 1.1, it should be focused
await user.keyboard('{arrowup}');
userEvent.keyboard('{arrowup}');
expect(dropdownTag1pt1Div).toHaveFocus();
// Press up arrow again to navigate to Tag 1, it should be focused
await user.keyboard('{arrowup}');
userEvent.keyboard('{arrowup}');
expect(dropdownTag1Div).toHaveFocus();
// Press down arrow twice to navigate to Tag 1.2, it should be focsed
await user.keyboard('{arrowdown}');
await user.keyboard('{arrowdown}');
userEvent.keyboard('{arrowdown}');
userEvent.keyboard('{arrowdown}');
expect(dropdownTag1pt2Div).toHaveFocus();
// Press space key to check Tag 1.2, it should be staged
await user.keyboard('[Space]');
userEvent.keyboard('{space}');
const taxonomyId = 123;
const addedStagedTag = {
value: 'Tag%201,Tag%201.2',
@@ -662,35 +659,35 @@ describe('<ContentTagsCollapsible />', () => {
expect(data.addStagedContentTag).toHaveBeenCalledWith(taxonomyId, addedStagedTag);
// Press enter key again to uncheck Tag 1.2 (since it's a leaf), it should be unstaged
await user.keyboard('{enter}');
userEvent.keyboard('{enter}');
const tagValue = 'Tag%201,Tag%201.2';
expect(data.removeStagedContentTag).toHaveBeenCalledWith(taxonomyId, tagValue);
// Press left arrow to navigate back to Tag 1, it should be focused
await user.keyboard('{arrowleft}');
userEvent.keyboard('{arrowleft}');
expect(dropdownTag1Div).toHaveFocus();
// Press tab key it should jump to cancel button, it should be focused
await user.keyboard('{Tab}');
userEvent.tab();
const dropdownCancel = getByText(messages.collapsibleCancelStagedTagsButtonText.defaultMessage);
expect(dropdownCancel).toHaveFocus();
// Press tab again, it should exit and close the select menu, since there are not staged tags
await user.keyboard('{Tab}');
userEvent.tab();
expect(queryByText('Tag 3')).not.toBeInTheDocument();
// Press shift tab, focus back on select menu input, it should open the menu
await user.tab({ shift: true });
userEvent.tab({ shift: true });
expect(queryByText('Tag 3')).toBeInTheDocument();
// Press shift tab again, it should focus out and close the select menu
await user.tab({ shift: true });
userEvent.tab({ shift: true });
expect(queryByText('Tag 3')).not.toBeInTheDocument();
// Press tab again, the select menu should open, then press escape, it should close
await user.keyboard('{Tab}');
userEvent.tab();
expect(queryByText('Tag 3')).toBeInTheDocument();
await user.keyboard('{escape}');
userEvent.keyboard('{escape}');
expect(queryByText('Tag 3')).not.toBeInTheDocument();
});
@@ -702,7 +699,7 @@ describe('<ContentTagsCollapsible />', () => {
const xButtonAppliedTag = within(appliedTag).getByRole('button', {
name: /delete/i,
});
fireEvent.click(xButtonAppliedTag);
await userEvent.click(xButtonAppliedTag);
// Check that the applied tag has been removed
expect(appliedTag).not.toBeInTheDocument();

View File

@@ -16,7 +16,7 @@
.tags-drawer-cancel-button:hover {
background-color: transparent;
color: var(--pgn-color-gray-300) !important;
color: $gray-300 !important;
}
.other-description {
@@ -25,7 +25,7 @@
.enable-taxonomies-button:not([disabled]):hover {
background-color: transparent;
color: var(--pgn-color-info-900) !important;
color: $info-900 !important;
}
}

View File

@@ -21,7 +21,6 @@ const path = '/content/:contentId?/*';
const mockOnClose = jest.fn();
const mockSetBlockingSheet = jest.fn();
const mockNavigate = jest.fn();
const mockSidebarAction = jest.fn();
mockContentTaxonomyTagsData.applyMock();
mockTaxonomyListData.applyMock();
mockTaxonomyTagsData.applyMock();
@@ -34,7 +33,6 @@ const {
languageWithoutTagsId,
largeTagsId,
emptyTagsId,
containerTagsId,
} = mockContentTaxonomyTagsData;
jest.mock('react-router-dom', () => ({
@@ -42,20 +40,14 @@ jest.mock('react-router-dom', () => ({
useNavigate: () => mockNavigate,
}));
jest.mock('../library-authoring/common/context/SidebarContext', () => ({
...jest.requireActual('../library-authoring/common/context/SidebarContext'),
useSidebarContext: () => ({ sidebarAction: mockSidebarAction() }),
}));
const renderDrawer = (contentId, drawerParams = {}, renderPath = path, containerId = '') => {
const params = { contentId, containerId };
return render(
const renderDrawer = (contentId, drawerParams = {}) => (
render(
<ContentTagsDrawerSheetContext.Provider value={drawerParams}>
<ContentTagsDrawer {...drawerParams} />
</ContentTagsDrawerSheetContext.Provider>,
{ path: renderPath, params },
);
};
{ path, params: { contentId } },
)
);
describe('<ContentTagsDrawer />', () => {
beforeEach(async () => {
@@ -192,26 +184,6 @@ describe('<ContentTagsDrawer />', () => {
expect(screen.getByRole('button', { name: /save/i })).toBeInTheDocument();
});
it('should change to edit mode sidebar action is set to JumpToManageTags', async () => {
mockSidebarAction.mockReturnValueOnce('jump-to-manage-tags');
renderDrawer(stagedTagsId, { variant: 'component' });
expect(await screen.findByText('Taxonomy 1')).toBeInTheDocument();
// Show delete tag buttons
expect(screen.getAllByRole('button', {
name: /delete/i,
}).length).toBe(2);
// Show add a tag select
expect(screen.getByText(/add a tag/i)).toBeInTheDocument();
// Show cancel button
expect(screen.getByRole('button', { name: /cancel/i })).toBeInTheDocument();
// Show save button
expect(screen.getByRole('button', { name: /save/i })).toBeInTheDocument();
});
it('should change to read mode when click on `Cancel` on drawer variant', async () => {
renderDrawer(stagedTagsId);
expect(await screen.findByText('Taxonomy 1')).toBeInTheDocument();
@@ -694,42 +666,6 @@ describe('<ContentTagsDrawer />', () => {
await waitFor(() => expect(axiosMock.history.put[0].url).toEqual(url));
});
[
'lct:org:lib:unit:1',
'lib-collection:org:lib:1',
'lb:org:lib:html:1',
].forEach((containerId) => {
it(`should invalidate children query when update child tag when containerId is ${containerId}`, async () => {
const newPath = '/container/:containerId/';
const { axiosMock, queryClient } = initializeMocks();
const mockInvalidateQueries = jest.spyOn(queryClient, 'invalidateQueries');
const url = getContentTaxonomyTagsApiUrl(containerTagsId);
axiosMock.onPut(url).reply(200);
renderDrawer(containerTagsId, { id: containerTagsId }, newPath, containerId);
expect(await screen.findByText('Taxonomy 1')).toBeInTheDocument();
const editTagsButton = screen.getByRole('button', {
name: /edit tags/i,
});
fireEvent.click(editTagsButton);
const saveButton = screen.getByRole('button', {
name: /save/i,
});
fireEvent.click(saveButton);
await waitFor(() => expect(axiosMock.history.put[0].url).toEqual(url));
expect(mockInvalidateQueries).toHaveBeenCalledTimes(5);
expect(mockInvalidateQueries).toHaveBeenNthCalledWith(5, [
'contentLibrary',
'lib:org:lib',
'content',
'container',
containerId,
'children',
]);
});
});
it('should taxonomies must be ordered', async () => {
renderDrawer(largeTagsId);
expect(await screen.findByText('Taxonomy 1')).toBeInTheDocument();

View File

@@ -14,7 +14,6 @@ import ContentTagsCollapsible from './ContentTagsCollapsible';
import Loading from '../generic/Loading';
import { useCreateContentTagsDrawerContext } from './ContentTagsDrawerHelper';
import { ContentTagsDrawerContext, ContentTagsDrawerSheetContext } from './common/context';
import { SidebarActions, useSidebarContext } from '../library-authoring/common/context/SidebarContext';
interface TaxonomyListProps {
contentId: string;
@@ -89,6 +88,7 @@ const ContentTagsDrawerTitle = () => {
<div className="d-flex justify-content-center align-items-center flex-column">
<Spinner
animation="border"
size="xl"
screenReaderText={intl.formatMessage(messages.loadingMessage)}
/>
</div>
@@ -148,6 +148,7 @@ const ContentTagsDrawerVariantFooter = ({ onClose, readOnly }: ContentTagsDrawer
: (
<Spinner
animation="border"
size="xl"
screenReaderText={intl.formatMessage(messages.loadingMessage)}
/>
)}
@@ -195,6 +196,7 @@ const ContentTagsComponentVariantFooter = ({ readOnly = false }: ContentTagsComp
<div className="d-flex justify-content-center">
<Spinner
animation="border"
size="xl"
screenReaderText={intl.formatMessage(messages.loadingMessage)}
/>
</div>
@@ -242,7 +244,6 @@ const ContentTagsDrawer = ({
if (contentId === undefined) {
throw new Error('Error: contentId cannot be null.');
}
const { sidebarAction } = useSidebarContext();
const context = useCreateContentTagsDrawerContext(contentId, !readOnly, variant === 'drawer');
const { blockingSheet } = useContext(ContentTagsDrawerSheetContext);
@@ -259,7 +260,6 @@ const ContentTagsDrawer = ({
closeToast,
setCollapsibleToInitalState,
otherTaxonomies,
toEditMode,
} = context;
let onCloseDrawer: () => void;
@@ -302,13 +302,8 @@ const ContentTagsDrawer = ({
// First call of the initial collapsible states
React.useEffect(() => {
// Open tag edit mode when sidebarAction is JumpToManageTags
if (sidebarAction === SidebarActions.JumpToManageTags) {
toEditMode();
} else {
setCollapsibleToInitalState();
}
}, [isTaxonomyListLoaded, isContentTaxonomyTagsLoaded, sidebarAction, toEditMode]);
setCollapsibleToInitalState();
}, [isTaxonomyListLoaded, isContentTaxonomyTagsLoaded]);
const renderFooter = () => {
if (isTaxonomyListLoaded && isContentTaxonomyTagsLoaded) {

View File

@@ -234,6 +234,7 @@ const ContentTagsDropDownSelector = ({
<div className="d-flex justify-content-center align-items-center flex-row">
<Spinner
animation="border"
size="xl"
screenReaderText={intl.formatMessage(messages.loadingTagsDropdownMessage)}
/>
</div>

View File

@@ -7,7 +7,7 @@
&:hover {
background-color: transparent;
color: var(--pgn-color-info-900) !important;
color: $info-900 !important;
}
}
@@ -19,8 +19,7 @@
// In the future, this customizability should be implemented in paragon instead
input.pgn__form-checkbox-input {
&:indeterminate {
border-color: var(--pgn-color-form-control-indicator-checked-border-base);
background-image: var(--pgn-other-content-form-control-checkbox-indicator-icon-checked-base);
@extend :checked; /* stylelint-disable-line scss/at-extend-no-missing-placeholder */
}
}
}
@@ -35,6 +34,6 @@
}
.dropdown-selector-tag-actions:focus-visible {
outline: solid 2px var(--pgn-color-info-900);
outline: solid 2px $info-900;
border-radius: 4px;
}

View File

@@ -9,13 +9,13 @@
&:hover {
svg {
color: var(--pgn-color-gray-900);
color: $gray-900;
}
}
&:focus-visible {
border: 2px solid;
border-color: var(--pgn-color-gray-900);
border-color: $gray-900;
}
}
}

View File

@@ -205,7 +205,7 @@ mockContentTaxonomyTagsData.emptyTagsId = 'block-v1:EmptyTagsOrg+STC1+2023_1+typ
mockContentTaxonomyTagsData.emptyTags = {
taxonomies: [],
};
mockContentTaxonomyTagsData.containerTagsId = 'lct:StagedTagsOrg:lib:unit:container_tags';
mockContentTaxonomyTagsData.containerTagsId = 'lct:org:lib:unit:container_tags';
mockContentTaxonomyTagsData.applyMock = () => jest.spyOn(api, 'getContentTaxonomyTagsData').mockImplementation(mockContentTaxonomyTagsData);
/**

View File

@@ -7,7 +7,6 @@ import {
useMutation,
useQueryClient,
} from '@tanstack/react-query';
import { useParams } from 'react-router';
import {
getTaxonomyTagsData,
getContentTaxonomyTagsData,
@@ -15,7 +14,7 @@ import {
updateContentTaxonomyTags,
getContentTaxonomyTagsCount,
} from './api';
import { libraryAuthoringQueryKeys, libraryQueryPredicate, xblockQueryKeys } from '../../library-authoring/data/apiHooks';
import { libraryQueryPredicate, xblockQueryKeys } from '../../library-authoring/data/apiHooks';
import { getLibraryId } from '../../generic/key-utils';
/** @typedef {import("../../taxonomy/data/types.js").TagListData} TagListData */
@@ -112,7 +111,7 @@ export const useContentTaxonomyTagsData = (contentId) => (
/**
* Builds the query to get meta data about the content object
* @param {string} contentId The id of the content object
* @param {string} contentId The id of the content object (unit/component)
* @param {boolean} enabled Flag to enable/disable the query
*/
export const useContentData = (contentId, enabled) => (
@@ -130,7 +129,6 @@ export const useContentData = (contentId, enabled) => (
export const useContentTaxonomyTagsUpdater = (contentId) => {
const queryClient = useQueryClient();
const unitIframe = window.frames['xblock-iframe'];
const { containerId } = useParams();
return useMutation({
/**
@@ -143,7 +141,7 @@ export const useContentTaxonomyTagsUpdater = (contentId) => {
* >}
*/
mutationFn: ({ tagsData }) => updateContentTaxonomyTags(contentId, tagsData),
onSettled: () => {
onSettled: /* istanbul ignore next */ () => {
queryClient.invalidateQueries({ queryKey: ['contentTaxonomyTags', contentId] });
/// Invalidate query with pattern on course outline
let contentPattern;
@@ -160,11 +158,6 @@ export const useContentTaxonomyTagsUpdater = (contentId) => {
queryClient.invalidateQueries(xblockQueryKeys.componentMetadata(contentId));
// Invalidate content search to update tags count
queryClient.invalidateQueries(['content_search'], { predicate: (query) => libraryQueryPredicate(query, libraryId) });
// If the tags for an item were edited from a container page (Unit, Subsection, Section),
// invalidate children query to fetch count again.
if (containerId) {
queryClient.invalidateQueries(libraryAuthoringQueryKeys.containerChildren(containerId));
}
}
},
onSuccess: /* istanbul ignore next */ () => {

View File

@@ -157,7 +157,7 @@ describe('useContentTaxonomyTagsUpdater', () => {
const contentId = 'testerContent';
const taxonomyId = 123;
const mutation = renderHook(() => useContentTaxonomyTagsUpdater(contentId)).result.current;
const mutation = useContentTaxonomyTagsUpdater(contentId);
const tagsData = [{
taxonomy: taxonomyId,
tags: ['tag1', 'tag2'],

View File

@@ -1,4 +1,5 @@
import { useState, useMemo } from 'react';
// @ts-check
import React, { useState, useMemo } from 'react';
import {
Card, Stack, Button, Collapsible, Icon,
} from '@openedx/paragon';
@@ -9,19 +10,10 @@ import { ContentTagsDrawerSheet } from '..';
import messages from '../messages';
import { useContentTaxonomyTagsData } from '../data/apiHooks';
import type { ContentTaxonomyTagData, Tag } from '../data/types';
import { LoadingSpinner } from '../../generic/Loading';
import TagsTree from '../TagsTree';
interface TagsSidebarBodyProps {
readOnly: boolean
}
type TagTree = {
[key: string]: { children: TagTree, canChangeObjecttag: boolean, canDeleteObjecttag: boolean }
};
const TagsSidebarBody = ({ readOnly }: TagsSidebarBodyProps) => {
const TagsSidebarBody = () => {
const intl = useIntl();
const [showManageTags, setShowManageTags] = useState(false);
const contentId = useParams().blockId;
@@ -32,8 +24,8 @@ const TagsSidebarBody = ({ readOnly }: TagsSidebarBodyProps) => {
isSuccess: isContentTaxonomyTagsLoaded,
} = useContentTaxonomyTagsData(contentId || '');
const buildTagsTree = (contentTags: Tag[]) => {
const resultTree: TagTree = {};
const buildTagsTree = (contentTags) => {
const resultTree = {};
contentTags.forEach(item => {
let currentLevel = resultTree;
@@ -54,7 +46,7 @@ const TagsSidebarBody = ({ readOnly }: TagsSidebarBodyProps) => {
};
const tree = useMemo(() => {
const result: (Omit<ContentTaxonomyTagData, 'tags'> & { tags: TagTree })[] = [];
const result = [];
if (isContentTaxonomyTagsLoaded && contentTaxonomyTagsData) {
contentTaxonomyTagsData.taxonomies.forEach((taxonomy) => {
result.push({
@@ -96,13 +88,7 @@ const TagsSidebarBody = ({ readOnly }: TagsSidebarBodyProps) => {
</div>
)}
<Button
className="mt-3 ml-2"
variant="outline-primary"
size="sm"
onClick={() => setShowManageTags(true)}
disabled={readOnly}
>
<Button className="mt-3 ml-2" variant="outline-primary" size="sm" onClick={() => setShowManageTags(true)}>
{intl.formatMessage(messages.manageTagsButton)}
</Button>
</Stack>
@@ -116,4 +102,6 @@ const TagsSidebarBody = ({ readOnly }: TagsSidebarBodyProps) => {
);
};
TagsSidebarBody.propTypes = {};
export default TagsSidebarBody;

View File

@@ -1,14 +1,10 @@
import TagsSidebarHeader from './TagsSidebarHeader';
import TagsSidebarBody from './TagsSidebarBody';
interface TagsSidebarControlsProps {
readOnly: boolean,
}
const TagsSidebarControls = ({ readOnly }: TagsSidebarControlsProps) => (
const TagsSidebarControls = () => (
<>
<TagsSidebarHeader />
<TagsSidebarBody readOnly={readOnly} />
<TagsSidebarBody />
</>
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { injectIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import messages from './messages';
@@ -33,4 +33,4 @@ AriaLiveRegion.propTypes = {
enableQuality: PropTypes.bool.isRequired,
};
export default AriaLiveRegion;
export default injectIntl(AriaLiveRegion);

View File

@@ -2,10 +2,11 @@ import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { ActionRow, Button, Icon } from '@openedx/paragon';
import { useSelector } from 'react-redux';
import { CheckCircle, RadioButtonUnchecked } from '@openedx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';
import { useWaffleFlags } from '../../data/apiHooks';
import { getWaffleFlags } from '../../data/selectors';
import messages from './messages';
const getUpdateLinks = (courseId, waffleFlags) => {
@@ -34,7 +35,7 @@ const ChecklistItemBody = ({
isCompleted,
}) => {
const intl = useIntl();
const waffleFlags = useWaffleFlags(courseId);
const waffleFlags = useSelector(getWaffleFlags);
const updateLinks = getUpdateLinks(courseId, waffleFlags);
return (

View File

@@ -1,10 +1,11 @@
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { injectIntl, FormattedMessage, FormattedNumber } from '@edx/frontend-platform/i18n';
import { Icon } from '@openedx/paragon';
import { Link } from 'react-router-dom';
import { ModeComment } from '@openedx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';
import { useWaffleFlags } from '../../data/apiHooks';
import { getWaffleFlags } from '../../data/selectors';
import messages from './messages';
const ChecklistItemComment = ({
@@ -12,7 +13,7 @@ const ChecklistItemComment = ({
checkId,
data,
}) => {
const waffleFlags = useWaffleFlags(courseId);
const waffleFlags = useSelector(getWaffleFlags);
const getPathToCourseOutlinePage = (assignmentId) => (waffleFlags.useNewCourseOutlinePage
? `/course/${courseId}#${assignmentId}` : `${getConfig().STUDIO_BASE_URL}/course/${courseId}#${assignmentId}`);

View File

@@ -1,6 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl } from '@edx/frontend-platform/i18n';
import { Container, Stack } from '@openedx/paragon';
import { LoadingSpinner } from '../../generic/Loading';
import { getCompletionCount, useChecklistState } from './hooks';
import ChecklistItemBody from './ChecklistItemBody';
@@ -127,4 +129,4 @@ ChecklistSection.propTypes = {
isLoading: PropTypes.bool.isRequired,
};
export default ChecklistSection;
export default injectIntl(ChecklistSection);

View File

@@ -13,10 +13,10 @@
.assignment-list {
display: inline;
padding-inline-start: var(--pgn-spacing-spacer-1);
padding-inline-start: map-get($spacers, 1);
}
//complete checklist item style
.checklist-item-complete {
box-shadow: -5px 0 0 0 var(--pgn-color-success-500);
box-shadow: -5px 0 0 0 $success-500;
}

View File

@@ -4,7 +4,9 @@ import {
initializeMocks, render, screen, within,
} from '../../testUtils';
import { getApiWaffleFlagsUrl } from '../../data/api';
import { fetchWaffleFlags } from '../../data/thunks';
import { generateCourseLaunchData } from '../factories/mockApiResponses';
import { executeThunk } from '../../utils';
import { checklistItems } from './utils/courseChecklistData';
import messages from './messages';
@@ -32,7 +34,7 @@ const renderComponent = (props) => {
describe('ChecklistSection', () => {
beforeEach(async () => {
const { axiosMock } = initializeMocks();
const { axiosMock, reduxStore } = initializeMocks();
axiosMock
.onGet(getApiWaffleFlagsUrl(courseId))
.reply(200, {
@@ -41,6 +43,7 @@ describe('ChecklistSection', () => {
useNewScheduleDetailsPage: true,
useNewCourseOutlinePage: true,
});
await executeThunk(fetchWaffleFlags(courseId), reduxStore.dispatch);
});
it('a heading using the dataHeading prop', () => {

View File

@@ -71,6 +71,16 @@ const messages = defineMessages({
defaultMessage: 'Learners engage best with short videos followed by opportunities to practice. Ensure that 80% or more of course videos are less than 10 minutes long.',
description: 'Description for a section that prompts a user to follow best practices for video length',
},
mobileFriendlyVideoShortDescription: {
id: 'mobileFriendlyVideoShortDescription',
defaultMessage: 'Create mobile-friendly video',
description: 'Label for a section that describes mobile friendly videos',
},
mobileFriendlyVideoLongDescription: {
id: 'mobileFriendlyVideoLongDescription',
defaultMessage: 'Mobile-friendly videos can be viewed across all supported devices. Ensure that at least 90% of course videos are mobile friendly by uploading course videos to the edX video pipeline.',
description: 'Description for a section that prompts a user to follow best practices for mobile friendly videos',
},
diverseSequencesShortDescription: {
id: 'diverseSequencesShortDescription',
defaultMessage: 'Build diverse learning sequences',

View File

@@ -36,6 +36,10 @@ export const checklistItems = {
id: 'videoDuration',
pacingTypeFilter: filters.ALL,
},
{
id: 'mobileFriendlyVideo',
pacingTypeFilter: filters.ALL,
},
{
id: 'diverseSequences',
pacingTypeFilter: filters.ALL,

View File

@@ -35,8 +35,18 @@ export const hasAssignmentDeadlines = (assignments, dates) => {
export const hasShortVideoDuration = (videos) => {
if (videos.totalNumber === 0) {
return false;
} if (videos.totalNumber > 0 && videos.durations.median !== null && videos.durations.median <= 600) {
return true;
} if (videos.totalNumber > 0 && videos.durations.median <= 600) {
return true;
}
return false;
};
export const hasMobileFriendlyVideos = (videos) => {
if (videos.totalNumber === 0) {
return true;
} if (videos.totalNumber > 0 && (videos.numMobileEncoded / videos.totalNumber) >= 0.9) {
return true;
}
@@ -47,7 +57,7 @@ export const hasDiverseSequences = (subsections) => {
if (subsections.totalVisible === 0) {
return false;
} if (subsections.totalVisible > 0) {
return ((subsections.numWithOneBlockType / subsections.totalVisible) <= 0.2);
return ((subsections.numWithOneBlockType / subsections.totalVisible) < 0.2);
}
return false;
@@ -58,7 +68,7 @@ export const hasWeeklyHighlights = sections => (
);
export const hasShortUnitDepth = units => (
units.numBlocks.median <= 3 && units.totalVisible > 0
units.numBlocks.median <= 3
);
export const hasProctoringEscalationEmail = proctoring => (

View File

@@ -189,8 +189,8 @@ describe('courseCheckValidators utility functions', () => {
);
describe('hasShortVideoDuration', () => {
it('returns false if course run has no videos', () => {
expect(validators.hasShortVideoDuration({ totalNumber: 0 })).toEqual(false);
it('returns true if course run has no videos', () => {
expect(validators.hasShortVideoDuration({ totalNumber: 0 })).toEqual(true);
});
it('returns true if course run videos have a median duration <= to 600', () => {
@@ -204,6 +204,22 @@ describe('courseCheckValidators utility functions', () => {
});
});
describe('hasMobileFriendlyVideos', () => {
it('returns true if course run has no videos', () => {
expect(validators.hasMobileFriendlyVideos({ totalNumber: 0 })).toEqual(true);
});
it('returns true if course run videos are >= 90% mobile friendly', () => {
expect(validators.hasMobileFriendlyVideos({ totalNumber: 10, numMobileEncoded: 9 }))
.toEqual(true);
});
it('returns true if course run videos are < 90% mobile friendly', () => {
expect(validators.hasMobileFriendlyVideos({ totalNumber: 10, numMobileEncoded: 8 }))
.toEqual(false);
});
});
describe('hasDiverseSequences', () => {
it('returns true if < 20% of visible subsections have more than one block type', () => {
expect(validators.hasDiverseSequences({ totalVisible: 10, numWithOneBlockType: 1 }))
@@ -248,7 +264,6 @@ describe('courseCheckValidators utility functions', () => {
describe('hasShortUnitDepth', () => {
it('returns true when course run has median number of blocks <= 3', () => {
const units = {
totalVisible: 2,
numBlocks: {
median: 3,
},
@@ -259,7 +274,6 @@ describe('courseCheckValidators utility functions', () => {
it('returns false when course run has median number of blocks > 3', () => {
const units = {
totalVisible: 2,
numBlocks: {
median: 4,
},

View File

@@ -14,6 +14,8 @@ const getValidatedValue = (data, id) => {
return healthValidators.hasAssignmentDeadlines(data.assignments, data.dates);
case 'videoDuration':
return healthValidators.hasShortVideoDuration(data.videos);
case 'mobileFriendlyVideo':
return healthValidators.hasMobileFriendlyVideos(data.videos);
case 'diverseSequences':
return healthValidators.hasDiverseSequences(data.subsections);
case 'weeklyHighlights':

View File

@@ -88,6 +88,20 @@ describe('getValidatedValue utility function', () => {
expect(spy).toHaveBeenCalledTimes(1);
});
it('mobile friendly video', () => {
const spy = jest.fn();
localValidators.hasMobileFriendlyVideos = spy;
const props = {
data: {
videos: {},
},
};
getValidatedValue(props, 'mobileFriendlyVideo');
expect(spy).toHaveBeenCalledTimes(1);
});
it('diverse sequences', () => {
const spy = jest.fn();
localValidators.hasDiverseSequences = spy;

View File

@@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Helmet } from 'react-helmet';
import { useDispatch, useSelector } from 'react-redux';
import { Container, Stack } from '@openedx/paragon';
@@ -17,8 +17,9 @@ import ConnectionErrorAlert from '../generic/ConnectionErrorAlert';
const CourseChecklist = ({
courseId,
// injected,
intl,
}) => {
const intl = useIntl();
const dispatch = useDispatch();
const courseDetails = useModel('courseDetails', courseId);
const enableQuality = getConfig().ENABLE_CHECKLIST_QUALITY === 'true';
@@ -96,6 +97,8 @@ const CourseChecklist = ({
CourseChecklist.propTypes = {
courseId: PropTypes.string.isRequired,
// injected
intl: intlShape.isRequired,
};
export default CourseChecklist;
export default injectIntl(CourseChecklist);

View File

@@ -75,90 +75,48 @@ describe('<CourseLibraries />', () => {
});
it('shows alert when out of sync components are present', async () => {
const user = userEvent.setup();
await renderCourseLibrariesPage(mockGetEntityLinks.courseKey);
const allTab = await screen.findByRole('tab', { name: 'Libraries' });
const reviewTab = await screen.findByRole('tab', { name: 'Review Content Updates 7' });
const reviewTab = await screen.findByRole('tab', { name: 'Review Content Updates 5' });
// review tab should be open by default as outOfSyncCount is greater than 0
expect(reviewTab).toHaveAttribute('aria-selected', 'true');
await user.click(allTab);
userEvent.click(allTab);
const alert = await screen.findByRole('alert');
expect(await within(alert).findByText(
'7 library components are out of sync. Review updates to accept or ignore changes',
'5 library components are out of sync. Review updates to accept or ignore changes',
)).toBeInTheDocument();
expect(allTab).toHaveAttribute('aria-selected', 'true');
const reviewBtn = await screen.findByRole('button', { name: 'Review' });
await user.click(reviewBtn);
userEvent.click(reviewBtn);
expect(allTab).toHaveAttribute('aria-selected', 'false');
expect(await screen.findByRole('tab', { name: 'Review Content Updates 7' })).toHaveAttribute('aria-selected', 'true');
expect(await screen.findByRole('tab', { name: 'Review Content Updates 5' })).toHaveAttribute('aria-selected', 'true');
expect(alert).not.toBeInTheDocument();
});
it('hide alert on dismiss', async () => {
const user = userEvent.setup();
await renderCourseLibrariesPage(mockGetEntityLinks.courseKey);
const reviewTab = await screen.findByRole('tab', { name: 'Review Content Updates 7' });
const reviewTab = await screen.findByRole('tab', { name: 'Review Content Updates 5' });
// review tab should be open by default as outOfSyncCount is greater than 0
expect(reviewTab).toHaveAttribute('aria-selected', 'true');
const allTab = await screen.findByRole('tab', { name: 'Libraries' });
await user.click(allTab);
userEvent.click(allTab);
expect(allTab).toHaveAttribute('aria-selected', 'true');
const alert = await screen.findByRole('alert');
expect(await within(alert).findByText(
'7 library components are out of sync. Review updates to accept or ignore changes',
'5 library components are out of sync. Review updates to accept or ignore changes',
)).toBeInTheDocument();
const dismissBtn = await screen.findByRole('button', { name: 'Dismiss' });
await user.click(dismissBtn);
userEvent.click(dismissBtn);
expect(allTab).toHaveAttribute('aria-selected', 'true');
waitFor(() => expect(alert).not.toBeInTheDocument());
// review updates button
const reviewActionBtn = await screen.findByRole('button', { name: 'Review Updates' });
await user.click(reviewActionBtn);
expect(await screen.findByRole('tab', { name: 'Review Content Updates 7' })).toHaveAttribute('aria-selected', 'true');
});
it('show alert if max lastPublishedDate is greated than the local storage value', async () => {
const user = userEvent.setup();
const lastPublishedDate = new Date('2025-05-01T22:20:44.989042Z');
localStorage.setItem(
`outOfSyncCountAlert-${mockGetEntityLinks.courseKey}`,
String(lastPublishedDate.getTime() - 1000),
);
await renderCourseLibrariesPage(mockGetEntityLinks.courseKey);
const allTab = await screen.findByRole('tab', { name: 'Libraries' });
const reviewTab = await screen.findByRole('tab', { name: 'Review Content Updates 7' });
// review tab should be open by default as outOfSyncCount is greater than 0
expect(reviewTab).toHaveAttribute('aria-selected', 'true');
await user.click(allTab);
const alert = await screen.findByRole('alert');
expect(await within(alert).findByText(
'7 library components are out of sync. Review updates to accept or ignore changes',
)).toBeInTheDocument();
});
it('doesnt show alert if max lastPublishedDate is less than the local storage value', async () => {
const user = userEvent.setup();
const lastPublishedDate = new Date('2025-05-01T22:20:44.989042Z');
localStorage.setItem(
`outOfSyncCountAlert-${mockGetEntityLinks.courseKey}`,
String(lastPublishedDate.getTime() + 1000),
);
await renderCourseLibrariesPage(mockGetEntityLinks.courseKey);
const allTab = await screen.findByRole('tab', { name: 'Libraries' });
const reviewTab = await screen.findByRole('tab', { name: 'Review Content Updates 7' });
// review tab should be open by default as outOfSyncCount is greater than 0
expect(reviewTab).toHaveAttribute('aria-selected', 'true');
await user.click(allTab);
expect(allTab).toHaveAttribute('aria-selected', 'true');
expect(screen.queryByRole('alert')).not.toBeInTheDocument();
userEvent.click(reviewActionBtn);
expect(await screen.findByRole('tab', { name: 'Review Content Updates 5' })).toHaveAttribute('aria-selected', 'true');
});
});
@@ -193,138 +151,94 @@ describe('<CourseLibraries ReviewTab />', () => {
});
it('shows all readyToSync links', async () => {
await renderCourseLibrariesReviewPage();
await renderCourseLibrariesReviewPage(mockGetEntityLinksSummaryByDownstreamContext.courseKey);
const updateBtns = await screen.findAllByRole('button', { name: 'Update' });
expect(updateBtns.length).toEqual(7);
expect(updateBtns.length).toEqual(5);
const ignoreBtns = await screen.findAllByRole('button', { name: 'Ignore' });
expect(ignoreBtns.length).toEqual(7);
expect(ignoreBtns.length).toEqual(5);
});
test.each([
{
label: 'update changes works with components',
itemIndex: 0,
expectedToastMsg: 'Success! "Dropdown" is updated',
},
{
label: 'update changes works with containers',
itemIndex: 5,
expectedToastMsg: 'Success! "Unit 1" is updated',
},
])('$label', async ({ itemIndex, expectedToastMsg }) => {
const user = userEvent.setup();
it('update changes works', async () => {
const mockInvalidateQueries = jest.spyOn(queryClient, 'invalidateQueries');
const usageKey = mockGetEntityLinks.response[itemIndex].downstreamUsageKey;
const usageKey = mockGetEntityLinks.response.results[0].downstreamUsageKey;
axiosMock.onPost(libraryBlockChangesUrl(usageKey)).reply(200, {});
await renderCourseLibrariesReviewPage(mockGetEntityLinksSummaryByDownstreamContext.courseKey);
const updateBtns = await screen.findAllByRole('button', { name: 'Update' });
expect(updateBtns.length).toEqual(7);
await user.click(updateBtns[itemIndex]);
expect(updateBtns.length).toEqual(5);
userEvent.click(updateBtns[0]);
await waitFor(() => {
expect(axiosMock.history.post.length).toEqual(1);
});
expect(axiosMock.history.post[0].url).toEqual(libraryBlockChangesUrl(usageKey));
expect(mockShowToast).toHaveBeenCalledWith(expectedToastMsg);
expect(mockInvalidateQueries).toHaveBeenCalledWith({ queryKey: ['courseLibraries', 'course-v1:OpenEdx+DemoX+CourseX'] });
expect(mockShowToast).toHaveBeenCalledWith('Success! "Dropdown" is updated');
expect(mockInvalidateQueries).toHaveBeenCalledWith(['courseLibraries', 'course-v1:OpenEdx+DemoX+CourseX']);
});
test.each([
{
label: 'update changes works in preview modal with components',
itemIndex: 0,
expectedToastMsg: 'Success! "Dropdown" is updated',
},
{
label: 'update changes works in preview modal with containers',
itemIndex: 5,
expectedToastMsg: 'Success! "Unit 1" is updated',
},
])('$label', async ({ itemIndex, expectedToastMsg }) => {
const user = userEvent.setup();
it('update changes works in preview modal', async () => {
const mockInvalidateQueries = jest.spyOn(queryClient, 'invalidateQueries');
const usageKey = mockGetEntityLinks.response[itemIndex].downstreamUsageKey;
const usageKey = mockGetEntityLinks.response.results[0].downstreamUsageKey;
axiosMock.onPost(libraryBlockChangesUrl(usageKey)).reply(200, {});
await renderCourseLibrariesReviewPage(mockGetEntityLinksSummaryByDownstreamContext.courseKey);
const previewBtns = await screen.findAllByRole('button', { name: 'Review Updates' });
expect(previewBtns.length).toEqual(7);
await user.click(previewBtns[itemIndex]);
expect(previewBtns.length).toEqual(5);
userEvent.click(previewBtns[0]);
const dialog = await screen.findByRole('dialog');
const confirmBtn = await within(dialog).findByRole('button', { name: 'Accept changes' });
await user.click(confirmBtn);
userEvent.click(confirmBtn);
await waitFor(() => {
expect(axiosMock.history.post.length).toEqual(1);
});
expect(axiosMock.history.post[0].url).toEqual(libraryBlockChangesUrl(usageKey));
expect(mockShowToast).toHaveBeenCalledWith(expectedToastMsg);
expect(mockInvalidateQueries).toHaveBeenCalledWith({ queryKey: ['courseLibraries', 'course-v1:OpenEdx+DemoX+CourseX'] });
expect(mockShowToast).toHaveBeenCalledWith('Success! "Dropdown" is updated');
expect(mockInvalidateQueries).toHaveBeenCalledWith(['courseLibraries', 'course-v1:OpenEdx+DemoX+CourseX']);
});
test.each([
{
label: 'ignore change works with components',
itemIndex: 0,
expectedToastMsg: '"Dropdown" will remain out of sync with library content. You will be notified when this component is updated again.',
},
{
label: 'ignore change works with containers',
itemIndex: 5,
expectedToastMsg: '"Unit 1" will remain out of sync with library content. You will be notified when this component is updated again.',
},
])('$label', async ({ itemIndex, expectedToastMsg }) => {
const user = userEvent.setup();
it('ignore change works', async () => {
const mockInvalidateQueries = jest.spyOn(queryClient, 'invalidateQueries');
const usageKey = mockGetEntityLinks.response[itemIndex].downstreamUsageKey;
const usageKey = mockGetEntityLinks.response.results[0].downstreamUsageKey;
axiosMock.onDelete(libraryBlockChangesUrl(usageKey)).reply(204, {});
await renderCourseLibrariesReviewPage(mockGetEntityLinksSummaryByDownstreamContext.courseKey);
const ignoreBtns = await screen.findAllByRole('button', { name: 'Ignore' });
expect(ignoreBtns.length).toEqual(7);
expect(ignoreBtns.length).toEqual(5);
// Show confirmation modal on clicking ignore.
await user.click(ignoreBtns[itemIndex]);
userEvent.click(ignoreBtns[0]);
const dialog = await screen.findByRole('dialog', { name: 'Ignore these changes?' });
expect(dialog).toBeInTheDocument();
const confirmBtn = await within(dialog).findByRole('button', { name: 'Ignore' });
await user.click(confirmBtn);
userEvent.click(confirmBtn);
await waitFor(() => {
expect(axiosMock.history.delete.length).toEqual(1);
});
expect(axiosMock.history.delete[0].url).toEqual(libraryBlockChangesUrl(usageKey));
expect(mockShowToast).toHaveBeenCalledWith(expectedToastMsg);
expect(mockInvalidateQueries).toHaveBeenCalledWith({ queryKey: ['courseLibraries', 'course-v1:OpenEdx+DemoX+CourseX'] });
expect(mockShowToast).toHaveBeenCalledWith(
'"Dropdown" will remain out of sync with library content. You will be notified when this component is updated again.',
);
expect(mockInvalidateQueries).toHaveBeenCalledWith(['courseLibraries', 'course-v1:OpenEdx+DemoX+CourseX']);
});
test.each([
{
label: 'ignore change works with components',
itemIndex: 0,
expectedToastMsg: '"Dropdown" will remain out of sync with library content. You will be notified when this component is updated again.',
},
{
label: 'ignore change works with containers',
itemIndex: 5,
expectedToastMsg: '"Unit 1" will remain out of sync with library content. You will be notified when this component is updated again.',
},
])('$label', async ({ itemIndex, expectedToastMsg }) => {
const user = userEvent.setup();
it('ignore change works in preview', async () => {
const mockInvalidateQueries = jest.spyOn(queryClient, 'invalidateQueries');
const usageKey = mockGetEntityLinks.response[itemIndex].downstreamUsageKey;
const usageKey = mockGetEntityLinks.response.results[0].downstreamUsageKey;
axiosMock.onDelete(libraryBlockChangesUrl(usageKey)).reply(204, {});
await renderCourseLibrariesReviewPage(mockGetEntityLinksSummaryByDownstreamContext.courseKey);
const previewBtns = await screen.findAllByRole('button', { name: 'Review Updates' });
expect(previewBtns.length).toEqual(7);
await user.click(previewBtns[itemIndex]);
expect(previewBtns.length).toEqual(5);
userEvent.click(previewBtns[0]);
const previewDialog = await screen.findByRole('dialog');
const ignoreBtn = await within(previewDialog).findByRole('button', { name: 'Ignore changes' });
await user.click(ignoreBtn);
userEvent.click(ignoreBtn);
// Show confirmation modal on clicking ignore.
const dialog = await screen.findByRole('dialog', { name: 'Ignore these changes?' });
expect(dialog).toBeInTheDocument();
const confirmBtn = await within(dialog).findByRole('button', { name: 'Ignore' });
await user.click(confirmBtn);
userEvent.click(confirmBtn);
await waitFor(() => {
expect(axiosMock.history.delete.length).toEqual(1);
});
expect(axiosMock.history.delete[0].url).toEqual(libraryBlockChangesUrl(usageKey));
expect(mockShowToast).toHaveBeenCalledWith(expectedToastMsg);
expect(mockInvalidateQueries).toHaveBeenCalledWith({ queryKey: ['courseLibraries', 'course-v1:OpenEdx+DemoX+CourseX'] });
expect(mockShowToast).toHaveBeenCalledWith(
'"Dropdown" will remain out of sync with library content. You will be notified when this component is updated again.',
);
expect(mockInvalidateQueries).toHaveBeenCalledWith(['courseLibraries', 'course-v1:OpenEdx+DemoX+CourseX']);
});
});

View File

@@ -164,7 +164,7 @@ export const CourseLibraries: React.FC<Props> = ({ courseId }) => {
if (tabKey !== CourseLibraryTabs.review) {
return null;
}
if (!outOfSyncCount) {
if (!outOfSyncCount || outOfSyncCount === 0) {
return (
<Stack direction="horizontal" gap={2}>
<Icon src={CheckCircle} size="xs" />

View File

@@ -18,11 +18,12 @@ interface OutOfSyncAlertProps {
* in course can be updated. Following are the conditions for displaying the alert.
*
* * The alert is displayed if components are out of sync.
* * If the user clicks on dismiss button, the state of dismiss is stored in localstorage of user
* in this format: outOfSyncCountAlert-${courseId} = <datetime value in milliseconds>.
* * If there are not new published components for the course and the user opens outline
* * If the user clicks on dismiss button, the state is stored in localstorage of user
* in this format: outOfSyncCountAlert-${courseId} = <number of out of sync components>.
* * If the number of sync components don't change for the course and the user opens outline
* in the same browser, they don't see the alert again.
* * If there is a new published component upstream, the alert is displayed again.
* * If the number changes, i.e., if a new component is out of sync or the user updates or ignores
* a component, the alert is displayed again.
*/
export const OutOfSyncAlert: React.FC<OutOfSyncAlertProps> = ({
showAlert,
@@ -33,9 +34,7 @@ export const OutOfSyncAlert: React.FC<OutOfSyncAlertProps> = ({
}) => {
const intl = useIntl();
const { data, isLoading } = useEntityLinksSummaryByDownstreamContext(courseId);
const outOfSyncCount = data?.reduce((count, lib) => count + (lib.readyToSyncCount || 0), 0);
const lastPublishedDate = data?.map(lib => new Date(lib.lastPublishedAt || 0).getTime())
.reduce((acc, lastPublished) => Math.max(lastPublished, acc), 0);
const outOfSyncCount = data?.reduce((count, lib) => count + lib.readyToSyncCount, 0);
const alertKey = `outOfSyncCountAlert-${courseId}`;
useEffect(() => {
@@ -47,14 +46,13 @@ export const OutOfSyncAlert: React.FC<OutOfSyncAlertProps> = ({
setShowAlert(false);
return;
}
const dismissedAlertDate = parseInt(localStorage.getItem(alertKey) ?? '0', 10);
setShowAlert((lastPublishedDate ?? 0) > dismissedAlertDate);
}, [outOfSyncCount, lastPublishedDate, isLoading, data]);
const dismissedAlert = localStorage.getItem(alertKey);
setShowAlert(parseInt(dismissedAlert || '', 10) !== outOfSyncCount);
}, [outOfSyncCount, isLoading, data]);
const dismissAlert = () => {
setShowAlert(false);
localStorage.setItem(alertKey, Date.now().toString());
localStorage.setItem(alertKey, String(outOfSyncCount));
onDismiss?.();
};

View File

@@ -1,5 +1,5 @@
import React, {
useCallback, useContext, useMemo, useState,
useCallback, useContext, useEffect, useMemo, useState,
} from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
@@ -14,12 +14,14 @@ import {
useToggle,
} from '@openedx/paragon';
import { tail, keyBy } from 'lodash';
import {
tail, keyBy, orderBy, merge, omitBy,
} from 'lodash';
import { useQueryClient } from '@tanstack/react-query';
import { Loop } from '@openedx/paragon/icons';
import { Loop, Warning } from '@openedx/paragon/icons';
import messages from './messages';
import previewChangesMessages from '../course-unit/preview-changes/messages';
import { invalidateLinksQuery, useEntityLinks } from './data/apiHooks';
import { courseLibrariesQueryKeys, useEntityLinks } from './data/apiHooks';
import {
SearchContextProvider, SearchKeywordsField, useSearchContext, BlockTypeLabel, Highlight, SearchSortWidget,
} from '../search-manager';
@@ -35,45 +37,28 @@ import { useLoadOnScroll } from '../hooks';
import DeleteModal from '../generic/delete-modal/DeleteModal';
import { PublishableEntityLink } from './data/api';
import AlertError from '../generic/alert-error';
import NewsstandIcon from '../generic/NewsstandIcon';
import AlertMessage from '../generic/alert-message';
interface Props {
courseId: string;
}
interface ItemCardProps {
interface BlockCardProps {
info: ContentHit;
itemType: 'component' | 'container';
actions?: React.ReactNode;
libraryName?: string;
}
const ItemCard: React.FC<ItemCardProps> = ({
info,
itemType,
actions,
libraryName,
}) => {
const BlockCard: React.FC<BlockCardProps> = ({ info, actions }) => {
const intl = useIntl();
const itemIcon = getItemIcon(info.blockType);
const componentIcon = getItemIcon(info.blockType);
const breadcrumbs = tail(info.breadcrumbs) as Array<{ displayName: string, usageKey: string }>;
const getItemLink = useCallback(() => {
const getBlockLink = useCallback(() => {
let key = info.usageKey;
if (breadcrumbs?.length > 1) {
key = breadcrumbs[breadcrumbs.length - 1].usageKey || key;
}
if (itemType === 'component') {
return `${getConfig().STUDIO_BASE_URL}/container/${key}`;
}
if (itemType === 'container') {
const encodedKey = encodeURIComponent(key);
return `${getConfig().STUDIO_BASE_URL}/course/${info.contextKey}?show=${encodedKey}`;
}
// istanbul ignore next
return '';
return `${getConfig().STUDIO_BASE_URL}/container/${key}`;
}, [info]);
return (
@@ -87,7 +72,7 @@ const ItemCard: React.FC<ItemCardProps> = ({
<Stack direction="horizontal" gap={2}>
<Stack direction="vertical" gap={1}>
<Stack direction="horizontal" gap={1} className="micro text-gray-500">
<Icon src={itemIcon} size="xs" />
<Icon src={componentIcon} size="xs" />
<BlockTypeLabel blockType={info.blockType} />
</Stack>
<Stack direction="horizontal" className="small" gap={1}>
@@ -96,27 +81,15 @@ const ItemCard: React.FC<ItemCardProps> = ({
</strong>
</Stack>
<Stack direction="horizontal" className="micro" gap={3}>
{libraryName && (
<Stack direction="horizontal" gap={2}>
<Icon src={NewsstandIcon} size="xs" />
{libraryName}
</Stack>
)}
{intl.formatMessage(messages.breadcrumbLabel)}
<Hyperlink showLaunchIcon={false} destination={getItemLink()} target="_blank">
{info.blockType === 'chapter' ? (
<div className="micro text-gray-700 border-bottom">
{intl.formatMessage(messages.viewSectionInCourseLabel)}
</div>
) : (
<Breadcrumb
className="micro text-gray-700 border-bottom"
ariaLabel={intl.formatMessage(messages.breadcrumbLabel)}
links={breadcrumbs.map((breadcrumb) => ({ label: breadcrumb.displayName }))}
spacer={<span className="custom-spacer">/</span>}
linkAs="span"
/>
)}
<Hyperlink showLaunchIcon={false} destination={getBlockLink()} target="_blank">
<Breadcrumb
className="micro text-gray-700 border-bottom"
ariaLabel={intl.formatMessage(messages.breadcrumbLabel)}
links={breadcrumbs.map((breadcrumb) => ({ label: breadcrumb.displayName }))}
spacer={<span className="custom-spacer">/</span>}
linkAs="span"
/>
</Hyperlink>
</Stack>
</Stack>
@@ -127,31 +100,37 @@ const ItemCard: React.FC<ItemCardProps> = ({
);
};
const ItemReviewList = ({
outOfSyncItems,
const ComponentReviewList = ({
outOfSyncComponents,
onSearchUpdate,
}: {
outOfSyncItems: PublishableEntityLink[];
outOfSyncComponents: PublishableEntityLink[];
onSearchUpdate: () => void;
}) => {
const intl = useIntl();
const { showToast } = useContext(ToastContext);
const [blockData, setBlockData] = useState<LibraryChangesMessageData | undefined>(undefined);
// ignore changes confirmation modal toggle.
const [isConfirmModalOpen, openConfirmModal, closeConfirmModal] = useToggle(false);
// Toggle preview changes modal
const [isPreviewModalOpen, openPreviewModal, closePreviewModal] = useToggle(false);
const acceptChangesMutation = useAcceptLibraryBlockChanges();
const ignoreChangesMutation = useIgnoreLibraryBlockChanges();
const {
hits,
hits: downstreamInfo,
isLoading: isIndexDataLoading,
searchKeywords,
searchSortOrder,
hasError,
hasNextPage,
isFetchingNextPage,
fetchNextPage,
} = useSearchContext();
const downstreamInfo = hits as ContentHit[];
} = useSearchContext() as {
hits: ContentHit[];
isLoading: boolean;
searchKeywords: string;
searchSortOrder: SearchSortOption;
hasError: boolean;
hasNextPage: boolean | undefined,
isFetchingNextPage: boolean;
fetchNextPage: () => void;
};
useLoadOnScroll(
hasNextPage,
@@ -160,37 +139,51 @@ const ItemReviewList = ({
true,
);
const outOfSyncItemsByKey = useMemo(
() => keyBy(outOfSyncItems, 'downstreamUsageKey'),
[outOfSyncItems],
const outOfSyncComponentsByKey = useMemo(
() => keyBy(outOfSyncComponents, 'downstreamUsageKey'),
[outOfSyncComponents],
);
const downstreamInfoByKey = useMemo(
() => keyBy(downstreamInfo, 'usageKey'),
[downstreamInfo],
);
const queryClient = useQueryClient();
const setSelectedBlockData = useCallback((info: ContentHit) => {
useEffect(() => {
if (searchKeywords) {
onSearchUpdate();
}
}, [searchKeywords]);
// Toggle preview changes modal
const [isModalOpen, openModal, closeModal] = useToggle(false);
const acceptChangesMutation = useAcceptLibraryBlockChanges();
const ignoreChangesMutation = useIgnoreLibraryBlockChanges();
const setSeletecdBlockData = (info: ContentHit) => {
setBlockData({
displayName: info.displayName,
downstreamBlockId: info.usageKey,
upstreamBlockId: outOfSyncItemsByKey[info.usageKey].upstreamKey,
upstreamBlockVersionSynced: outOfSyncItemsByKey[info.usageKey].versionSynced,
isContainer: info.blockType === 'vertical' || info.blockType === 'sequential' || info.blockType === 'chapter',
upstreamBlockId: outOfSyncComponentsByKey[info.usageKey].upstreamUsageKey,
upstreamBlockVersionSynced: outOfSyncComponentsByKey[info.usageKey].versionSynced,
isVertical: info.blockType === 'vertical',
});
}, [outOfSyncItemsByKey]);
};
// Show preview changes on review
const onReview = useCallback((info: ContentHit) => {
setSelectedBlockData(info);
openPreviewModal();
}, [setSelectedBlockData, openPreviewModal]);
setSeletecdBlockData(info);
openModal();
}, [setSeletecdBlockData, openModal]);
const onIgnoreClick = useCallback((info: ContentHit) => {
setSelectedBlockData(info);
setSeletecdBlockData(info);
openConfirmModal();
}, [setSelectedBlockData, openConfirmModal]);
}, [setSeletecdBlockData, openConfirmModal]);
const reloadLinks = useCallback((usageKey: string) => {
const courseKey = outOfSyncItemsByKey[usageKey].downstreamContextKey;
invalidateLinksQuery(queryClient, courseKey);
}, [outOfSyncItemsByKey]);
const courseKey = outOfSyncComponentsByKey[usageKey].downstreamContextKey;
queryClient.invalidateQueries(courseLibrariesQueryKeys.courseLibraries(courseKey));
}, [outOfSyncComponentsByKey]);
const postChange = (accept: boolean) => {
// istanbul ignore if: this should never happen
@@ -243,6 +236,19 @@ const ItemReviewList = ({
}
}, [blockData]);
const orderInfo = useMemo(() => {
if (searchSortOrder !== SearchSortOption.RECENTLY_MODIFIED) {
return downstreamInfo;
}
if (isIndexDataLoading) {
return [];
}
let merged = merge(downstreamInfoByKey, outOfSyncComponentsByKey);
merged = omitBy(merged, (o) => !o.displayName);
const ordered = orderBy(Object.values(merged), 'updated', 'desc');
return ordered;
}, [downstreamInfoByKey, outOfSyncComponentsByKey]);
if (isIndexDataLoading) {
return <Loading />;
}
@@ -253,12 +259,10 @@ const ItemReviewList = ({
return (
<>
{downstreamInfo?.map((info) => (
<ItemCard
{orderInfo?.map((info) => (
<BlockCard
key={info.usageKey}
info={info}
itemType={outOfSyncItemsByKey[info.usageKey]?.upstreamType}
libraryName={outOfSyncItemsByKey[info.usageKey]?.upstreamContextTitle}
actions={(
<ActionRow>
<Button
@@ -289,14 +293,20 @@ const ItemReviewList = ({
)}
/>
))}
{blockData && (
<PreviewLibraryXBlockChanges
blockData={blockData}
isModalOpen={isPreviewModalOpen}
closeModal={closePreviewModal}
postChange={postChange}
/>
)}
<PreviewLibraryXBlockChanges
blockData={blockData}
isModalOpen={isModalOpen}
closeModal={closeModal}
postChange={postChange}
alertNode={(
<AlertMessage
show
variant="warning"
icon={Warning}
title={intl.formatMessage(messages.olderVersionPreviewAlert)}
/>
)}
/>
<DeleteModal
isOpen={isConfirmModalOpen}
close={closeConfirmModal}
@@ -313,20 +323,36 @@ const ItemReviewList = ({
const ReviewTabContent = ({ courseId }: Props) => {
const intl = useIntl();
const {
data: outOfSyncItems,
isLoading: isSyncItemsLoading,
data: linkPages,
isLoading: isSyncComponentsLoading,
hasNextPage,
isFetchingNextPage,
fetchNextPage,
isError,
error,
} = useEntityLinks({
courseId,
readyToSync: true,
useTopLevelParents: true,
});
} = useEntityLinks({ courseId, readyToSync: true });
const downstreamKeys = useMemo(
() => outOfSyncItems?.map(link => link.downstreamUsageKey),
[outOfSyncItems],
const outOfSyncComponents = useMemo(
() => linkPages?.pages?.reduce((links, page) => [...links, ...page.results], []) ?? [],
[linkPages],
);
const downstreamKeys = useMemo(
() => outOfSyncComponents?.map(link => link.downstreamUsageKey),
[outOfSyncComponents],
);
useLoadOnScroll(
hasNextPage,
isFetchingNextPage,
fetchNextPage,
true,
);
const onSearchUpdate = () => {
if (hasNextPage && !isFetchingNextPage) {
fetchNextPage();
}
};
const disableSortOptions = [
SearchSortOption.RELEVANCE,
@@ -335,7 +361,7 @@ const ReviewTabContent = ({ courseId }: Props) => {
SearchSortOption.RECENTLY_PUBLISHED,
];
if (isSyncItemsLoading) {
if (isSyncComponentsLoading) {
return <Loading />;
}
@@ -356,8 +382,9 @@ const ReviewTabContent = ({ courseId }: Props) => {
<SearchSortWidget disableOptions={disableSortOptions} />
<ActionRow.Spacer />
</ActionRow>
<ItemReviewList
outOfSyncItems={outOfSyncItems}
<ComponentReviewList
outOfSyncComponents={outOfSyncComponents}
onSearchUpdate={onSearchUpdate}
/>
</SearchContextProvider>
);

Some files were not shown because too many files have changed in this diff Show More