diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e238f3e40acf9..71f30eb220ab7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -22,7 +22,7 @@ /.github/ @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @john-bodley @kgabryje @dpgaspar -# Notify PMC members of changes to required Github Actions +# Notify PMC members of changes to required GitHub Actions /.asf.yaml @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @john-bodley @kgabryje @dpgaspar diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 773e7358345f1..11ed2d772093b 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -32,4 +32,4 @@ jobs: # license: https://applitools.com/legal/open-source-terms-of-use/ # pkg:npm/node-forge@1.3.1 # selecting BSD-3-Clause licensing terms for node-forge to ensure compatibility with Apache - allow-dependencies-licenses: pkg:npm/store2@2.14.2, pkg:npm/applitools/core, pkg:npm/applitools/core-base, pkg:npm/applitools/css-tree, pkg:npm/applitools/ec-client, pkg:npm/applitools/eg-socks5-proxy-server, pkg:npm/applitools/eyes, pkg:npm/applitools/eyes-cypress, pkg:npm/applitools/nml-client, pkg:npm/applitools/tunnel-client, pkg:npm/applitools/utils, pkg:npm/node-forge@1.3.1 + allow-dependencies-licenses: pkg:npm/store2@2.14.2, pkg:npm/applitools/core, pkg:npm/applitools/core-base, pkg:npm/applitools/css-tree, pkg:npm/applitools/ec-client, pkg:npm/applitools/eg-socks5-proxy-server, pkg:npm/applitools/eyes, pkg:npm/applitools/eyes-cypress, pkg:npm/applitools/nml-client, pkg:npm/applitools/tunnel-client, pkg:npm/applitools/utils, pkg:npm/node-forge@1.3.1, pkg:npm/rgbcolor diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index c8c4756ea543c..287026c084412 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -21,7 +21,7 @@ jobs: steps: - id: set_matrix run: | - MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["dev"]'; else echo '["dev", "lean", "py310", "websocket", "dockerize"]'; fi) + MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["dev"]'; else echo '["dev", "lean", "py310", "websocket", "dockerize", "py311"]'; fi) echo "matrix_config=${MATRIX_CONFIG}" >> $GITHUB_OUTPUT echo $GITHUB_OUTPUT diff --git a/.github/workflows/superset-docs-verify.yml b/.github/workflows/superset-docs-verify.yml index 4863da4052451..139cd0ae88aaa 100644 --- a/.github/workflows/superset-docs-verify.yml +++ b/.github/workflows/superset-docs-verify.yml @@ -4,6 +4,7 @@ on: pull_request: paths: - "docs/**" + - ".github/workflows/superset-docs-verify.yml" types: [synchronize, opened, reopened, ready_for_review] # cancel previous workflow jobs for PRs @@ -16,10 +17,12 @@ jobs: # See docs here: https://github.com/marketplace/actions/linkinator name: Link Checking runs-on: ubuntu-latest - continue-on-error: true # This will make the job advisory (non-blocking, no red X) steps: - uses: actions/checkout@v4 - - uses: JustinBeckwith/linkinator-action@v1.10.4 + # Do not bump this linkinator-action version without opening + # an ASF Infra ticket to allow the new verison first! + - uses: JustinBeckwith/linkinator-action@v1.11.0 + continue-on-error: true # This will make the job advisory (non-blocking, no red X) with: paths: "**/*.md, **/*.mdx" linksToSkip: >- @@ -40,6 +43,12 @@ jobs: https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html, ^https://img\.shields\.io/.*, https://vkusvill.ru/ + https://www.linkedin.com/in/mark-thomas-b16751158/ + https://theiconic.com.au/ + https://wattbewerb.de/ + https://timbr.ai/ + https://opensource.org/license/apache-2-0 + https://www.plaidcloud.com/ build-deploy: name: Build & Deploy runs-on: ubuntu-22.04 diff --git a/.github/workflows/tag-release.yml b/.github/workflows/tag-release.yml index 52e8067aaf819..ec06bc8e1cf63 100644 --- a/.github/workflows/tag-release.yml +++ b/.github/workflows/tag-release.yml @@ -42,7 +42,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - build_preset: ["dev", "lean", "py310", "websocket", "dockerize"] + build_preset: ["dev", "lean", "py310", "websocket", "dockerize", "py311"] fail-fast: false steps: - name: Set up QEMU diff --git a/Dockerfile b/Dockerfile index 229d21747db59..3b9273cb72bbf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -85,10 +85,11 @@ RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \ RUN rm /app/superset/translations/*/LC_MESSAGES/*.po RUN rm /app/superset/translations/messages.pot +FROM python:${PY_VER} AS python-base ###################################################################### # Final lean image... ###################################################################### -FROM python:${PY_VER} AS lean +FROM python-base AS lean # Include translations in the final build. The default supports en only to # reduce complexity and weight for those only using en @@ -120,6 +121,7 @@ COPY --chown=superset:superset pyproject.toml setup.py MANIFEST.in README.md ./ # setup.py uses the version information in package.json COPY --chown=superset:superset superset-frontend/package.json superset-frontend/ COPY --chown=superset:superset requirements/base.txt requirements/ +COPY --chown=superset:superset scripts/check-env.py scripts/ RUN --mount=type=cache,target=/root/.cache/pip \ apt-get update -qq && apt-get install -yqq --no-install-recommends \ build-essential \ diff --git a/README.md b/README.md index 7d8546e950b2c..62d5e11ee76a8 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ under the License. # Superset -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/license/apache-2-0) [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/apache/superset?sort=semver)](https://github.com/apache/superset/tree/latest) [![Build Status](https://github.com/apache/superset/workflows/Python/badge.svg)](https://github.com/apache/superset/actions) [![PyPI version](https://badge.fury.io/py/apache-superset.svg)](https://badge.fury.io/py/apache-superset) @@ -135,6 +135,7 @@ Here are some of the major database solutions that are supported: doris oceanbase oceanbase + denodo

**A more comprehensive list of supported databases** along with the configuration instructions can be found [here](https://superset.apache.org/docs/configuration/databases). diff --git a/RELEASING/release-notes-4-1/README.md b/RELEASING/release-notes-4-1/README.md index 9c7b387198bee..2c7ac19bfc024 100644 --- a/RELEASING/release-notes-4-1/README.md +++ b/RELEASING/release-notes-4-1/README.md @@ -34,7 +34,7 @@ We released a [Big Number with Time Period Comparison](https://github.com/apache ### Table with Time Comparison -Added functionality to do [table time comparisons](https://github.com/apache/superset/pull/28057) behind the `CHART_PLUGINS_EXPERIMENTAL` feature flag. This will help improve and facilitate efficient data analysis. +Added functionality to do [table time comparisons](https://github.com/apache/superset/pull/28057). This will help improve and facilitate efficient data analysis.
Image @@ -137,4 +137,4 @@ There is now a [metadata bar](https://github.com/apache/superset/pull/27857) add ## Change to Docker image builds -Starting in 4.1.0, the release's docker image does not ship with drivers needed to operate Superset. Users may need to install a driver for their metadata database (MySQL or Postgres) as well as the driver for their data warehouse. This is a result of changes to the `lean` docker image that official releases come from; see [Docker Build Presets](/docs/installation/docker-builds#build-presets) for more details. +Starting in 4.1.0, the release's docker image does not ship with drivers needed to operate Superset. Users may need to install a driver for their metadata database (MySQL or Postgres) as well as the driver for their data warehouse. This is a result of changes to the `lean` docker image that official releases come from; see [Docker Build Presets](/docs/docs/installation/docker-builds.mdx#build-presets) for more details. diff --git a/RESOURCES/INTHEWILD.md b/RESOURCES/INTHEWILD.md index 777fb9ee923bc..291635af0b3f3 100644 --- a/RESOURCES/INTHEWILD.md +++ b/RESOURCES/INTHEWILD.md @@ -84,6 +84,7 @@ Join our growing community! - [Deepomatic](https://deepomatic.com/) [@Zanoellia] - [Dial Once](https://www.dial-once.com/) - [Dremio](https://dremio.com) [@narendrans] +- [EFinance](https://www.efinance.com.eg) [@habeeb556] - [Elestio](https://elest.io/) [@kaiwalyakoparkar] - [ELMO Cloud HR & Payroll](https://elmosoftware.com.au/) - [Endress+Hauser](https://www.endress.com/) [@rumbin] @@ -95,7 +96,7 @@ Join our growing community! - [jampp](https://jampp.com/) - [Konfío](https://konfio.mx) [@uis-rodriguez] - [Mainstrat](https://mainstrat.com/) -- [mishmash io](https://mishmash.io/)[@mishmash-io] +- [mishmash io](https://mishmash.io/) [@mishmash-io] - [Myra Labs](https://www.myralabs.com/) [@viksit] - [Nielsen](https://www.nielsen.com/) [@amitNielsen] - [Ona](https://ona.io) [@pld] @@ -103,6 +104,7 @@ Join our growing community! - [Oslandia](https://oslandia.com) - [Peak AI](https://www.peak.ai/) [@azhar22k] - [PeopleDoc](https://www.people-doc.com) [@rodo] +- [PlaidCloud](https://www.plaidcloud.com) - [Preset, Inc.](https://preset.io) - [PubNub](https://pubnub.com) [@jzucker2] - [ReadyTech](https://www.readytech.io) @@ -115,7 +117,7 @@ Join our growing community! - [timbr.ai](https://timbr.ai/) [@semantiDan] - [Tobii](https://www.tobii.com/) [@dwa] - [Tooploox](https://www.tooploox.com/) [@jakubczaplicki] -- [Unvired](https://unvired.com)[@srinisubramanian] +- [Unvired](https://unvired.com) [@srinisubramanian] - [Whale](https://whale.im) - [Windsor.ai](https://www.windsor.ai/) [@octaviancorlade] - [Zeta](https://www.zeta.tech/) [@shaikidris] @@ -128,7 +130,7 @@ Join our growing community! - [Kuaishou](https://www.kuaishou.com/) [@zhaoyu89730105] - [Netflix](https://www.netflix.com/) - [Prensa Iberica](https://www.prensaiberica.es/) [@zamar-roura] -- [TME QQMUSIC/WESING](https://www.tencentmusic.com/)[@shenyuanli,@marklaw] +- [TME QQMUSIC/WESING](https://www.tencentmusic.com/) [@shenyuanli,@marklaw] - [Xite](https://xite.com/) [@shashankkoppar] - [Zaihang](https://www.zaih.com/) @@ -137,7 +139,7 @@ Join our growing community! - [Brilliant.org](https://brilliant.org/) - [Platzi.com](https://platzi.com/) - [Sunbird](https://www.sunbird.org/) [@eksteporg] -- [The GRAPH Network](https://thegraphnetwork.org/)[@fccoelho] +- [The GRAPH Network](https://thegraphnetwork.org/) [@fccoelho] - [Udemy](https://www.udemy.com/) [@sungjuly] - [VIPKID](https://www.vipkid.com.cn/) [@illpanda] - [WikiMedia Foundation](https://wikimediafoundation.org) [@vg] @@ -152,21 +154,24 @@ Join our growing community! ### Healthcare - [Amino](https://amino.com) [@shkr] - [Bluesquare](https://www.bluesquarehub.com/) [@madewulf] -- [Care](https://www.getcare.io/)[@alandao2021] +- [Care](https://www.getcare.io/) [@alandao2021] - [Living Goods](https://www.livinggoods.org) [@chelule] - [Maieutical Labs](https://maieuticallabs.it) [@xrmx] +- [Medic](https://medic.org) [@1yuv] - [REDCap Cloud](https://www.redcapcloud.com/) - [TrustMedis](https://trustmedis.com/) [@famasya] - [WeSure](https://www.wesure.cn/) +- [2070Health](https://2070health.com/) ### HR / Staffing - [Swile](https://www.swile.co/) [@PaoloTerzi] - [Symmetrics](https://www.symmetrics.fyi) - [bluquist](https://bluquist.com/) -### Government +### Government / Non-Profit - [City of Ann Arbor, MI](https://www.a2gov.org/) [@sfirke] - [RIS3 Strategy of CZ, MIT CR](https://www.ris3.cz/) [@RIS3CZ] +- [NRLM - Sarathi, India](https://pib.gov.in/PressReleasePage.aspx?PRID=1999586) ### Travel - [Agoda](https://www.agoda.com/) [@lostseaway, @maiake, @obombayo] @@ -183,6 +188,6 @@ Join our growing community! - [komoot](https://www.komoot.com/) [@christophlingg] - [Let's Roam](https://www.letsroam.com/) - [Onebeat](https://1beat.com/) [@GuyAttia] -- [Twitter](https://twitter.com/) +- [X](https://x.com/) - [VLMedia](https://www.vlmedia.com.tr/) [@ibotheperfect] - [Yahoo!](https://yahoo.com/) diff --git a/docker-compose.yml b/docker-compose.yml index 605be1333be5a..e8dc2efa899df 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,6 +25,7 @@ x-superset-user: &superset-user root x-superset-depends-on: &superset-depends-on - db - redis + - superset-checks x-superset-volumes: &superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container - ./docker:/app/docker @@ -130,6 +131,23 @@ services: - REDIS_PORT=6379 - REDIS_SSL=false + superset-checks: + build: + context: . + target: python-base + cache_from: + - apache/superset-cache:3.10-slim-bookworm + container_name: superset_checks + command: ["/app/scripts/check-env.py"] + env_file: + - path: docker/.env # default + required: true + - path: docker/.env-local # optional override + required: false + user: *superset-user + healthcheck: + disable: true + superset-init: build: <<: *common-build diff --git a/docs/docs/configuration/databases.mdx b/docs/docs/configuration/databases.mdx index b02a1a83887a5..49c9417df862c 100644 --- a/docs/docs/configuration/databases.mdx +++ b/docs/docs/configuration/databases.mdx @@ -55,6 +55,7 @@ are compatible with Superset. | [ClickHouse](/docs/configuration/databases#clickhouse) | `pip install clickhouse-connect` | `clickhousedb://{username}:{password}@{hostname}:{port}/{database}` | | [CockroachDB](/docs/configuration/databases#cockroachdb) | `pip install cockroachdb` | `cockroachdb://root@{hostname}:{port}/{database}?sslmode=disable` | | [Couchbase](/docs/configuration/databases#couchbase) | `pip install couchbase-sqlalchemy` | `couchbase://{username}:{password}@{hostname}:{port}?truststorepath={ssl certificate path}` | +| [Denodo](/docs/configuration/databases#denodo) | `pip install denodo-sqlalchemy` | `denodo://{username}:{password}@{hostname}:{port}/{database}` | | [Dremio](/docs/configuration/databases#dremio) | `pip install sqlalchemy_dremio` |`dremio+flight://{username}:{password}@{host}:32010`, often useful: `?UseEncryption=true/false`. For Legacy ODBC: `dremio+pyodbc://{username}:{password}@{host}:31010` | | [Elasticsearch](/docs/configuration/databases#elasticsearch) | `pip install elasticsearch-dbapi` | `elasticsearch+http://{user}:{password}@{host}:9200/` | | [Exasol](/docs/configuration/databases#exasol) | `pip install sqlalchemy-exasol` | `exa+pyodbc://{username}:{password}@{hostname}:{port}/my_schema?CONNECTIONLCALL=en_US.UTF-8&driver=EXAODBC` | @@ -512,6 +513,16 @@ For a connection to a SQL endpoint you need to use the HTTP path from the endpoi ``` +#### Denodo + +The recommended connector library for Denodo is +[denodo-sqlalchemy](https://pypi.org/project/denodo-sqlalchemy/). + +The expected connection string is formatted as follows (default port is 9996): + +``` +denodo://{username}:{password}@{hostname}:{port}/{database} +``` #### Dremio @@ -1307,6 +1318,10 @@ Here's what the connection string looks like: starrocks://:@:/. ``` +:::note +StarRocks maintains their Superset docuementation [here](https://docs.starrocks.io/docs/integrations/BI_integrations/Superset/). +::: + #### Teradata The recommended connector library is diff --git a/docs/docs/configuration/sql-templating.mdx b/docs/docs/configuration/sql-templating.mdx index 64caea2157579..39bea00d85b00 100644 --- a/docs/docs/configuration/sql-templating.mdx +++ b/docs/docs/configuration/sql-templating.mdx @@ -48,12 +48,15 @@ WHERE ( {% if to_dttm is not none %} dttm_col < '{{ to_dttm }}' AND {% endif %} - true + 1 = 1 ) ``` -Note how the Jinja parameters are called within double brackets in the query, and without in the -logic blocks. +The `1 = 1` at the end ensures a value is present for the `WHERE` clause even when +the time filter is not set. For many database engines, this could be replaced with `true`. + +Note that the Jinja parameters are called within _double_ brackets in the query and with +_single_ brackets in the logic blocks. To add custom functionality to the Jinja context, you need to overload the default Jinja context in your environment by defining the `JINJA_CONTEXT_ADDONS` in your superset configuration diff --git a/docs/docs/contributing/development.mdx b/docs/docs/contributing/development.mdx index 14d6a526d630e..cb48a4c7b29b4 100644 --- a/docs/docs/contributing/development.mdx +++ b/docs/docs/contributing/development.mdx @@ -29,7 +29,7 @@ cd superset ## docker compose (recommended!) -Setting things up to squeeze an "hello world" into any part of Superset should be as simple as +Setting things up to squeeze a "hello world" into any part of Superset should be as simple as ```bash docker compose up @@ -45,7 +45,7 @@ Note that: - **Postgres** as the metadata database and to store example datasets, charts and dashboards which should be populated upon startup - **Redis** as the message queue for our async backend and caching backend -- It'll load up examples into the database upon first startup +- It'll load up examples into the database upon the first startup - all other details and pointers available in [docker-compose.yml](https://github.com/apache/superset/blob/master/docker-compose.yml) - The local repository is mounted within the services, meaning updating @@ -53,6 +53,13 @@ Note that: - Superset is served at localhost:8088/ - You can login with admin/admin +:::note +Installing and building Node modules for Apache Superset inside `superset-node` can take a +significant amount of time. This is normal due to the size of the dependencies. Please be +patient while the process completes, as long wait times do not indicate an issue with your setup. +If delays seem excessive, check your internet connection or system resources. +::: + :::caution Since `docker compose` is primarily designed to run a set of containers on **a single host** and can't credibly support **high availability** as a result, we do not support nor recommend @@ -136,12 +143,11 @@ You can also run the pre-commit checks manually in various ways: Replace `` with the ID of the specific hook you want to run. You can find the list of available hooks in the `.pre-commit-config.yaml` file. - ## Alternatives to `docker compose` :::caution This part of the documentation is a patchwork of information related to setting up -development environments without `docker compose` and are documented/supported to varying +development environments without `docker compose` and is documented/supported to varying degrees. It's been difficult to maintain this wide array of methods and insure they're functioning across environments. ::: @@ -181,11 +187,11 @@ superset load-examples # Start the Flask dev web server from inside your virtualenv. # Note that your page may not have CSS at this point. -# See instructions below how to build the front-end assets. +# See instructions below on how to build the front-end assets. superset run -p 8088 --with-threads --reload --debugger --debug ``` -Or you can install via our Makefile +Or you can install it via our Makefile ```bash # Create a virtual environment and activate it (recommended) @@ -203,7 +209,7 @@ $ make pre-commit ``` **Note: the FLASK_APP env var should not need to be set, as it's currently controlled -via `.flaskenv`, however if needed, it should be set to `superset.app:create_app()`** +via `.flaskenv`, however, if needed, it should be set to `superset.app:create_app()`** If you have made changes to the FAB-managed templates, which are not built the same way as the newer, React-powered front-end assets, you need to start the app without the `--with-threads` argument like so: `superset run -p 8088 --reload --debugger --debug` @@ -306,7 +312,7 @@ cd superset-frontend npm ci ``` -Note that Superset uses [Scarf](https://docs.scarf.sh) to capture telemetry/analytics about versions being installed, including the `scarf-js` npm package and an analytics pixel. As noted elsewhere in this documentation, Scarf gathers aggregated stats for the sake of security/release strategy, and does not capture/retain PII. [You can read here](https://docs.scarf.sh/package-analytics/) about the `scarf-js` package, and various means to opt out of it, but you can opt out of the npm package _and_ the pixel by setting the `SCARF_ANALYTICS` environment variable to `false` or opt out of the pixel by adding this setting in `superset-frontent/package.json`: +Note that Superset uses [Scarf](https://docs.scarf.sh) to capture telemetry/analytics about versions being installed, including the `scarf-js` npm package and an analytics pixel. As noted elsewhere in this documentation, Scarf gathers aggregated stats for the sake of security/release strategy and does not capture/retain PII. [You can read here](https://docs.scarf.sh/package-analytics/) about the `scarf-js` package, and various means to opt out of it, but you can opt out of the npm package _and_ the pixel by setting the `SCARF_ANALYTICS` environment variable to `false` or opt out of the pixel by adding this setting in `superset-frontent/package.json`: ```json // your-package/package.json @@ -334,7 +340,7 @@ Error: ENOSPC: System limit for number of file watchers reached ``` The error is thrown because the number of files monitored by the system has reached the limit. -You can address this this error by increasing the number of inotify watchers. +You can address this error by increasing the number of inotify watchers. The current value of max watches can be checked with: @@ -345,13 +351,13 @@ cat /proc/sys/fs/inotify/max_user_watches Edit the file `/etc/sysctl.conf` to increase this value. The value needs to be decided based on the system memory [(see this StackOverflow answer for more context)](https://stackoverflow.com/questions/535768/what-is-a-reasonable-amount-of-inotify-watches-with-linux). -Open the file in editor and add a line at the bottom specifying the max watches values. +Open the file in an editor and add a line at the bottom specifying the max watches values. ```bash fs.inotify.max_user_watches=524288 ``` -Save the file and exit editor. +Save the file and exit the editor. To confirm that the change succeeded, run the following command to load the updated value of max_user_watches from `sysctl.conf`: ```bash @@ -449,7 +455,7 @@ pre-commit install A series of checks will now run when you make a git commit. -Alternatively it is possible to run pre-commit via tox: +Alternatively, it is possible to run pre-commit via tox: ```bash tox -e pre-commit @@ -533,7 +539,7 @@ commands are invoked. There is also a utility script included in the Superset codebase to run python integration tests. The [readme can be found here](https://github.com/apache/superset/tree/master/scripts/tests) -To run all integration tests for example, run this script from the root directory: +To run all integration tests, for example, run this script from the root directory: ```bash scripts/tests/run.sh @@ -608,14 +614,14 @@ As an alternative you can use docker compose environment for testing: Make sure you have added below line to your /etc/hosts file: `127.0.0.1 db` -If you already have launched Docker environment please use the following command to assure a fresh database instance: +If you already have launched Docker environment please use the following command to ensure a fresh database instance: `docker compose down -v` Launch environment: `CYPRESS_CONFIG=true docker compose up` -It will serve backend and frontend on port 8088. +It will serve the backend and frontend on port 8088. Run Cypress tests: @@ -657,7 +663,7 @@ For debugging locally using VSCode, you can configure a launch configuration fil Follow these instructions to debug the Flask app running inside a docker container. Note that this will run a barebones Superset web server, -First add the following to the ./docker-compose.yaml file +First, add the following to the ./docker-compose.yaml file ```diff superset: @@ -779,11 +785,11 @@ Often in a Kubernetes environment nodes are not addressable from outside the clu kubectl port-forward pod/superset- 5678:5678 ``` -You can now launch your VSCode debugger with the same config as above. VSCode will connect to to 127.0.0.1:5678 which is forwarded by kubectl to your remote kubernetes POD. +You can now launch your VSCode debugger with the same config as above. VSCode will connect to 127.0.0.1:5678 which is forwarded by kubectl to your remote kubernetes POD. ### Storybook -Superset includes a [Storybook](https://storybook.js.org/) to preview the layout/styling of various Superset components, and variations thereof. To open and view the Storybook: +Superset includes a [Storybook](https://storybook.js.org/) to preview the layout/styling of various Superset components and variations thereof. To open and view the Storybook: ```bash cd superset-frontend @@ -933,7 +939,7 @@ To fix it: from alembic import op ``` - Alternatively you may also run `superset db merge` to create a migration script + Alternatively, you may also run `superset db merge` to create a migration script just for merging the heads. ```bash diff --git a/docs/docs/installation/pypi.mdx b/docs/docs/installation/pypi.mdx index 564760e52b9fb..c7fc19e64bfbe 100644 --- a/docs/docs/installation/pypi.mdx +++ b/docs/docs/installation/pypi.mdx @@ -22,16 +22,16 @@ level dependencies. **Debian and Ubuntu** -The following command will ensure that the required dependencies are installed: +In Ubuntu **20.04 and 22.04** the following command will ensure that the required dependencies are installed: ```bash -sudo apt-get install build-essential libssl-dev libffi-dev python-dev python-pip libsasl2-dev libldap2-dev default-libmysqlclient-dev +sudo apt-get install build-essential libssl-dev libffi-dev python3-dev python3-pip libsasl2-dev libldap2-dev default-libmysqlclient-dev ``` -In Ubuntu 20.04 the following command will ensure that the required dependencies are installed: +In Ubuntu **before 20.04** the following command will ensure that the required dependencies are installed: ```bash -sudo apt-get install build-essential libssl-dev libffi-dev python3-dev python3-pip libsasl2-dev libldap2-dev default-libmysqlclient-dev +sudo apt-get install build-essential libssl-dev libffi-dev python-dev python-pip libsasl2-dev libldap2-dev default-libmysqlclient-dev ``` **Fedora and RHEL-derivative Linux distributions** diff --git a/docs/package.json b/docs/package.json index f6aecc25da714..c2ca5d344f146 100644 --- a/docs/package.json +++ b/docs/package.json @@ -17,19 +17,19 @@ "typecheck": "tsc" }, "dependencies": { - "@algolia/client-search": "^4.24.0", + "@algolia/client-search": "^5.12.0", "@ant-design/icons": "^5.4.0", - "@docsearch/react": "^3.6.2", + "@docsearch/react": "^3.6.3", "@docusaurus/core": "^3.5.2", "@docusaurus/plugin-client-redirects": "^3.5.2", "@docusaurus/preset-classic": "^3.5.2", "@emotion/core": "^10.1.1", "@emotion/styled": "^10.0.27", - "@mdx-js/react": "^3.0.0", - "@saucelabs/theme-github-codeblock": "^0.2.3", + "@mdx-js/react": "^3.1.0", + "@saucelabs/theme-github-codeblock": "^0.3.0", "@superset-ui/style": "^0.14.23", "@svgr/webpack": "^8.1.0", - "antd": "^5.20.5", + "antd": "^5.21.6", "buffer": "^6.0.3", "clsx": "^2.1.1", "docusaurus-plugin-less": "^2.0.2", @@ -48,9 +48,9 @@ "devDependencies": { "@docusaurus/module-type-aliases": "^3.5.2", "@docusaurus/tsconfig": "^3.5.2", - "@types/react": "^18.3.10", - "typescript": "^5.6.2", - "webpack": "^5.94.0" + "@types/react": "^18.3.12", + "typescript": "^5.6.3", + "webpack": "^5.96.1" }, "browserslist": { "production": [ diff --git a/docs/src/resources/data.js b/docs/src/resources/data.js index ec19e92400256..baeed74eb9543 100644 --- a/docs/src/resources/data.js +++ b/docs/src/resources/data.js @@ -132,4 +132,9 @@ export const Databases = [ href: 'https://www.couchbase.com/', imgName: 'couchbase.svg', }, + { + title: 'Denodo', + href: 'https://www.denodo.com/', + imgName: 'denodo.png', + }, ]; diff --git a/docs/static/img/databases/denodo.png b/docs/static/img/databases/denodo.png new file mode 100644 index 0000000000000..3561c387c4bf2 Binary files /dev/null and b/docs/static/img/databases/denodo.png differ diff --git a/docs/static/resources/openapi.json b/docs/static/resources/openapi.json index c2cadfd1f5767..39ce305170b12 100644 --- a/docs/static/resources/openapi.json +++ b/docs/static/resources/openapi.json @@ -3008,6 +3008,33 @@ }, "type": "object" }, + "DashboardNativeFiltersConfigUpdateSchema": { + "properties": { + "deleted": { + "description": "List of filter ids to delete", + "items": { + "type": "integer" + }, + "type": "array" + }, + "modified": { + "description": "List of filter objects to update", + "items": { + "type": "object" + }, + "type": "array" + }, + "reordered": { + "description": "List of filter ids in the new order", + "items": { + "type": "integer" + }, + "type": "array" + } + }, + "required": ["deleted", "modified", "reordered"], + "type": "object" + }, "DashboardCopySchema": { "properties": { "css": { @@ -13495,6 +13522,72 @@ "tags": ["Dashboards"] } }, + "/api/v1/dashboard/{id_or_slug}/filters/": { + "put": { + "description": "Update the filters for a given dashboard", + "parameters": [ + { + "in": "path", + "name": "id_or_slug", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DashboardNativeFiltersConfigUpdateSchema" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "result": { + "type": "array", + "items": { + "type": "object" + } + } + }, + "type": "object" + } + } + }, + "description": "Successfully updated the filters" + }, + "400": { + "$ref": "#/components/responses/400" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "403": { + "$ref": "#/components/responses/403" + }, + "404": { + "$ref": "#/components/responses/404" + }, + "500": { + "$ref": "#/components/responses/500" + } + }, + "security": [ + { + "jwt": [] + } + ], + "tags": ["Dashboards"] + } + }, "/api/v1/dashboard/{id_or_slug}/copy/": { "post": { "parameters": [ diff --git a/docs/yarn.lock b/docs/yarn.lock index e544f0b762421..d29c5738a6351 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -17,12 +17,17 @@ dependencies: "@algolia/autocomplete-shared" "1.9.3" -"@algolia/autocomplete-preset-algolia@1.9.3": - version "1.9.3" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz#64cca4a4304cfcad2cf730e83067e0c1b2f485da" - integrity sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA== +"@algolia/autocomplete-preset-algolia@1.17.6": + version "1.17.6" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.6.tgz#465b652bff5c262aad4da2488d78629cfa906be6" + integrity sha512-Cvg5JENdSCMuClwhJ1ON1/jSuojaYMiUW2KePm18IkdCzPJj/NXojaOxw58RFtQFpJgfVW8h2E8mEoDtLlMdeA== dependencies: - "@algolia/autocomplete-shared" "1.9.3" + "@algolia/autocomplete-shared" "1.17.6" + +"@algolia/autocomplete-shared@1.17.6": + version "1.17.6" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.6.tgz#ad951632b6d477d4ba9a68a347e1702d26009d58" + integrity sha512-aq/3V9E00Tw2GC/PqgyPGXtqJUlVc17v4cn1EUhSc+O/4zd04Uwb3UmPm8KDaYQQOrkt1lwvCj2vG2wRE5IKhw== "@algolia/autocomplete-shared@1.9.3": version "1.9.3" @@ -41,11 +46,6 @@ resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.23.3.tgz#3bec79092d512a96c9bfbdeec7cff4ad36367166" integrity sha512-h9XcNI6lxYStaw32pHpB1TMm0RuxphF+Ik4o7tcQiodEdpKK+wKufY6QXtba7t3k8eseirEMVB83uFFF3Nu54A== -"@algolia/cache-common@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.24.0.tgz#81a8d3a82ceb75302abb9b150a52eba9960c9744" - integrity sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g== - "@algolia/cache-in-memory@4.23.3": version "4.23.3" resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.23.3.tgz#3945f87cd21ffa2bec23890c85305b6b11192423" @@ -53,6 +53,16 @@ dependencies: "@algolia/cache-common" "4.23.3" +"@algolia/client-abtesting@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.12.0.tgz#45175422ee85d505ff6a16d1634a739478a6ad0b" + integrity sha512-hx4eVydkm3yrFCFxmcBtSzI/ykt0cZ6sDWch+v3JTgKpD2WtosMJU3Upv1AjQ4B6COSHCOWEX3vfFxW6OoH6aA== + dependencies: + "@algolia/client-common" "5.12.0" + "@algolia/requester-browser-xhr" "5.12.0" + "@algolia/requester-fetch" "5.12.0" + "@algolia/requester-node-http" "5.12.0" + "@algolia/client-account@4.23.3": version "4.23.3" resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.23.3.tgz#8751bbf636e6741c95e7c778488dee3ee430ac6f" @@ -72,6 +82,16 @@ "@algolia/requester-common" "4.23.3" "@algolia/transporter" "4.23.3" +"@algolia/client-analytics@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.12.0.tgz#e387f4de01f4fb549b7506762003bef335be2927" + integrity sha512-EpTsSv6IW8maCfXCDIptgT7+mQJj7pImEkcNUnxR8yUKAHzTogTXv9yGm2WXOZFVuwstd2i0sImhQ1Vz8RH/hA== + dependencies: + "@algolia/client-common" "5.12.0" + "@algolia/requester-browser-xhr" "5.12.0" + "@algolia/requester-fetch" "5.12.0" + "@algolia/requester-node-http" "5.12.0" + "@algolia/client-common@4.23.3": version "4.23.3" resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.23.3.tgz#891116aa0db75055a7ecc107649f7f0965774704" @@ -80,13 +100,20 @@ "@algolia/requester-common" "4.23.3" "@algolia/transporter" "4.23.3" -"@algolia/client-common@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.24.0.tgz#77c46eee42b9444a1d1c1583a83f7df4398a649d" - integrity sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA== +"@algolia/client-common@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.12.0.tgz#e33b6fefb333beb56eb58ab7424fcd7ec11ac7d0" + integrity sha512-od3WmO8qxyfNhKc+K3D17tvun3IMs/xMNmxCG9MiElAkYVbPPTRUYMkRneCpmJyQI0hNx2/EA4kZgzVfQjO86Q== + +"@algolia/client-insights@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.12.0.tgz#bb80c4227178b452dd93a649b9991b8140cba52d" + integrity sha512-8alajmsYUd+7vfX5lpRNdxqv3Xx9clIHLUItyQK0Z6gwGMbVEFe6YYhgDtwslMAP0y6b0WeJEIZJMLgT7VYpRw== dependencies: - "@algolia/requester-common" "4.24.0" - "@algolia/transporter" "4.24.0" + "@algolia/client-common" "5.12.0" + "@algolia/requester-browser-xhr" "5.12.0" + "@algolia/requester-fetch" "5.12.0" + "@algolia/requester-node-http" "5.12.0" "@algolia/client-personalization@4.23.3": version "4.23.3" @@ -97,6 +124,26 @@ "@algolia/requester-common" "4.23.3" "@algolia/transporter" "4.23.3" +"@algolia/client-personalization@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.12.0.tgz#ad711245403754686efff6a65d6c83877e64ecfa" + integrity sha512-bUV9HtfkTBgpoVhxFrMkmVPG03ZN1Rtn51kiaEtukucdk3ggjR9Qu1YUfRSU2lFgxr9qJc8lTxwfvhjCeJRcqw== + dependencies: + "@algolia/client-common" "5.12.0" + "@algolia/requester-browser-xhr" "5.12.0" + "@algolia/requester-fetch" "5.12.0" + "@algolia/requester-node-http" "5.12.0" + +"@algolia/client-query-suggestions@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.12.0.tgz#fc3bbf6d86e8989bb8487dc69ec49743fa75ceb4" + integrity sha512-Q5CszzGWfxbIDs9DJ/QJsL7bP6h+lJMg27KxieEnI9KGCu0Jt5iFA3GkREkgRZxRdzlHbZKkrIzhtHVbSHw/rg== + dependencies: + "@algolia/client-common" "5.12.0" + "@algolia/requester-browser-xhr" "5.12.0" + "@algolia/requester-fetch" "5.12.0" + "@algolia/requester-node-http" "5.12.0" + "@algolia/client-search@4.23.3": version "4.23.3" resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.23.3.tgz#a3486e6af13a231ec4ab43a915a1f318787b937f" @@ -106,30 +153,36 @@ "@algolia/requester-common" "4.23.3" "@algolia/transporter" "4.23.3" -"@algolia/client-search@^4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.24.0.tgz#75e6c02d33ef3e0f34afd9962c085b856fc4a55f" - integrity sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA== +"@algolia/client-search@5.12.0", "@algolia/client-search@^5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.12.0.tgz#cd3eb4854664177d6e992bb2b942e2a12e4cb919" + integrity sha512-R3qzEytgVLHOGNri+bpta6NtTt7YtkvUe/QBcAmMDjW4Jk1P0eBYIPfvnzIPbINRsLxIq9fZs9uAYBgsrts4Zg== dependencies: - "@algolia/client-common" "4.24.0" - "@algolia/requester-common" "4.24.0" - "@algolia/transporter" "4.24.0" + "@algolia/client-common" "5.12.0" + "@algolia/requester-browser-xhr" "5.12.0" + "@algolia/requester-fetch" "5.12.0" + "@algolia/requester-node-http" "5.12.0" "@algolia/events@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== +"@algolia/ingestion@1.12.0": + version "1.12.0" + resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.12.0.tgz#01a297fb2a58019595e5d74e95939da033a18194" + integrity sha512-zpHo6qhR22tL8FsdSI4DvEraPDi/019HmMrCFB/TUX98yzh5ooAU7sNW0qPL1I7+S++VbBmNzJOEU9VI8tEC8A== + dependencies: + "@algolia/client-common" "5.12.0" + "@algolia/requester-browser-xhr" "5.12.0" + "@algolia/requester-fetch" "5.12.0" + "@algolia/requester-node-http" "5.12.0" + "@algolia/logger-common@4.23.3": version "4.23.3" resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.23.3.tgz#35c6d833cbf41e853a4f36ba37c6e5864920bfe9" integrity sha512-y9kBtmJwiZ9ZZ+1Ek66P0M68mHQzKRxkW5kAAXYN/rdzgDN0d2COsViEFufxJ0pb45K4FRcfC7+33YB4BLrZ+g== -"@algolia/logger-common@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.24.0.tgz#28d439976019ec0a46ba7a1a739ef493d4ef8123" - integrity sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA== - "@algolia/logger-console@4.23.3": version "4.23.3" resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.23.3.tgz#30f916781826c4db5f51fcd9a8a264a06e136985" @@ -137,6 +190,16 @@ dependencies: "@algolia/logger-common" "4.23.3" +"@algolia/monitoring@1.12.0": + version "1.12.0" + resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.12.0.tgz#f510bfd9d09352b31ccce293d1fd84cdea59354c" + integrity sha512-i2AJZED/zf4uhxezAJUhMKoL5QoepCBp2ynOYol0N76+TSoohaMADdPnWCqOULF4RzOwrG8wWynAwBlXsAI1RQ== + dependencies: + "@algolia/client-common" "5.12.0" + "@algolia/requester-browser-xhr" "5.12.0" + "@algolia/requester-fetch" "5.12.0" + "@algolia/requester-node-http" "5.12.0" + "@algolia/recommend@4.23.3": version "4.23.3" resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-4.23.3.tgz#53d4f194d22d9c72dc05f3f7514c5878f87c5890" @@ -154,6 +217,16 @@ "@algolia/requester-node-http" "4.23.3" "@algolia/transporter" "4.23.3" +"@algolia/recommend@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.12.0.tgz#bc9f69c78c08ba9a3579e7fe2a0f4037b494cc55" + integrity sha512-0jmZyKvYnB/Bj5c7WKsKedOUjnr0UtXm0LVFUdQrxXfqOqvWv9n6Vpr65UjdYG4Q49kRQxhlwtal9WJYrYymXg== + dependencies: + "@algolia/client-common" "5.12.0" + "@algolia/requester-browser-xhr" "5.12.0" + "@algolia/requester-fetch" "5.12.0" + "@algolia/requester-node-http" "5.12.0" + "@algolia/requester-browser-xhr@4.23.3": version "4.23.3" resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.3.tgz#9e47e76f60d540acc8b27b4ebc7a80d1b41938b9" @@ -161,15 +234,24 @@ dependencies: "@algolia/requester-common" "4.23.3" +"@algolia/requester-browser-xhr@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.12.0.tgz#dba0072d5098a145e4724a723ea1c765b4af0cb6" + integrity sha512-KxwleraFuVoEGCoeW6Y1RAEbgBMS7SavqeyzWdtkJc6mXeCOJXn1iZitb8Tyn2FcpMNUKlSm0adrUTt7G47+Ow== + dependencies: + "@algolia/client-common" "5.12.0" + "@algolia/requester-common@4.23.3": version "4.23.3" resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.23.3.tgz#7dbae896e41adfaaf1d1fa5f317f83a99afb04b3" integrity sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw== -"@algolia/requester-common@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.24.0.tgz#1c60c198031f48fcdb9e34c4057a3ea987b9a436" - integrity sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA== +"@algolia/requester-fetch@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.12.0.tgz#4db2772b9b0699fdfadbcd7b87e0608a4acf8363" + integrity sha512-FuDZXUGU1pAg2HCnrt8+q1VGHKChV/LhvjvZlLOT7e56GJie6p+EuLu4/hMKPOVuQQ8XXtrTHKIU3Lw+7O5/bQ== + dependencies: + "@algolia/client-common" "5.12.0" "@algolia/requester-node-http@4.23.3": version "4.23.3" @@ -178,6 +260,13 @@ dependencies: "@algolia/requester-common" "4.23.3" +"@algolia/requester-node-http@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.12.0.tgz#6c6bb47df33351b819790f26346632196c97a3c7" + integrity sha512-ncDDY7CxZhMs6LIoPl+vHFQceIBhYPY5EfuGF1V7beO0U38xfsCYEyutEFB2kRzf4D9Gqppn3iWX71sNtrKcuw== + dependencies: + "@algolia/client-common" "5.12.0" + "@algolia/transporter@4.23.3": version "4.23.3" resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.23.3.tgz#545b045b67db3850ddf0bbecbc6c84ff1f3398b7" @@ -187,15 +276,6 @@ "@algolia/logger-common" "4.23.3" "@algolia/requester-common" "4.23.3" -"@algolia/transporter@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.24.0.tgz#226bb1f8af62430374c1972b2e5c8580ab275102" - integrity sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA== - dependencies: - "@algolia/cache-common" "4.24.0" - "@algolia/logger-common" "4.24.0" - "@algolia/requester-common" "4.24.0" - "@ampproject/remapping@^2.2.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -211,19 +291,19 @@ dependencies: "@ctrl/tinycolor" "^3.6.1" -"@ant-design/cssinjs-utils@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@ant-design/cssinjs-utils/-/cssinjs-utils-1.0.3.tgz#d68e46be9680cf9f416374a03aff0dd11bd1728d" - integrity sha512-BrztZZKuoYcJK8uEH40ylBemf/Mu/QPiDos56g2bv6eUoniQkgQHOCOvA3+pncoFO1TaS8xcUCIqGzDA0I+ZVQ== +"@ant-design/cssinjs-utils@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.1.tgz#57abb43671023f937348bd33442862c60ac8e8b2" + integrity sha512-2HAiyGGGnM0es40SxdszeQAU5iWp41wBIInq+ONTCKjlSKOrzQfnw4JDtB8IBmqE6tQaEKwmzTP2LGdt5DSwYQ== dependencies: "@ant-design/cssinjs" "^1.21.0" "@babel/runtime" "^7.23.2" rc-util "^5.38.0" -"@ant-design/cssinjs@^1.21.0": - version "1.21.0" - resolved "https://registry.yarnpkg.com/@ant-design/cssinjs/-/cssinjs-1.21.0.tgz#de7289bfd71c7a494a28b96569ad88f999619105" - integrity sha512-gIilraPl+9EoKdYxnupxjHB/Q6IHNRjEXszKbDxZdsgv4sAZ9pjkCq8yanDWNvyfjp4leir2OVAJm0vxwKK8YA== +"@ant-design/cssinjs@^1.21.0", "@ant-design/cssinjs@^1.21.1": + version "1.21.1" + resolved "https://registry.yarnpkg.com/@ant-design/cssinjs/-/cssinjs-1.21.1.tgz#7320813c5f747e0cde52c388eff5198d78d57230" + integrity sha512-tyWnlK+XH7Bumd0byfbCiZNK43HEubMoCcu9VxwsAwiHdHTgWa+tMN0/yvxa+e8EzuFP1WdUNNPclRpVtD33lg== dependencies: "@babel/runtime" "^7.11.1" "@emotion/hash" "^0.8.0" @@ -231,7 +311,7 @@ classnames "^2.3.1" csstype "^3.1.3" rc-util "^5.35.0" - stylis "^4.0.13" + stylis "^4.3.3" "@ant-design/fast-color@^2.0.6": version "2.0.6" @@ -245,10 +325,10 @@ resolved "https://registry.yarnpkg.com/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz#ed2be7fb4d82ac7e1d45a54a5b06d6cecf8be6f6" integrity sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA== -"@ant-design/icons@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-5.4.0.tgz#4bd8f335c68207cc06fe9943d164a81cdfcfbeac" - integrity sha512-QZbWC5xQYexCI5q4/fehSEkchJr5UGtvAJweT743qKUQQGs9IH2DehNLP49DJ3Ii9m9CijD2HN6fNy3WKhIFdA== +"@ant-design/icons@^5.4.0", "@ant-design/icons@^5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-5.5.1.tgz#4ff57b2a0d3bafae3d990c2781fd857ead36c935" + integrity sha512-0UrM02MA2iDIgvLatWrj6YTCYe0F/cwXvVE0E2SqGrL7PZireQwgEKTKBisWpZyal5eXZLvuM98kju6YtYne8w== dependencies: "@ant-design/colors" "^7.0.0" "@ant-design/icons-svg" "^4.4.0" @@ -1274,10 +1354,10 @@ core-js-pure "^3.30.2" regenerator-runtime "^0.14.0" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.3", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.22.6", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.6", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.4", "@babel/runtime@^7.24.7", "@babel/runtime@^7.24.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4": - version "7.25.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb" - integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.3", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.22.6", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.6", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.4", "@babel/runtime@^7.24.7", "@babel/runtime@^7.24.8", "@babel/runtime@^7.25.6", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== dependencies: regenerator-runtime "^0.14.0" @@ -1335,20 +1415,20 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@docsearch/css@3.6.2": - version "3.6.2" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.6.2.tgz#ccd9c83dbfeaf34efe4e3547ee596714ae7e5891" - integrity sha512-vKNZepO2j7MrYBTZIGXvlUOIR+v9KRf70FApRgovWrj3GTs1EITz/Xb0AOlm1xsQBp16clVZj1SY/qaOJbQtZw== +"@docsearch/css@3.6.3": + version "3.6.3" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.6.3.tgz#d787cc9d27a7e67305fa47d668656eb2e64c4526" + integrity sha512-3uvbg8E7rhqE1C4oBAK3tGlS2qfhi9zpfZgH/yjDPF73vd9B41urVIKujF4rczcF4E3qs34SedhehiDJ4UdNBA== -"@docsearch/react@^3.5.2", "@docsearch/react@^3.6.2": - version "3.6.2" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.6.2.tgz#32b16dd7d5614f0d39e6bc018549816b68d171b8" - integrity sha512-rtZce46OOkVflCQH71IdbXSFK+S8iJZlUF56XBW5rIgx/eG5qoomC7Ag3anZson1bBac/JFQn7XOBfved/IMRA== +"@docsearch/react@^3.5.2", "@docsearch/react@^3.6.3": + version "3.6.3" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.6.3.tgz#326a0811306060bfb481df3cd0db51adaa9f737c" + integrity sha512-2munr4uBuZq1PG+Ge+F+ldIdxb3Wi8OmEIv2tQQb4RvEvvph+xtQkxwHzVIEnt5s+HecwucuXwB+3JhcZboFLg== dependencies: "@algolia/autocomplete-core" "1.9.3" - "@algolia/autocomplete-preset-algolia" "1.9.3" - "@docsearch/css" "3.6.2" - algoliasearch "^4.19.1" + "@algolia/autocomplete-preset-algolia" "1.17.6" + "@docsearch/css" "3.6.3" + algoliasearch "^5.11.0" "@docusaurus/core@3.5.2", "@docusaurus/core@^3.5.2": version "3.5.2" @@ -1991,10 +2071,10 @@ unist-util-visit "^5.0.0" vfile "^6.0.0" -"@mdx-js/react@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.0.1.tgz#997a19b3a5b783d936c75ae7c47cfe62f967f746" - integrity sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A== +"@mdx-js/react@^3.0.0", "@mdx-js/react@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.1.0.tgz#c4522e335b3897b9a845db1dbdd2f966ae8fb0ed" + integrity sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ== dependencies: "@types/mdx" "^2.0.0" @@ -2115,10 +2195,10 @@ classnames "^2.3.2" rc-util "^5.24.4" -"@rc-component/trigger@^2.0.0", "@rc-component/trigger@^2.1.1", "@rc-component/trigger@^2.2.1": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@rc-component/trigger/-/trigger-2.2.2.tgz#7c8c27ce92cacbb32b1cda70f0533fe52202c41d" - integrity sha512-xDyi0fJ3IV6XJEReMOewS9PEnnuLHKz4rjbgIniDsJFHjL5nROuUlu64mfo90jglLDkQUxRwK7aTtumA65/zYQ== +"@rc-component/trigger@^2.0.0", "@rc-component/trigger@^2.1.1", "@rc-component/trigger@^2.2.3": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@rc-component/trigger/-/trigger-2.2.3.tgz#b47e945115e2d0a7f7e067dbb9ed76c91c1b4385" + integrity sha512-X1oFIpKoXAMXNDYCviOmTfuNuYxE4h5laBsyCqVAVMjNHxoF3/uiyA7XdegK1XbCvBbCZ6P6byWrEoDRpKL8+A== dependencies: "@babel/runtime" "^7.23.2" "@rc-component/portal" "^1.1.0" @@ -2127,10 +2207,10 @@ rc-resize-observer "^1.3.1" rc-util "^5.38.0" -"@saucelabs/theme-github-codeblock@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@saucelabs/theme-github-codeblock/-/theme-github-codeblock-0.2.3.tgz#706a43292f600532271979941b0155db667c2c21" - integrity sha512-GSl3Lr/jOWm4OP3BPX2vXxc8FMSOXj1mJnls6cUqMwlGOfKQ1Ia9pq1O9/ES+5TrZHIzAws/n5FFSn1OkGJw/Q== +"@saucelabs/theme-github-codeblock@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@saucelabs/theme-github-codeblock/-/theme-github-codeblock-0.3.0.tgz#7936bc6aa97a15f2483ac143df4918c8d2baf5f0" + integrity sha512-+8xWxBfN+I8StJ0QXERMbGf+BHwRXHWV3mFl9uDayXERiZ/rR93d0nAS3s9s/rKjqh/YSm/4dThEkBNBLnGs4Q== "@sideway/address@^4.1.5": version "4.1.5" @@ -2738,6 +2818,22 @@ dependencies: "@types/ms" "*" +"@types/eslint-scope@^3.7.7": + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.1.tgz#d5795ad732ce81715f27f75da913004a56751584" + integrity sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + "@types/estree-jsx@^1.0.0": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz#858a88ea20f34fe65111f005a689fa1ebf70dc18" @@ -2745,10 +2841,10 @@ dependencies: "@types/estree" "*" -"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== +"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": version "4.19.0" @@ -2835,7 +2931,7 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -2939,10 +3035,10 @@ "@types/history" "^4.7.11" "@types/react" "*" -"@types/react@*", "@types/react@^18.3.10": - version "18.3.10" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.10.tgz#6edc26dc22ff8c9c226d3c7bf8357b013c842219" - integrity sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg== +"@types/react@*", "@types/react@^18.3.12": + version "18.3.12" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.12.tgz#99419f182ccd69151813b7ee24b792fe08774f60" + integrity sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw== dependencies: "@types/prop-types" "*" csstype "^3.0.2" @@ -3168,11 +3264,6 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-import-attributes@^1.9.5: - version "1.9.5" - resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" - integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== - acorn-jsx@^5.0.0: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -3183,10 +3274,10 @@ acorn-walk@^8.0.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== -acorn@^8.0.0, acorn@^8.0.4, acorn@^8.7.1, acorn@^8.8.2: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.0.0, acorn@^8.0.4, acorn@^8.14.0, acorn@^8.8.2: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== address@^1.0.1, address@^1.1.2: version "1.2.2" @@ -3247,7 +3338,7 @@ algoliasearch-helper@^3.13.3: dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^4.18.0, algoliasearch@^4.19.1: +algoliasearch@^4.18.0: version "4.23.3" resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.23.3.tgz#e09011d0a3b0651444916a3e6bbcba064ec44b60" integrity sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg== @@ -3268,6 +3359,25 @@ algoliasearch@^4.18.0, algoliasearch@^4.19.1: "@algolia/requester-node-http" "4.23.3" "@algolia/transporter" "4.23.3" +algoliasearch@^5.11.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.12.0.tgz#2e822a7916d691e55058ea7dba277d5110969dd0" + integrity sha512-psGBRYdGgik8I6m28iAB8xpubvjEt7UQU+w5MAJUA2324WHiGoHap5BPkkjB14rMaXeRts6pmOsrVIglGyOVwg== + dependencies: + "@algolia/client-abtesting" "5.12.0" + "@algolia/client-analytics" "5.12.0" + "@algolia/client-common" "5.12.0" + "@algolia/client-insights" "5.12.0" + "@algolia/client-personalization" "5.12.0" + "@algolia/client-query-suggestions" "5.12.0" + "@algolia/client-search" "5.12.0" + "@algolia/ingestion" "1.12.0" + "@algolia/monitoring" "1.12.0" + "@algolia/recommend" "5.12.0" + "@algolia/requester-browser-xhr" "5.12.0" + "@algolia/requester-fetch" "5.12.0" + "@algolia/requester-node-http" "5.12.0" + ansi-align@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" @@ -3309,57 +3419,57 @@ ansi-styles@^6.1.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== -antd@^5.20.5: - version "5.20.5" - resolved "https://registry.yarnpkg.com/antd/-/antd-5.20.5.tgz#a55d5023759b08e501cabef3700d59664453fce0" - integrity sha512-w/oVwoZAt5qP0PKhOkCmYXe06kXuoTh7UdQlltba/IzpbCCEh465z3Qw3i9HZY745HtOIS6ze707mVsORzN18g== +antd@^5.21.6: + version "5.21.6" + resolved "https://registry.yarnpkg.com/antd/-/antd-5.21.6.tgz#60d8eb442f7f8019bab198e30ea5a8d6d224a6ce" + integrity sha512-EviOde/VEu+OsIKH5t6YXTMmmNeg9R85m0W5zXAo+Np8Latg9q10691JvAqOTMpnrRmbdeKUQL1Krp69Bzbe/g== dependencies: "@ant-design/colors" "^7.1.0" - "@ant-design/cssinjs" "^1.21.0" - "@ant-design/cssinjs-utils" "^1.0.3" - "@ant-design/icons" "^5.4.0" + "@ant-design/cssinjs" "^1.21.1" + "@ant-design/cssinjs-utils" "^1.1.1" + "@ant-design/icons" "^5.5.1" "@ant-design/react-slick" "~1.1.2" - "@babel/runtime" "^7.24.8" + "@babel/runtime" "^7.25.6" "@ctrl/tinycolor" "^3.6.1" "@rc-component/color-picker" "~2.0.1" "@rc-component/mutate-observer" "^1.1.0" "@rc-component/qrcode" "~1.0.0" "@rc-component/tour" "~1.15.1" - "@rc-component/trigger" "^2.2.1" + "@rc-component/trigger" "^2.2.3" classnames "^2.5.1" copy-to-clipboard "^3.3.3" dayjs "^1.11.11" - rc-cascader "~3.28.0" + rc-cascader "~3.28.2" rc-checkbox "~3.3.0" - rc-collapse "~3.7.3" - rc-dialog "~9.5.2" + rc-collapse "~3.8.0" + rc-dialog "~9.6.0" rc-drawer "~7.2.0" rc-dropdown "~4.2.0" rc-field-form "~2.4.0" - rc-image "~7.9.0" + rc-image "~7.11.0" rc-input "~1.6.3" rc-input-number "~9.2.0" - rc-mentions "~2.15.0" - rc-menu "~9.14.1" - rc-motion "^2.9.2" - rc-notification "~5.6.0" - rc-pagination "~4.2.0" - rc-picker "~4.6.14" + rc-mentions "~2.16.1" + rc-menu "~9.15.1" + rc-motion "^2.9.3" + rc-notification "~5.6.2" + rc-pagination "~4.3.0" + rc-picker "~4.6.15" rc-progress "~4.0.0" rc-rate "~2.13.0" rc-resize-observer "^1.4.0" - rc-segmented "~2.3.0" - rc-select "~14.15.1" - rc-slider "~11.1.5" + rc-segmented "~2.5.0" + rc-select "~14.15.2" + rc-slider "~11.1.7" rc-steps "~6.0.1" rc-switch "~4.1.0" - rc-table "~7.45.7" - rc-tabs "~15.1.1" - rc-textarea "~1.8.1" - rc-tooltip "~6.2.0" + rc-table "~7.47.5" + rc-tabs "~15.3.0" + rc-textarea "~1.8.2" + rc-tooltip "~6.2.1" rc-tree "~5.9.0" rc-tree-select "~5.23.0" - rc-upload "~4.7.0" + rc-upload "~4.8.1" rc-util "^5.43.0" scroll-into-view-if-needed "^3.1.0" throttle-debounce "^5.0.2" @@ -3641,15 +3751,15 @@ braces@^3.0.3, braces@~3.0.2: dependencies: fill-range "^7.1.1" -browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.21.10, browserslist@^4.22.2, browserslist@^4.23.0: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== +browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.22.2, browserslist@^4.23.0, browserslist@^4.24.0: + version "4.24.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580" + integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg== dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" + caniuse-lite "^1.0.30001669" + electron-to-chromium "^1.5.41" + node-releases "^2.0.18" + update-browserslist-db "^1.1.1" buffer-from@^1.0.0: version "1.1.2" @@ -3744,11 +3854,16 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001599: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001599: version "1.0.30001614" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001614.tgz#f894b4209376a0bf923d67d9c361d96b1dfebe39" integrity sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog== +caniuse-lite@^1.0.30001669: + version "1.0.30001677" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz#27c2e2c637e007cfa864a16f7dfe7cde66b38b5f" + integrity sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog== + ccount@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" @@ -4637,10 +4752,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.668: - version "1.4.752" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.752.tgz#99227455547c8254488e3dab7d316c34a2c067b8" - integrity sha512-P3QJreYI/AUTcfBVrC4zy9KvnZWekViThgQMX/VpJ+IsOBbcX5JFpORM4qWapwWQ+agb2nYAOyn/4PMXOk0m2Q== +electron-to-chromium@^1.5.41: + version "1.5.50" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz#d9ba818da7b2b5ef1f3dd32bce7046feb7e93234" + integrity sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw== emoji-regex@^8.0.0: version "8.0.0" @@ -4742,11 +4857,16 @@ es-module-lexer@^1.2.1: resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.2.tgz#00b423304f2500ac59359cc9b6844951f372d497" integrity sha512-l60ETUTmLqbVbVHv1J4/qj+M8nq7AwMzEcg3kmJDt9dCNrTk+yHcYFf/Kw75pMDwd9mPcIGCG5LcS20SxYRzFA== -escalade@^3.1.1, escalade@^3.1.2: +escalade@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + escape-goat@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-4.0.0.tgz#9424820331b510b0666b98f7873fe11ac4aa8081" @@ -5703,9 +5823,9 @@ http-parser-js@>=0.5.1: integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== http-proxy-middleware@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" - integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + version "2.0.7" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz#915f236d92ae98ef48278a95dedf17e991936ec6" + integrity sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA== dependencies: "@types/http-proxy" "^1.17.8" http-proxy "^1.18.1" @@ -7294,10 +7414,10 @@ node-forge@^1: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -7647,6 +7767,11 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -8184,10 +8309,10 @@ raw-body@2.5.2: iconv-lite "0.4.24" unpipe "1.0.0" -rc-cascader@~3.28.0: - version "3.28.1" - resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-3.28.1.tgz#ea8a3de60521290096bab7e3fbe8ca097b976468" - integrity sha512-9+8oHIMWVLHxuaapDiqFNmD9KSyKN/P4bo9x/MBuDbyTqP8f2/POmmZxdXWBO3yq/uE3pKyQCXYNUxrNfHRv2A== +rc-cascader@~3.28.2: + version "3.28.2" + resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-3.28.2.tgz#91720d3498261a7bff9fffc953501a8830f601fb" + integrity sha512-8f+JgM83iLTvjgdkgU7GfI4qY8icXOBP0cGZjOdx2iJAkEe8ucobxDQAVE69UD/c3ehCxZlcgEHeD5hFmypbUw== dependencies: "@babel/runtime" "^7.12.5" array-tree-filter "^2.1.0" @@ -8205,20 +8330,20 @@ rc-checkbox@~3.3.0: classnames "^2.3.2" rc-util "^5.25.2" -rc-collapse@~3.7.3: - version "3.7.3" - resolved "https://registry.yarnpkg.com/rc-collapse/-/rc-collapse-3.7.3.tgz#68161683d8fd1004bef4eb281fc106f3c8dc16eb" - integrity sha512-60FJcdTRn0X5sELF18TANwtVi7FtModq649H11mYF1jh83DniMoM4MqY627sEKRCTm4+WXfGDcB7hY5oW6xhyw== +rc-collapse@~3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/rc-collapse/-/rc-collapse-3.8.0.tgz#02bcf81e1601aa185cd3b9fab0ceefd8dc11aefb" + integrity sha512-YVBkssrKPBG09TGfcWWGj8zJBYD9G3XuTy89t5iUmSXrIXEAnO1M+qjUxRW6b4Qi0+wNWG6MHJF/+US+nmIlzA== dependencies: "@babel/runtime" "^7.10.1" classnames "2.x" rc-motion "^2.3.4" rc-util "^5.27.0" -rc-dialog@~9.5.2: - version "9.5.2" - resolved "https://registry.yarnpkg.com/rc-dialog/-/rc-dialog-9.5.2.tgz#4cf7cca23aedb6fd3d9344ea8ffd14daa94ee3a0" - integrity sha512-qVUjc8JukG+j/pNaHVSRa2GO2/KbV2thm7yO4hepQ902eGdYK913sGkwg/fh9yhKYV1ql3BKIN2xnud3rEXAPw== +rc-dialog@~9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/rc-dialog/-/rc-dialog-9.6.0.tgz#dc7a255c6ad1cb56021c3a61c7de86ee88c7c371" + integrity sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg== dependencies: "@babel/runtime" "^7.10.1" "@rc-component/portal" "^1.0.0-8" @@ -8256,15 +8381,15 @@ rc-field-form@~2.4.0: "@rc-component/async-validator" "^5.0.3" rc-util "^5.32.2" -rc-image@~7.9.0: - version "7.9.0" - resolved "https://registry.yarnpkg.com/rc-image/-/rc-image-7.9.0.tgz#2d700a5cf891bb3d0d800b7c38348927ebb9f49b" - integrity sha512-l4zqO5E0quuLMCtdKfBgj4Suv8tIS011F5k1zBBlK25iMjjiNHxA0VeTzGFtUZERSA45gvpXDg8/P6qNLjR25g== +rc-image@~7.11.0: + version "7.11.0" + resolved "https://registry.yarnpkg.com/rc-image/-/rc-image-7.11.0.tgz#18c77ea557a6fdbe26856c688a9aace1505c0e77" + integrity sha512-aZkTEZXqeqfPZtnSdNUnKQA0N/3MbgR7nUnZ+/4MfSFWPFHZau4p5r5ShaI0KPEMnNjv4kijSCFq/9wtJpwykw== dependencies: "@babel/runtime" "^7.11.2" "@rc-component/portal" "^1.0.2" classnames "^2.2.6" - rc-dialog "~9.5.2" + rc-dialog "~9.6.0" rc-motion "^2.6.2" rc-util "^5.34.1" @@ -8288,23 +8413,23 @@ rc-input@~1.6.0, rc-input@~1.6.3: classnames "^2.2.1" rc-util "^5.18.1" -rc-mentions@~2.15.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/rc-mentions/-/rc-mentions-2.15.0.tgz#ada022b32e68fa067a859ee0024c3f2aa7a9c871" - integrity sha512-f5v5i7VdqvBDXbphoqcQWmXDif2Msd2arritVoWybrVDuHE6nQ7XCYsybHbV//WylooK52BFDouFvyaRDtXZEw== +rc-mentions@~2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/rc-mentions/-/rc-mentions-2.16.1.tgz#5e54ebe3ce6cd79838846ff1c8cfaf2e7aa15cec" + integrity sha512-GnhSTGP9Mtv6pqFFGQze44LlrtWOjHNrUUAcsdo9DnNAhN4pwVPEWy4z+2jpjkiGlJ3VoXdvMHcNDQdfI9fEaw== dependencies: "@babel/runtime" "^7.22.5" "@rc-component/trigger" "^2.0.0" classnames "^2.2.6" rc-input "~1.6.0" - rc-menu "~9.14.0" + rc-menu "~9.15.1" rc-textarea "~1.8.0" rc-util "^5.34.1" -rc-menu@~9.14.0, rc-menu@~9.14.1: - version "9.14.1" - resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-9.14.1.tgz#5c2aea72bdce421e9d50bf721ad8b76c154ae66f" - integrity sha512-5wlRb3M8S4yGlWhSoEYJ7ZVRElyScdcpUHxgiLxkeig1tEdyKrnED3B2fhpN0Rrpdp9jyhnmZR/Lwq2fH5VvDQ== +rc-menu@~9.15.1: + version "9.15.1" + resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-9.15.1.tgz#d8b38ea534a7f596a8da063881519e7eaafca698" + integrity sha512-UKporqU6LPfHnpPmtP6hdEK4iO5Q+b7BRv/uRpxdIyDGplZy9jwUjsnpev5bs3PQKB0H0n34WAPDfjAfn3kAPA== dependencies: "@babel/runtime" "^7.10.1" "@rc-component/trigger" "^2.0.0" @@ -8313,19 +8438,19 @@ rc-menu@~9.14.0, rc-menu@~9.14.1: rc-overflow "^1.3.1" rc-util "^5.27.0" -rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motion@^2.4.3, rc-motion@^2.4.4, rc-motion@^2.6.1, rc-motion@^2.6.2, rc-motion@^2.9.0, rc-motion@^2.9.2: - version "2.9.2" - resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.9.2.tgz#f7c6d480250df8a512d0cfdce07ff3da906958cf" - integrity sha512-fUAhHKLDdkAXIDLH0GYwof3raS58dtNUmzLF2MeiR8o6n4thNpSDQhOqQzWE4WfFZDCi9VEN8n7tiB7czREcyw== +rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motion@^2.4.3, rc-motion@^2.4.4, rc-motion@^2.6.1, rc-motion@^2.6.2, rc-motion@^2.9.0, rc-motion@^2.9.3: + version "2.9.3" + resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.9.3.tgz#b1bdaf816f1ccb3e4b3b0c531c3037a59286379e" + integrity sha512-rkW47ABVkic7WEB0EKJqzySpvDqwl60/tdkY7hWP7dYnh5pm0SzJpo54oW3TDUGXV5wfxXFmMkxrzRRbotQ0+w== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" rc-util "^5.43.0" -rc-notification@~5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/rc-notification/-/rc-notification-5.6.0.tgz#1639aa30686d79ee4bb8ace05a698a5a104aaa74" - integrity sha512-TGQW5T7waOxLwgJG7fXcw8l7AQiFOjaZ7ISF5PrU526nunHRNcTMuzKihQHaF4E/h/KfOCDk3Mv8eqzbu2e28w== +rc-notification@~5.6.2: + version "5.6.2" + resolved "https://registry.yarnpkg.com/rc-notification/-/rc-notification-5.6.2.tgz#8525b32d49dd96ec974acae61d1d1eabde61463a" + integrity sha512-Id4IYMoii3zzrG0lB0gD6dPgJx4Iu95Xu0BQrhHIbp7ZnAZbLqdqQ73aIWH0d0UFcElxwaKjnzNovTjo7kXz7g== dependencies: "@babel/runtime" "^7.10.1" classnames "2.x" @@ -8342,19 +8467,19 @@ rc-overflow@^1.3.1, rc-overflow@^1.3.2: rc-resize-observer "^1.0.0" rc-util "^5.37.0" -rc-pagination@~4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-4.2.0.tgz#b7222b429dec38f6c74e139a30ae7765e9a0b8a6" - integrity sha512-V6qeANJsT6tmOcZ4XiUmj8JXjRLbkusuufpuoBw2GiAn94fIixYjFLmbruD1Sbhn8fPLDnWawPp4CN37zQorvw== +rc-pagination@~4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-4.3.0.tgz#c6022f820aa3a45fd734ae33a2915d39597dce1d" + integrity sha512-UubEWA0ShnroQ1tDa291Fzw6kj0iOeF26IsUObxYTpimgj4/qPCWVFl18RLZE+0Up1IZg0IK4pMn6nB3mjvB7g== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.3.2" rc-util "^5.38.0" -rc-picker@~4.6.14: - version "4.6.14" - resolved "https://registry.yarnpkg.com/rc-picker/-/rc-picker-4.6.14.tgz#86f6836794a593a54b929cfde201f42f02ef85b0" - integrity sha512-7DuTfUFdkxmsNpWQ0TWv6FPGna5e6KKC4nxtx3x9xhumLz7jb3fhlDdWQvqEL6tpt9DOb1+N5j+wB+lDOSS9kg== +rc-picker@~4.6.15: + version "4.6.15" + resolved "https://registry.yarnpkg.com/rc-picker/-/rc-picker-4.6.15.tgz#1531c9c382a295e2d1f1f38440d6678b09cd0468" + integrity sha512-OWZ1yrMie+KN2uEUfYCfS4b2Vu6RC1FWwNI0s+qypsc3wRt7g+peuZKVIzXCTaJwyyZruo80+akPg2+GmyiJjw== dependencies: "@babel/runtime" "^7.24.7" "@rc-component/trigger" "^2.0.0" @@ -8391,20 +8516,20 @@ rc-resize-observer@^1.0.0, rc-resize-observer@^1.1.0, rc-resize-observer@^1.3.1, rc-util "^5.38.0" resize-observer-polyfill "^1.5.1" -rc-segmented@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/rc-segmented/-/rc-segmented-2.3.0.tgz#b3fe080fb434a266c02e30bb62a47d2c6e094341" - integrity sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg== +rc-segmented@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/rc-segmented/-/rc-segmented-2.5.0.tgz#3b5423adf57459345c77c39c7581fde786a16c11" + integrity sha512-B28Fe3J9iUFOhFJET3RoXAPFJ2u47QvLSYcZWC4tFYNGPEjug5LAxEasZlA/PpAxhdOPqGWsGbSj7ftneukJnw== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" rc-motion "^2.4.4" rc-util "^5.17.0" -rc-select@~14.15.0, rc-select@~14.15.1: - version "14.15.1" - resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-14.15.1.tgz#1c8ab356cfdf1b24e974d62aec752620845d95a7" - integrity sha512-mGvuwW1RMm1NCSI8ZUoRoLRK51R2Nb+QJnmiAvbDRcjh2//ulCkxeV6ZRFTECPpE1t2DPfyqZMPw90SVJzQ7wQ== +rc-select@~14.15.0, rc-select@~14.15.2: + version "14.15.2" + resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-14.15.2.tgz#d85fcf3a708bdf837b003feeed653347b8980ad0" + integrity sha512-oNoXlaFmpqXYcQDzcPVLrEqS2J9c+/+oJuGrlXeVVX/gVgrbHa5YcyiRUXRydFjyuA7GP3elRuLF7Y3Tfwltlw== dependencies: "@babel/runtime" "^7.10.1" "@rc-component/trigger" "^2.1.1" @@ -8414,10 +8539,10 @@ rc-select@~14.15.0, rc-select@~14.15.1: rc-util "^5.16.1" rc-virtual-list "^3.5.2" -rc-slider@~11.1.5: - version "11.1.5" - resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-11.1.5.tgz#9a596464a36d78feb90589fee4eb0bf7cec40584" - integrity sha512-b77H5PbjMKsvkYXAYIkn50QuFX6ICQmCTibDinI9q+BHx65/TV4TeU25+oadhSRzykxs0/vBWeKBwRyySOeWlg== +rc-slider@~11.1.7: + version "11.1.7" + resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-11.1.7.tgz#3de333b1ec84d53a7bda2f816bb4779423628f09" + integrity sha512-ytYbZei81TX7otdC0QvoYD72XSlxvTihNth5OeZ6PMXyEDq/vHdWFulQmfDGyXK1NwKwSlKgpvINOa88uT5g2A== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.5" @@ -8441,35 +8566,35 @@ rc-switch@~4.1.0: classnames "^2.2.1" rc-util "^5.30.0" -rc-table@~7.45.7: - version "7.45.7" - resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.45.7.tgz#f7c509e05c677a30ad5b212750122da6f5318004" - integrity sha512-wi9LetBL1t1csxyGkMB2p3mCiMt+NDexMlPbXHvQFmBBAsMxrgNSAPwUci2zDLUq9m8QdWc1Nh8suvrpy9mXrg== +rc-table@~7.47.5: + version "7.47.5" + resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.47.5.tgz#3c530200baa82346c7e72fe9b1dbd47d4aa15838" + integrity sha512-fzq+V9j/atbPIcvs3emuclaEoXulwQpIiJA6/7ey52j8+9cJ4P8DGmp4YzfUVDrb3qhgedcVeD6eRgUrokwVEQ== dependencies: "@babel/runtime" "^7.10.1" "@rc-component/context" "^1.4.0" classnames "^2.2.5" rc-resize-observer "^1.1.0" - rc-util "^5.37.0" + rc-util "^5.41.0" rc-virtual-list "^3.14.2" -rc-tabs@~15.1.1: - version "15.1.1" - resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-15.1.1.tgz#99f4c7647e01d3e22216d94222d717e928ed98d0" - integrity sha512-Tc7bJvpEdkWIVCUL7yQrMNBJY3j44NcyWS48jF/UKMXuUlzaXK+Z/pEL5LjGcTadtPvVmNqA40yv7hmr+tCOAw== +rc-tabs@~15.3.0: + version "15.3.0" + resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-15.3.0.tgz#3fcc332fbb9307d5eb147e0404daca871fb92a89" + integrity sha512-lzE18r+zppT/jZWOAWS6ntdkDUKHOLJzqMi5UAij1LeKwOaQaupupAoI9Srn73GRzVpmGznkECMRrzkRusC40A== dependencies: "@babel/runtime" "^7.11.2" classnames "2.x" rc-dropdown "~4.2.0" - rc-menu "~9.14.0" + rc-menu "~9.15.1" rc-motion "^2.6.2" rc-resize-observer "^1.0.0" rc-util "^5.34.1" -rc-textarea@~1.8.0, rc-textarea@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/rc-textarea/-/rc-textarea-1.8.1.tgz#0313ed2e7980269e1bd4f3c203a4e9a84cad8e2d" - integrity sha512-bm36N2ZqwZAP60ZQg2OY9mPdqWC+m6UTjHc+CqEZOxb3Ia29BGHazY/s5bI8M4113CkqTzhtFUDNA078ZiOx3Q== +rc-textarea@~1.8.0, rc-textarea@~1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/rc-textarea/-/rc-textarea-1.8.2.tgz#57a6847304551c1883fc3fb0c5076d587f70bf7f" + integrity sha512-UFAezAqltyR00a8Lf0IPAyTd29Jj9ee8wt8DqXyDMal7r/Cg/nDt3e1OOv3Th4W6mKaZijjgwuPXhAfVNTN8sw== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.1" @@ -8477,10 +8602,10 @@ rc-textarea@~1.8.0, rc-textarea@~1.8.1: rc-resize-observer "^1.0.0" rc-util "^5.27.0" -rc-tooltip@~6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-6.2.0.tgz#4dd7575674137a5b14f118a5c16435d3f5e4a9c9" - integrity sha512-iS/3iOAvtDh9GIx1ulY7EFUXUtktFccNLsARo3NPgLf0QW9oT0w3dA9cYWlhqAKmD+uriEwdWz1kH0Qs4zk2Aw== +rc-tooltip@~6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-6.2.1.tgz#9a8f0335c86443a0c20c2557933205f645a381b7" + integrity sha512-rws0duD/3sHHsD905Nex7FvoUGy2UBQRhTkKxeEvr2FB+r21HsOxcDJI0TzyO8NHhnAA8ILr8pfbSBg5Jj5KBg== dependencies: "@babel/runtime" "^7.11.2" "@rc-component/trigger" "^2.0.0" @@ -8508,16 +8633,16 @@ rc-tree@~5.9.0: rc-util "^5.16.1" rc-virtual-list "^3.5.1" -rc-upload@~4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/rc-upload/-/rc-upload-4.7.0.tgz#719c6e66549844f4db8c57f066f2758c0a43b525" - integrity sha512-eUwxYNHlsYe5vYhKFAUGrQG95JrnPzY+BmPi1Daq39fWNl/eOc7v4UODuWrVp2LFkQBuV3cMCG/I68iub6oBrg== +rc-upload@~4.8.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/rc-upload/-/rc-upload-4.8.1.tgz#ac55f2bc101b95b52a6e47f3c18f0f55b54e16d2" + integrity sha512-toEAhwl4hjLAI1u8/CgKWt30BR06ulPa4iGQSMvSXoHzO88gPCslxqV/mnn4gJU7PDoltGIC9Eh+wkeudqgHyw== dependencies: "@babel/runtime" "^7.18.3" classnames "^2.2.5" rc-util "^5.2.0" -rc-util@^5.0.1, rc-util@^5.16.1, rc-util@^5.17.0, rc-util@^5.18.1, rc-util@^5.2.0, rc-util@^5.20.1, rc-util@^5.21.0, rc-util@^5.24.4, rc-util@^5.25.2, rc-util@^5.27.0, rc-util@^5.30.0, rc-util@^5.31.1, rc-util@^5.32.2, rc-util@^5.34.1, rc-util@^5.35.0, rc-util@^5.36.0, rc-util@^5.37.0, rc-util@^5.38.0, rc-util@^5.38.1, rc-util@^5.40.1, rc-util@^5.43.0: +rc-util@^5.0.1, rc-util@^5.16.1, rc-util@^5.17.0, rc-util@^5.18.1, rc-util@^5.2.0, rc-util@^5.20.1, rc-util@^5.21.0, rc-util@^5.24.4, rc-util@^5.25.2, rc-util@^5.27.0, rc-util@^5.30.0, rc-util@^5.31.1, rc-util@^5.32.2, rc-util@^5.34.1, rc-util@^5.35.0, rc-util@^5.36.0, rc-util@^5.37.0, rc-util@^5.38.0, rc-util@^5.38.1, rc-util@^5.40.1, rc-util@^5.41.0, rc-util@^5.43.0: version "5.43.0" resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.43.0.tgz#bba91fbef2c3e30ea2c236893746f3e9b05ecc4c" integrity sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw== @@ -9668,10 +9793,10 @@ stylehacks@^6.1.1: browserslist "^4.23.0" postcss-selector-parser "^6.0.16" -stylis@^4.0.13: - version "4.3.2" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.2.tgz#8f76b70777dd53eb669c6f58c997bf0a9972e444" - integrity sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg== +stylis@^4.3.3: + version "4.3.4" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.4.tgz#ca5c6c4a35c4784e4e93a2a24dc4e9fa075250a4" + integrity sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now== supports-color@^5.3.0: version "5.5.0" @@ -9984,10 +10109,10 @@ types-ramda@^0.30.0: dependencies: ts-toolbelt "^9.6.0" -typescript@^5.6.2: - version "5.6.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.2.tgz#d1de67b6bef77c41823f822df8f0b3bcff60a5a0" - integrity sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw== +typescript@^5.6.3: + version "5.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== undici-types@~5.26.4: version "5.26.5" @@ -10110,13 +10235,13 @@ unraw@^3.0.0: resolved "https://registry.yarnpkg.com/unraw/-/unraw-3.0.0.tgz#73443ed70d2ab09ccbac2b00525602d5991fbbe3" integrity sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg== -update-browserslist-db@^1.0.13: - version "1.0.14" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.14.tgz#46a9367c323f8ade9a9dddb7f3ae7814b3a0b31c" - integrity sha512-JixKH8GR2pWYshIPUg/NujK3JO7JiqEEUiNArE86NQyrgUuZeTlZQN3xuS/yiV5Kb48ev9K6RqNkaJjXsdg7Jw== +update-browserslist-db@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" + integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== dependencies: - escalade "^3.1.2" - picocolors "^1.0.0" + escalade "^3.2.0" + picocolors "^1.1.0" update-notifier@^6.0.2: version "6.0.2" @@ -10336,18 +10461,18 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.88.1, webpack@^5.94.0: - version "5.94.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.94.0.tgz#77a6089c716e7ab90c1c67574a28da518a20970f" - integrity sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg== +webpack@^5.88.1, webpack@^5.96.1: + version "5.96.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.96.1.tgz#3676d1626d8312b6b10d0c18cc049fba7ac01f0c" + integrity sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA== dependencies: - "@types/estree" "^1.0.5" + "@types/eslint-scope" "^3.7.7" + "@types/estree" "^1.0.6" "@webassemblyjs/ast" "^1.12.1" "@webassemblyjs/wasm-edit" "^1.12.1" "@webassemblyjs/wasm-parser" "^1.12.1" - acorn "^8.7.1" - acorn-import-attributes "^1.9.5" - browserslist "^4.21.10" + acorn "^8.14.0" + browserslist "^4.24.0" chrome-trace-event "^1.0.2" enhanced-resolve "^5.17.1" es-module-lexer "^1.2.1" diff --git a/helm/superset/Chart.yaml b/helm/superset/Chart.yaml index 9ce9dd379be1b..2988973071a52 100644 --- a/helm/superset/Chart.yaml +++ b/helm/superset/Chart.yaml @@ -29,7 +29,7 @@ maintainers: - name: craig-rueda email: craig@craigrueda.com url: https://github.com/craig-rueda -version: 0.12.13 +version: 0.13.0 dependencies: - name: postgresql version: 12.1.6 diff --git a/helm/superset/README.md b/helm/superset/README.md index 5aeda56426aa7..796fddfd006ef 100644 --- a/helm/superset/README.md +++ b/helm/superset/README.md @@ -23,7 +23,7 @@ NOTE: This file is generated by helm-docs: https://github.com/norwoodj/helm-docs # superset -![Version: 0.12.13](https://img.shields.io/badge/Version-0.12.13-informational?style=flat-square) +![Version: 0.13.0](https://img.shields.io/badge/Version-0.13.0-informational?style=flat-square) Apache Superset is a modern, enterprise-ready business intelligence web application @@ -69,6 +69,7 @@ On helm this can be set on `extraSecretEnv.SUPERSET_SECRET_KEY` or `configOverri | extraConfigs | object | `{}` | Extra files to mount on `/app/pythonpath` | | extraEnv | object | `{}` | Extra environment variables that will be passed into pods | | extraEnvRaw | list | `[]` | Extra environment variables in RAW format that will be passed into pods | +| extraLabels | object | `{}` | Labels to be added to all resources | | extraSecretEnv | object | `{}` | Extra environment variables to pass as secrets | | extraSecrets | object | `{}` | Extra files to mount on `/app/pythonpath` as secrets | | extraVolumeMounts | list | `[]` | | diff --git a/helm/superset/templates/configmap-superset.yaml b/helm/superset/templates/configmap-superset.yaml index 9ca29666d285a..fa0928c1fbc2c 100644 --- a/helm/superset/templates/configmap-superset.yaml +++ b/helm/superset/templates/configmap-superset.yaml @@ -28,6 +28,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} data: {{- range $path, $config := .Values.extraConfigs }} {{ $path }}: | diff --git a/helm/superset/templates/deployment-beat.yaml b/helm/superset/templates/deployment-beat.yaml index df2fb1d2e909c..ff298f478d4d3 100644 --- a/helm/superset/templates/deployment-beat.yaml +++ b/helm/superset/templates/deployment-beat.yaml @@ -28,6 +28,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- if .Values.supersetCeleryBeat.deploymentAnnotations }} annotations: {{- toYaml .Values.supersetCeleryBeat.deploymentAnnotations | nindent 4 }} {{- end }} @@ -58,6 +61,9 @@ spec: labels: app: "{{ template "superset.name" . }}-celerybeat" release: {{ .Release.Name }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 8 }} + {{- end }} {{- if .Values.supersetCeleryBeat.podLabels }} {{- toYaml .Values.supersetCeleryBeat.podLabels | nindent 8 }} {{- end }} diff --git a/helm/superset/templates/deployment-flower.yaml b/helm/superset/templates/deployment-flower.yaml index c03c8a19f6a29..179df9309dd49 100644 --- a/helm/superset/templates/deployment-flower.yaml +++ b/helm/superset/templates/deployment-flower.yaml @@ -28,6 +28,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- if .Values.supersetCeleryFlower.deploymentAnnotations }} annotations: {{- toYaml .Values.supersetCeleryFlower.deploymentAnnotations | nindent 4 }} {{- end }} @@ -47,6 +50,9 @@ spec: labels: app: "{{ template "superset.name" . }}-flower" release: {{ .Release.Name }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 8 }} + {{- end }} {{- if .Values.supersetCeleryFlower.podLabels }} {{- toYaml .Values.supersetCeleryFlower.podLabels | nindent 8 }} {{- end }} diff --git a/helm/superset/templates/deployment-worker.yaml b/helm/superset/templates/deployment-worker.yaml index 214f9215f7295..96ee915f290ef 100644 --- a/helm/superset/templates/deployment-worker.yaml +++ b/helm/superset/templates/deployment-worker.yaml @@ -27,6 +27,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- if .Values.supersetWorker.deploymentLabels }} {{- toYaml .Values.supersetWorker.deploymentLabels | nindent 4 }} {{- end }} @@ -64,6 +67,9 @@ spec: labels: app: {{ template "superset.name" . }}-worker release: {{ .Release.Name }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 8 }} + {{- end }} {{- if .Values.supersetWorker.podLabels }} {{- toYaml .Values.supersetWorker.podLabels | nindent 8 }} {{- end }} diff --git a/helm/superset/templates/deployment-ws.yaml b/helm/superset/templates/deployment-ws.yaml index f9ac663be936d..868b84309ffbb 100644 --- a/helm/superset/templates/deployment-ws.yaml +++ b/helm/superset/templates/deployment-ws.yaml @@ -28,6 +28,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- if .Values.supersetWebsockets.deploymentAnnotations }} annotations: {{- toYaml .Values.supersetWebsockets.deploymentAnnotations | nindent 4 }} {{- end }} @@ -50,6 +53,9 @@ spec: labels: app: "{{ template "superset.name" . }}-ws" release: {{ .Release.Name }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 8 }} + {{- end }} {{- if .Values.supersetWebsockets.podLabels }} {{- toYaml .Values.supersetWebsockets.podLabels | nindent 8 }} {{- end }} diff --git a/helm/superset/templates/deployment.yaml b/helm/superset/templates/deployment.yaml index 60eddc4165a4a..444ec103da66c 100644 --- a/helm/superset/templates/deployment.yaml +++ b/helm/superset/templates/deployment.yaml @@ -27,6 +27,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- if .Values.supersetNode.deploymentLabels }} {{- toYaml .Values.supersetNode.deploymentLabels | nindent 4 }} {{- end }} @@ -66,6 +69,9 @@ spec: labels: app: {{ template "superset.name" . }} release: {{ .Release.Name }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 8 }} + {{- end }} {{- if .Values.supersetNode.podLabels }} {{- toYaml .Values.supersetNode.podLabels | nindent 8 }} {{- end }} diff --git a/helm/superset/templates/hpa-node.yaml b/helm/superset/templates/hpa-node.yaml index aee2d1da78fd8..843620ea15e66 100644 --- a/helm/superset/templates/hpa-node.yaml +++ b/helm/superset/templates/hpa-node.yaml @@ -27,6 +27,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} spec: scaleTargetRef: apiVersion: apps/v1 diff --git a/helm/superset/templates/hpa-worker.yaml b/helm/superset/templates/hpa-worker.yaml index f2fd2154a46a4..fd4f027cc6b39 100644 --- a/helm/superset/templates/hpa-worker.yaml +++ b/helm/superset/templates/hpa-worker.yaml @@ -27,6 +27,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} spec: scaleTargetRef: apiVersion: apps/v1 diff --git a/helm/superset/templates/ingress.yaml b/helm/superset/templates/ingress.yaml index 749c29134e2cf..05acb20d6ffce 100644 --- a/helm/superset/templates/ingress.yaml +++ b/helm/superset/templates/ingress.yaml @@ -29,6 +29,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- with .Values.ingress.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} diff --git a/helm/superset/templates/init-job.yaml b/helm/superset/templates/init-job.yaml index ecc51490ef99f..0cb46e816b0ea 100644 --- a/helm/superset/templates/init-job.yaml +++ b/helm/superset/templates/init-job.yaml @@ -23,6 +23,10 @@ kind: Job metadata: name: {{ template "superset.fullname" . }}-init-db namespace: {{ .Release.Namespace }} + {{- if .Values.extraLabels }} + labels: + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- if .Values.init.jobAnnotations }} annotations: {{- toYaml .Values.init.jobAnnotations | nindent 4 }} {{- end }} diff --git a/helm/superset/templates/pdb-beat.yaml b/helm/superset/templates/pdb-beat.yaml index de808b475c166..91cf5ddc58503 100644 --- a/helm/superset/templates/pdb-beat.yaml +++ b/helm/superset/templates/pdb-beat.yaml @@ -31,6 +31,9 @@ metadata: chart: {{ template "superset.chart" $ }} release: {{ $.Release.Name }} heritage: {{ $.Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} spec: {{- if .minAvailable }} minAvailable: {{ .minAvailable }} diff --git a/helm/superset/templates/pdb-flower.yaml b/helm/superset/templates/pdb-flower.yaml index 363ec7a42aebd..241de3143cd7e 100644 --- a/helm/superset/templates/pdb-flower.yaml +++ b/helm/superset/templates/pdb-flower.yaml @@ -31,6 +31,9 @@ metadata: chart: {{ template "superset.chart" $ }} release: {{ $.Release.Name }} heritage: {{ $.Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} spec: {{- if .minAvailable }} minAvailable: {{ .minAvailable }} diff --git a/helm/superset/templates/pdb-worker.yaml b/helm/superset/templates/pdb-worker.yaml index 163662261664d..d4ec768fba2a5 100644 --- a/helm/superset/templates/pdb-worker.yaml +++ b/helm/superset/templates/pdb-worker.yaml @@ -31,6 +31,9 @@ metadata: chart: {{ template "superset.chart" $ }} release: {{ $.Release.Name }} heritage: {{ $.Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} spec: {{- if .minAvailable }} minAvailable: {{ .minAvailable }} diff --git a/helm/superset/templates/pdb-ws.yaml b/helm/superset/templates/pdb-ws.yaml index 647d6b49447d4..0e303880aa115 100644 --- a/helm/superset/templates/pdb-ws.yaml +++ b/helm/superset/templates/pdb-ws.yaml @@ -31,6 +31,9 @@ metadata: chart: {{ template "superset.chart" $ }} release: {{ $.Release.Name }} heritage: {{ $.Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} spec: {{- if .minAvailable }} minAvailable: {{ .minAvailable }} diff --git a/helm/superset/templates/pdb.yaml b/helm/superset/templates/pdb.yaml index 0d825343d3147..3f86836f68d3b 100644 --- a/helm/superset/templates/pdb.yaml +++ b/helm/superset/templates/pdb.yaml @@ -31,6 +31,9 @@ metadata: chart: {{ template "superset.chart" $ }} release: {{ $.Release.Name }} heritage: {{ $.Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} spec: {{- if .minAvailable }} minAvailable: {{ .minAvailable }} diff --git a/helm/superset/templates/secret-env.yaml b/helm/superset/templates/secret-env.yaml index 653799496076d..04169ad15050f 100644 --- a/helm/superset/templates/secret-env.yaml +++ b/helm/superset/templates/secret-env.yaml @@ -27,6 +27,9 @@ metadata: chart: {{ template "superset.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} type: Opaque stringData: REDIS_HOST: {{ tpl .Values.supersetNode.connections.redis_host . | quote }} diff --git a/helm/superset/templates/secret-superset-config.yaml b/helm/superset/templates/secret-superset-config.yaml index 41a051fa03708..c672fe900b09e 100644 --- a/helm/superset/templates/secret-superset-config.yaml +++ b/helm/superset/templates/secret-superset-config.yaml @@ -27,6 +27,9 @@ metadata: chart: {{ template "superset.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} type: Opaque stringData: superset_config.py: | diff --git a/helm/superset/templates/secret-ws.yaml b/helm/superset/templates/secret-ws.yaml index aaa9a24587a33..a559ac0056ada 100644 --- a/helm/superset/templates/secret-ws.yaml +++ b/helm/superset/templates/secret-ws.yaml @@ -28,6 +28,9 @@ metadata: chart: {{ template "superset.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} type: Opaque stringData: config.json: | diff --git a/helm/superset/templates/service-flower.yaml b/helm/superset/templates/service-flower.yaml index 8c198891b0a57..c2bda0fb86ba3 100644 --- a/helm/superset/templates/service-flower.yaml +++ b/helm/superset/templates/service-flower.yaml @@ -28,6 +28,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- with .Values.supersetCeleryFlower.service.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} diff --git a/helm/superset/templates/service-ws.yaml b/helm/superset/templates/service-ws.yaml index 3dd02b77a6d2e..1517e2e5772e3 100644 --- a/helm/superset/templates/service-ws.yaml +++ b/helm/superset/templates/service-ws.yaml @@ -28,6 +28,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- with .Values.supersetWebsockets.service.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} diff --git a/helm/superset/templates/service.yaml b/helm/superset/templates/service.yaml index f20c80c78d9ce..e435961ba9b6d 100644 --- a/helm/superset/templates/service.yaml +++ b/helm/superset/templates/service.yaml @@ -27,6 +27,9 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- with .Values.service.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} diff --git a/helm/superset/templates/serviceaccount.yaml b/helm/superset/templates/serviceaccount.yaml index 0c2cfb30efa34..e92fc6202fa0b 100644 --- a/helm/superset/templates/serviceaccount.yaml +++ b/helm/superset/templates/serviceaccount.yaml @@ -32,6 +32,9 @@ metadata: kubernetes.io/cluster-service: "true" {{- end }} addonmanager.kubernetes.io/mode: Reconcile + {{- if .Values.extraLabels }} + {{- toYaml .Values.extraLabels | nindent 4 }} + {{- end }} {{- if .Values.serviceAccount.annotations }} annotations: {{- toYaml .Values.serviceAccount.annotations | nindent 4 }} {{- end }} diff --git a/helm/superset/values.yaml b/helm/superset/values.yaml index c0fcda027edb9..7bd2a7b20a287 100644 --- a/helm/superset/values.yaml +++ b/helm/superset/values.yaml @@ -27,6 +27,9 @@ nameOverride: ~ # -- Provide a name to override the full names of resources fullnameOverride: ~ +# -- Labels to be added to all resources +extraLabels: {} + # -- User ID directive. This user must have enough permissions to run the bootstrap script # Running containers as root is not recommended in production. Change this to another UID - e.g. 1000 to be more secure runAsUser: 0 diff --git a/pyproject.toml b/pyproject.toml index ada303a4e9662..551e12bc1ea4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -119,6 +119,7 @@ databricks = [ "sqlalchemy-databricks>=0.2.0", ] db2 = ["ibm-db-sa>0.3.8, <=0.4.0"] +denodo = ["denodo-sqlalchemy~=1.0.6"] dremio = ["sqlalchemy-dremio>=1.2.1, <4"] drill = ["sqlalchemy-drill>=1.1.4, <2"] druid = ["pydruid>=0.6.5,<0.7"] @@ -187,6 +188,7 @@ development = [ "pip-compile-multi", "pre-commit", "progress>=1.5,<2", + "psutil", "pyfakefs", "pyinstrument>=4.0.2,<5", "pylint", diff --git a/requirements/base.txt b/requirements/base.txt index 904b1a18fc061..f4f7a441d57d4 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -109,7 +109,7 @@ flask==2.3.3 # flask-session # flask-sqlalchemy # flask-wtf -flask-appbuilder==4.5.0 +flask-appbuilder==4.5.2 # via apache-superset flask-babel==2.0.0 # via flask-appbuilder @@ -385,7 +385,7 @@ vine==5.1.0 # kombu wcwidth==0.2.13 # via prompt-toolkit -werkzeug==3.0.3 +werkzeug==3.0.6 # via # -r requirements/base.in # flask @@ -394,7 +394,7 @@ werkzeug==3.0.3 # flask-login wrapt==1.16.0 # via deprecated -wtforms==3.1.2 +wtforms==3.2.1 # via # apache-superset # flask-appbuilder diff --git a/requirements/development.txt b/requirements/development.txt index b2ed1b8b3a1cc..b8c93cca56509 100644 --- a/requirements/development.txt +++ b/requirements/development.txt @@ -174,6 +174,8 @@ protobuf==4.23.0 # googleapis-common-protos # grpcio-status # proto-plus +psutil==6.0.0 + # via apache-superset psycopg2-binary==2.9.6 # via apache-superset pure-sasl==0.6.2 @@ -186,7 +188,7 @@ pyee==11.0.1 # via playwright pyfakefs==5.3.5 # via apache-superset -pyhive[hive_pure_sasl]==0.7.0 +pyhive[presto]==0.7.0 # via apache-superset pyinstrument==4.4.0 # via apache-superset @@ -233,6 +235,16 @@ thrift==0.16.0 # thrift-sasl thrift-sasl==0.4.3 # via apache-superset +tomli==2.0.1 + # via + # build + # coverage + # pip-tools + # pylint + # pyproject-api + # pyproject-hooks + # pytest + # tox tomlkit==0.12.5 # via pylint toposort==1.10 diff --git a/scripts/check-env.py b/scripts/check-env.py new file mode 100755 index 0000000000000..647aa11421bd0 --- /dev/null +++ b/scripts/check-env.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python3 +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import platform +import subprocess +import sys +from typing import Callable, Optional, Set, Tuple + +import click +import psutil +from packaging.version import InvalidVersion, Version + + +class Requirement: + def __init__( + self, + name: str, + ideal_range: Tuple[Version, Version], + supported_range: Tuple[Version, Version], + req_type: str, + command: str, + version_post_process: Optional[Callable[[str], str]] = None, + ): + self.name = name + self.ideal_range = ideal_range + self.supported_range = supported_range + self.req_type = req_type + self.command = command + self.version_post_process = version_post_process + self.version = self.get_version() + self.status = self.check_version() + + def get_version(self) -> Optional[str]: + try: + version = subprocess.check_output(self.command, shell=True).decode().strip() + if self.version_post_process: + version = self.version_post_process(version) + return version.split()[-1] + except subprocess.CalledProcessError: + return None + + def check_version(self) -> str: + if self.version is None: + return "❌ Not Installed" + + try: + version_number = Version(self.version) + except InvalidVersion: + return "❌ Invalid Version Format" + + ideal_min, ideal_max = self.ideal_range + supported_min, supported_max = self.supported_range + + if ideal_min <= version_number <= ideal_max: + return "✅ Ideal" + elif supported_min <= version_number: + return "🟡 Supported" + else: + return "❌ Unsupported" + + def format_result(self) -> str: + ideal_range_str = f"{self.ideal_range[0]} - {self.ideal_range[1]}" + supported_range_str = f"{self.supported_range[0]} - {self.supported_range[1]}" + return f"{self.status.split()[0]} {self.name:<25} {self.version or 'N/A':<25} {ideal_range_str:<25} {supported_range_str:<25}" + + +def check_memory(min_gb: int) -> str: + total_memory = psutil.virtual_memory().total / (1024**3) + if total_memory >= min_gb: + return f"✅ Memory: {total_memory:.2f} GB" + else: + return f"❌ Memory: {total_memory:.2f} GB (Minimum required: {min_gb} GB)" + + +def get_cpu_info() -> str: + cpu_count = psutil.cpu_count(logical=True) + cpu_freq = psutil.cpu_freq() + cpu_info = ( + f"{cpu_count} cores at {cpu_freq.current:.2f} MHz" + if cpu_freq + else f"{cpu_count} cores" + ) + return f"CPU: {cpu_info}" + + +def get_docker_platform() -> str: + try: + output = ( + subprocess.check_output( + "docker info --format '{{.OperatingSystem}}'", shell=True + ) + .decode() + .strip() + ) + if "Docker Desktop" in output: + return f"Docker Platform: {output} ({platform.system()})" + return f"Docker Platform: {output}" + except subprocess.CalledProcessError: + return "Docker Platform: ❌ Not Detected" + + +@click.command( + help=""" +This script checks the local environment for various software versions and other requirements, providing feedback on whether they are ideal, supported, or unsupported. +""" +) +@click.option( + "--docker", is_flag=True, help="Check Docker and Docker Compose requirements" +) +@click.option( + "--frontend", + is_flag=True, + help="Check frontend requirements (npm, Node.js, memory)", +) +@click.option("--backend", is_flag=True, help="Check backend requirements (Python)") +def main(docker: bool, frontend: bool, backend: bool) -> None: + requirements = [ + Requirement( + "python", + (Version("3.10.0"), Version("3.10.999")), + (Version("3.9.0"), Version("3.11.999")), + "backend", + "python --version", + ), + Requirement( + "npm", + (Version("10.0.0"), Version("999.999.999")), + (Version("10.0.0"), Version("999.999.999")), + "frontend", + "npm -v", + ), + Requirement( + "node", + (Version("20.0.0"), Version("20.999.999")), + (Version("20.0.0"), Version("20.999.999")), + "frontend", + "node -v", + ), + Requirement( + "docker", + (Version("20.10.0"), Version("999.999.999")), + (Version("19.0.0"), Version("999.999.999")), + "docker", + "docker --version", + lambda v: v.split(",")[0], + ), + Requirement( + "docker-compose", + (Version("2.28.0"), Version("999.999.999")), + (Version("1.29.0"), Version("999.999.999")), + "docker", + "docker-compose --version", + ), + Requirement( + "git", + (Version("2.30.0"), Version("999.999.999")), + (Version("2.20.0"), Version("999.999.999")), + "backend", + "git --version", + ), + ] + + print("==================") + print("System Information") + print("==================") + print(f"OS: {platform.system()} {platform.release()}") + print(get_cpu_info()) + print(get_docker_platform()) + print("\n") + + check_req_types: Set[str] = set() + if docker: + check_req_types.add("docker") + if frontend: + check_req_types.add("frontend") + if backend: + check_req_types.add("backend") + if not check_req_types: + check_req_types.update(["docker", "frontend", "backend"]) + + headers = ["Status", "Software", "Version Found", "Ideal Range", "Supported Range"] + row_format = "{:<2} {:<25} {:<25} {:<25} {:<25}" + + print("=" * 100) + print(row_format.format(*headers)) + print("=" * 100) + + all_ok = True + for requirement in requirements: + if requirement.req_type in check_req_types: + result = requirement.format_result() + if "❌" in requirement.status: + all_ok = False + print(result) + + if "frontend" in check_req_types: + memory_check = check_memory(12) + if "❌" in memory_check: + all_ok = False + print(memory_check) + + if not all_ok: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js index 700652a0171d3..9777651427545 100644 --- a/superset-frontend/.eslintrc.js +++ b/superset-frontend/.eslintrc.js @@ -280,7 +280,6 @@ module.exports = { 'theme-colors/no-literal-colors': 0, 'translation-vars/no-template-vars': 0, 'no-restricted-imports': 0, - 'jest/no-alias-methods': 0, 'react/no-void-elements': 0, }, }, @@ -371,7 +370,6 @@ module.exports = { 'react-prefer-function-component/react-prefer-function-component': 1, 'prettier/prettier': 'error', // disabling some things that come with the eslint 7->8 upgrade. Will address these in a separate PR - 'jest/no-alias-methods': 0, 'react/no-unknown-property': 0, 'react/no-void-elements': 0, 'react/function-component-definition': [ diff --git a/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts b/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts index 7b89b75a4ba62..854f0a5880f3a 100644 --- a/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts +++ b/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts @@ -378,7 +378,7 @@ export function cancelNativeFilterSettings() { .should('be.visible') .should('have.text', 'There are unsaved changes.'); cy.get(nativeFilters.modal.footer) - .find(nativeFilters.modal.yesCancelButton) + .find(nativeFilters.modal.confirmCancelButton) .contains('cancel') .click({ force: true }); cy.get(nativeFilters.modal.container).should('not.exist'); diff --git a/superset-frontend/cypress-base/cypress/support/directories.ts b/superset-frontend/cypress-base/cypress/support/directories.ts index 77268a5e04734..b59aa1bf81963 100644 --- a/superset-frontend/cypress-base/cypress/support/directories.ts +++ b/superset-frontend/cypress-base/cypress/support/directories.ts @@ -322,7 +322,9 @@ export const nativeFilters = { footer: '.ant-modal-footer', saveButton: dataTestLocator('native-filter-modal-save-button'), cancelButton: dataTestLocator('native-filter-modal-cancel-button'), - yesCancelButton: '[type="button"]', + confirmCancelButton: dataTestLocator( + 'native-filter-modal-confirm-cancel-button', + ), alertXUnsavedFilters: '.ant-alert-message', tabsList: { filterItemsContainer: dataTestLocator('filter-title-container'), diff --git a/superset-frontend/cypress-base/package-lock.json b/superset-frontend/cypress-base/package-lock.json index 38e80a183cc9a..a648fa64f541d 100644 --- a/superset-frontend/cypress-base/package-lock.json +++ b/superset-frontend/cypress-base/package-lock.json @@ -2849,13 +2849,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -2870,21 +2870,21 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", - "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "peer": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { @@ -2893,12 +2893,12 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@nodelib/fs.scandir": { @@ -3159,9 +3159,9 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, "node_modules/@types/eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "peer": true, "dependencies": { "@types/estree": "*", @@ -3169,9 +3169,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "peer": true, "dependencies": { "@types/eslint": "*", @@ -3179,9 +3179,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "peer": true }, "node_modules/@types/fetch-mock": { @@ -3616,148 +3616,148 @@ } }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.5.tgz", - "integrity": "sha512-LHY/GSAZZRpsNQH+/oHqhRQ5FT7eoULcBqgfyTB5nQHogFnK3/7QoN7dLnwSE/JkUAF0SrRuclT7ODqMFtWxxQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "peer": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.5.tgz", - "integrity": "sha512-1j1zTIC5EZOtCplMBG/IEwLtUojtwFVwdyVMbL/hwWqbzlQoJsWCOavrdnLkemwNoC/EOwtUFch3fuo+cbcXYQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "peer": true }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.5.tgz", - "integrity": "sha512-L65bDPmfpY0+yFrsgz8b6LhXmbbs38OnwDCf6NpnMUYqa+ENfE5Dq9E42ny0qz/PdR0LJyq/T5YijPnU8AXEpA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "peer": true }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.5.tgz", - "integrity": "sha512-fDKo1gstwFFSfacIeH5KfwzjykIE6ldh1iH9Y/8YkAZrhmu4TctqYjSh7t0K2VyDSXOZJ1MLhht/k9IvYGcIxg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", "peer": true }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.5.tgz", - "integrity": "sha512-DhykHXM0ZABqfIGYNv93A5KKDw/+ywBFnuWybZZWcuzWHfbp21wUfRkbtz7dMGwGgT4iXjWuhRMA2Mzod6W4WA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "peer": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.5", - "@webassemblyjs/helper-api-error": "1.11.5", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.5.tgz", - "integrity": "sha512-oC4Qa0bNcqnjAowFn7MPCETQgDYytpsfvz4ujZz63Zu/a/v71HeCAAmZsgZ3YVKec3zSPYytG3/PrRCqbtcAvA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "peer": true }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.5.tgz", - "integrity": "sha512-uEoThA1LN2NA+K3B9wDo3yKlBfVtC6rh0i4/6hvbz071E8gTNZD/pT0MsBf7MeD6KbApMSkaAK0XeKyOZC7CIA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.5.tgz", - "integrity": "sha512-37aGq6qVL8A8oPbPrSGMBcp38YZFXcHfiROflJn9jxSdSMMM5dS5P/9e2/TpaJuhE+wFrbukN2WI6Hw9MH5acg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.5.tgz", - "integrity": "sha512-ajqrRSXaTJoPW+xmkfYN6l8VIeNnR4vBOTQO9HzR7IygoCcKWkICbKFbVTNMjMgMREqXEr0+2M6zukzM47ZUfQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "peer": true, "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.5.tgz", - "integrity": "sha512-WiOhulHKTZU5UPlRl53gHR8OxdGsSOxqfpqWeA2FmcwBMaoEdz6b2x2si3IwC9/fSPLfe8pBMRTHVMk5nlwnFQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "peer": true }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.5.tgz", - "integrity": "sha512-C0p9D2fAu3Twwqvygvf42iGCQ4av8MFBLiTb+08SZ4cEdwzWx9QeAHDo1E2k+9s/0w1DM40oflJOpkZ8jW4HCQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/helper-wasm-section": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5", - "@webassemblyjs/wasm-opt": "1.11.5", - "@webassemblyjs/wasm-parser": "1.11.5", - "@webassemblyjs/wast-printer": "1.11.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.5.tgz", - "integrity": "sha512-14vteRlRjxLK9eSyYFvw1K8Vv+iPdZU0Aebk3j6oB8TQiQYuO6hj9s4d7qf6f2HJr2khzvNldAFG13CgdkAIfA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/ieee754": "1.11.5", - "@webassemblyjs/leb128": "1.11.5", - "@webassemblyjs/utf8": "1.11.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.5.tgz", - "integrity": "sha512-tcKwlIXstBQgbKy1MlbDMlXaxpucn42eb17H29rawYLxm5+MsEmgPzeCP8B1Cl69hCice8LeKgZpRUAPtqYPgw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5", - "@webassemblyjs/wasm-parser": "1.11.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.5.tgz", - "integrity": "sha512-SVXUIwsLQlc8srSD7jejsfTU83g7pIGr2YYNb9oHdtldSxaOhvA5xwvIiWIfcX8PlSakgqMXsLpLfbbJ4cBYew==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-api-error": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/ieee754": "1.11.5", - "@webassemblyjs/leb128": "1.11.5", - "@webassemblyjs/utf8": "1.11.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.5.tgz", - "integrity": "sha512-f7Pq3wvg3GSPUPzR0F6bmI89Hdb+u9WXrSKc4v+N0aV0q6r42WoF92Jp2jEorBEBRoRNXgjp53nBniDXcqZYPA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.11.5", + "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, @@ -4346,9 +4346,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "funding": [ { "type": "opencollective", @@ -4357,13 +4357,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -4470,9 +4474,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001481", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz", - "integrity": "sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==", + "version": "1.0.30001676", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz", + "integrity": "sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==", "funding": [ { "type": "opencollective", @@ -5218,9 +5222,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.371", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.371.tgz", - "integrity": "sha512-jlBzY4tFcJaiUjzhRTCWAqRvTO/fWzjA3Bls0mykzGZ7zvcMP7h05W6UcgzfT9Ca1SW2xyKDOFRyI0pQeRNZGw==" + "version": "1.5.50", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", + "integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -5244,9 +5248,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", - "integrity": "sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "peer": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -5288,9 +5292,9 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -8137,9 +8141,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/normalize-url": { "version": "6.1.0", @@ -8479,9 +8483,9 @@ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -9240,9 +9244,9 @@ "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==" }, "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "peer": true, "dependencies": { "randombytes": "^2.1.0" @@ -9636,13 +9640,13 @@ } }, "node_modules/terser": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz", - "integrity": "sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw==", + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", "peer": true, "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -9654,16 +9658,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "peer": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" + "terser": "^5.26.0" }, "engines": { "node": ">= 10.13.0" @@ -9688,9 +9692,9 @@ } }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "peer": true, "dependencies": { "@types/json-schema": "^7.0.8", @@ -9706,9 +9710,9 @@ } }, "node_modules/terser/node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "peer": true, "bin": { "acorn": "bin/acorn" @@ -10057,9 +10061,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "funding": [ { "type": "opencollective", @@ -10075,8 +10079,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -10189,9 +10193,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", @@ -10251,34 +10255,33 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { - "version": "5.80.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.80.0.tgz", - "integrity": "sha512-OIMiq37XK1rWO8mH9ssfFKZsXg4n6klTEDL7S8/HqbAOBBaiy8ABvXvz0dDCXeEF9gqwxSvVk611zFPjS8hJxA==", - "peer": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", + "version": "5.96.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", + "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.13.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.2", + "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -10307,9 +10310,9 @@ } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "peer": true, "bin": { "acorn": "bin/acorn" @@ -10318,19 +10321,10 @@ "node": ">=0.4.0" } }, - "node_modules/webpack/node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "peer": true, - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "peer": true, "dependencies": { "@types/json-schema": "^7.0.8", @@ -12566,13 +12560,13 @@ "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==" }, "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } }, "@jridgewell/resolve-uri": { @@ -12581,18 +12575,18 @@ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" }, "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" }, "@jridgewell/source-map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", - "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "peer": true, "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "@jridgewell/sourcemap-codec": { @@ -12601,12 +12595,12 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@nodelib/fs.scandir": { @@ -12841,9 +12835,9 @@ } }, "@types/eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "peer": true, "requires": { "@types/estree": "*", @@ -12851,9 +12845,9 @@ } }, "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "peer": true, "requires": { "@types/eslint": "*", @@ -12861,9 +12855,9 @@ } }, "@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "peer": true }, "@types/fetch-mock": { @@ -13255,148 +13249,148 @@ } }, "@webassemblyjs/ast": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.5.tgz", - "integrity": "sha512-LHY/GSAZZRpsNQH+/oHqhRQ5FT7eoULcBqgfyTB5nQHogFnK3/7QoN7dLnwSE/JkUAF0SrRuclT7ODqMFtWxxQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "peer": true, "requires": { - "@webassemblyjs/helper-numbers": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.5.tgz", - "integrity": "sha512-1j1zTIC5EZOtCplMBG/IEwLtUojtwFVwdyVMbL/hwWqbzlQoJsWCOavrdnLkemwNoC/EOwtUFch3fuo+cbcXYQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "peer": true }, "@webassemblyjs/helper-api-error": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.5.tgz", - "integrity": "sha512-L65bDPmfpY0+yFrsgz8b6LhXmbbs38OnwDCf6NpnMUYqa+ENfE5Dq9E42ny0qz/PdR0LJyq/T5YijPnU8AXEpA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "peer": true }, "@webassemblyjs/helper-buffer": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.5.tgz", - "integrity": "sha512-fDKo1gstwFFSfacIeH5KfwzjykIE6ldh1iH9Y/8YkAZrhmu4TctqYjSh7t0K2VyDSXOZJ1MLhht/k9IvYGcIxg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", "peer": true }, "@webassemblyjs/helper-numbers": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.5.tgz", - "integrity": "sha512-DhykHXM0ZABqfIGYNv93A5KKDw/+ywBFnuWybZZWcuzWHfbp21wUfRkbtz7dMGwGgT4iXjWuhRMA2Mzod6W4WA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "peer": true, "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.5", - "@webassemblyjs/helper-api-error": "1.11.5", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.5.tgz", - "integrity": "sha512-oC4Qa0bNcqnjAowFn7MPCETQgDYytpsfvz4ujZz63Zu/a/v71HeCAAmZsgZ3YVKec3zSPYytG3/PrRCqbtcAvA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "peer": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.5.tgz", - "integrity": "sha512-uEoThA1LN2NA+K3B9wDo3yKlBfVtC6rh0i4/6hvbz071E8gTNZD/pT0MsBf7MeD6KbApMSkaAK0XeKyOZC7CIA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "peer": true, "requires": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" } }, "@webassemblyjs/ieee754": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.5.tgz", - "integrity": "sha512-37aGq6qVL8A8oPbPrSGMBcp38YZFXcHfiROflJn9jxSdSMMM5dS5P/9e2/TpaJuhE+wFrbukN2WI6Hw9MH5acg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "peer": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.5.tgz", - "integrity": "sha512-ajqrRSXaTJoPW+xmkfYN6l8VIeNnR4vBOTQO9HzR7IygoCcKWkICbKFbVTNMjMgMREqXEr0+2M6zukzM47ZUfQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "peer": true, "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.5.tgz", - "integrity": "sha512-WiOhulHKTZU5UPlRl53gHR8OxdGsSOxqfpqWeA2FmcwBMaoEdz6b2x2si3IwC9/fSPLfe8pBMRTHVMk5nlwnFQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "peer": true }, "@webassemblyjs/wasm-edit": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.5.tgz", - "integrity": "sha512-C0p9D2fAu3Twwqvygvf42iGCQ4av8MFBLiTb+08SZ4cEdwzWx9QeAHDo1E2k+9s/0w1DM40oflJOpkZ8jW4HCQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "peer": true, "requires": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/helper-wasm-section": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5", - "@webassemblyjs/wasm-opt": "1.11.5", - "@webassemblyjs/wasm-parser": "1.11.5", - "@webassemblyjs/wast-printer": "1.11.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, "@webassemblyjs/wasm-gen": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.5.tgz", - "integrity": "sha512-14vteRlRjxLK9eSyYFvw1K8Vv+iPdZU0Aebk3j6oB8TQiQYuO6hj9s4d7qf6f2HJr2khzvNldAFG13CgdkAIfA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "peer": true, "requires": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/ieee754": "1.11.5", - "@webassemblyjs/leb128": "1.11.5", - "@webassemblyjs/utf8": "1.11.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wasm-opt": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.5.tgz", - "integrity": "sha512-tcKwlIXstBQgbKy1MlbDMlXaxpucn42eb17H29rawYLxm5+MsEmgPzeCP8B1Cl69hCice8LeKgZpRUAPtqYPgw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "peer": true, "requires": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-buffer": "1.11.5", - "@webassemblyjs/wasm-gen": "1.11.5", - "@webassemblyjs/wasm-parser": "1.11.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, "@webassemblyjs/wasm-parser": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.5.tgz", - "integrity": "sha512-SVXUIwsLQlc8srSD7jejsfTU83g7pIGr2YYNb9oHdtldSxaOhvA5xwvIiWIfcX8PlSakgqMXsLpLfbbJ4cBYew==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "peer": true, "requires": { - "@webassemblyjs/ast": "1.11.5", - "@webassemblyjs/helper-api-error": "1.11.5", - "@webassemblyjs/helper-wasm-bytecode": "1.11.5", - "@webassemblyjs/ieee754": "1.11.5", - "@webassemblyjs/leb128": "1.11.5", - "@webassemblyjs/utf8": "1.11.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wast-printer": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.5.tgz", - "integrity": "sha512-f7Pq3wvg3GSPUPzR0F6bmI89Hdb+u9WXrSKc4v+N0aV0q6r42WoF92Jp2jEorBEBRoRNXgjp53nBniDXcqZYPA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "peer": true, "requires": { - "@webassemblyjs/ast": "1.11.5", + "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, @@ -13837,14 +13831,14 @@ } }, "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" } }, "buffer-crc32": { @@ -13918,9 +13912,9 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "caniuse-lite": { - "version": "1.0.30001481", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz", - "integrity": "sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==" + "version": "1.0.30001676", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz", + "integrity": "sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==" }, "caseless": { "version": "0.12.0", @@ -14474,9 +14468,9 @@ } }, "electron-to-chromium": { - "version": "1.4.371", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.371.tgz", - "integrity": "sha512-jlBzY4tFcJaiUjzhRTCWAqRvTO/fWzjA3Bls0mykzGZ7zvcMP7h05W6UcgzfT9Ca1SW2xyKDOFRyI0pQeRNZGw==" + "version": "1.5.50", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", + "integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==" }, "emoji-regex": { "version": "8.0.0", @@ -14500,9 +14494,9 @@ } }, "enhanced-resolve": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", - "integrity": "sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "peer": true, "requires": { "graceful-fs": "^4.2.4", @@ -14538,9 +14532,9 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" }, "escape-string-regexp": { "version": "1.0.5", @@ -16564,9 +16558,9 @@ } }, "node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "normalize-url": { "version": "6.1.0", @@ -16821,9 +16815,9 @@ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "picomatch": { "version": "2.3.1", @@ -17395,9 +17389,9 @@ "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==" }, "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "peer": true, "requires": { "randombytes": "^2.1.0" @@ -17701,21 +17695,21 @@ } }, "terser": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz", - "integrity": "sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw==", + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", "peer": true, "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "dependencies": { "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "peer": true }, "commander": { @@ -17727,22 +17721,22 @@ } }, "terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "peer": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" + "terser": "^5.26.0" }, "dependencies": { "schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "peer": true, "requires": { "@types/json-schema": "^7.0.8", @@ -17999,12 +17993,12 @@ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==" }, "update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" } }, "uri-js": { @@ -18087,9 +18081,9 @@ } }, "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "peer": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -18138,54 +18132,46 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "webpack": { - "version": "5.80.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.80.0.tgz", - "integrity": "sha512-OIMiq37XK1rWO8mH9ssfFKZsXg4n6klTEDL7S8/HqbAOBBaiy8ABvXvz0dDCXeEF9gqwxSvVk611zFPjS8hJxA==", - "peer": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", + "version": "5.96.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", + "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "peer": true, + "requires": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.13.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.2", + "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "dependencies": { "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "peer": true }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "peer": true, - "requires": {} - }, "schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "peer": true, "requires": { "@types/json-schema": "^7.0.8", diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index c19eafc75c2c4..bff23d7339713 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -23,7 +23,7 @@ "@reduxjs/toolkit": "^1.9.3", "@rjsf/core": "^5.21.1", "@rjsf/utils": "^5.19.3", - "@rjsf/validator-ajv8": "^5.19.3", + "@rjsf/validator-ajv8": "^5.22.3", "@scarf/scarf": "^1.3.0", "@superset-ui/chart-controls": "file:./packages/superset-ui-chart-controls", "@superset-ui/core": "file:./packages/superset-ui-core", @@ -59,7 +59,7 @@ "@visx/tooltip": "^3.0.0", "@visx/xychart": "^3.5.1", "abortcontroller-polyfill": "^1.7.5", - "ace-builds": "^1.35.4", + "ace-builds": "^1.36.3", "antd": "4.10.3", "antd-v5": "npm:antd@^5.18.0", "babel-plugin-typescript-to-proptypes": "^2.0.0", @@ -71,6 +71,7 @@ "d3-scale": "^2.1.2", "dayjs": "^1.11.13", "dom-to-image-more": "^3.2.0", + "dom-to-pdf": "^0.3.2", "emotion-rgba": "0.0.12", "fast-glob": "^3.3.2", "fs-extra": "^11.2.0", @@ -86,6 +87,7 @@ "json-bigint": "^1.0.0", "json-stringify-pretty-compact": "^2.0.0", "lodash": "^4.17.21", + "luxon": "^3.5.0", "mapbox-gl": "^2.10.0", "markdown-to-jsx": "^7.4.7", "match-sorter": "^6.3.4", @@ -229,7 +231,7 @@ "eslint": "^8.56.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^7.2.0", - "eslint-import-resolver-typescript": "^3.6.1", + "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-cypress": "^3.5.0", "eslint-plugin-file-progress": "^1.5.0", "eslint-plugin-import": "^2.24.2", @@ -239,11 +241,11 @@ "eslint-plugin-lodash": "^7.4.0", "eslint-plugin-no-only-tests": "^3.3.0", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.22.0", + "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-prefer-function-component": "^3.3.0", "eslint-plugin-storybook": "^0.8.0", - "eslint-plugin-testing-library": "^6.2.2", + "eslint-plugin-testing-library": "^6.4.0", "eslint-plugin-theme-colors": "file:tools/eslint-plugin-theme-colors", "eslint-plugin-translation-vars": "file:tools/eslint-plugin-translation-vars", "exports-loader": "^5.0.0", @@ -269,7 +271,7 @@ "open-cli": "^8.0.0", "po2json": "^0.4.5", "prettier": "3.3.3", - "prettier-plugin-packagejson": "^2.5.2", + "prettier-plugin-packagejson": "^2.5.3", "process": "^0.11.10", "react-resizable": "^3.0.5", "react-test-renderer": "^16.14.0", @@ -7666,6 +7668,15 @@ "node": ">= 8" } }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "engines": { + "node": ">=12.4.0" + } + }, "node_modules/@npmcli/agent": { "version": "2.2.2", "devOptional": true, @@ -9592,9 +9603,9 @@ } }, "node_modules/@rjsf/utils": { - "version": "5.21.1", - "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.21.1.tgz", - "integrity": "sha512-KEwEtIswzKE2WTLRxvh5vwMwvNMTHnRSxwaRlz3QKz5/iQr9XGJTWcmArjIN3y0ypfLk+X6qZsboamQBIhTV3w==", + "version": "5.22.3", + "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.22.3.tgz", + "integrity": "sha512-/aWtYX2ruK3x/bGsePc25UEbSsJvLUAMQO1i306RQ3QQzWn4hbyenBfT4iMxh6Kaly6kmKavBlB7knpooCx4OQ==", "dependencies": { "json-schema-merge-allof": "^0.8.1", "jsonpointer": "^5.0.1", @@ -9615,9 +9626,9 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/@rjsf/validator-ajv8": { - "version": "5.19.4", - "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.19.4.tgz", - "integrity": "sha512-meatFQFif92mlFUcmywbDElWSOUdLg6rIowisNaquktUxTRce2TL9TPd7vgcMdwFI1h9NiFok5q6V8v3XyyLLQ==", + "version": "5.22.3", + "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.22.3.tgz", + "integrity": "sha512-fHu+oPOckpSHMwKdPCP/h8TtcOJ4I45RxFR//cN1c+um6OtpE/0t9JkVWAtbQlNJffIrzacnJjH5NpGwssxjrA==", "dependencies": { "ajv": "^8.12.0", "ajv-formats": "^2.1.1", @@ -9628,7 +9639,7 @@ "node": ">=14" }, "peerDependencies": { - "@rjsf/utils": "^5.19.x" + "@rjsf/utils": "^5.22.x" } }, "node_modules/@rjsf/validator-ajv8/node_modules/ajv": { @@ -13879,6 +13890,13 @@ "version": "6.9.7", "license": "MIT" }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/range-parser": { "version": "1.2.4", "license": "MIT" @@ -16038,8 +16056,9 @@ } }, "node_modules/ace-builds": { - "version": "1.35.4", - "license": "BSD-3-Clause" + "version": "1.36.3", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.36.3.tgz", + "integrity": "sha512-YcdwV2IIaJSfjkWAR1NEYN5IxBiXefTgwXsJ//UlaFrjXDX5hQpvPFvEePHz2ZBUfvO54RjHeRUQGX8MS5HaMQ==" }, "node_modules/acorn": { "version": "8.11.3", @@ -17076,14 +17095,16 @@ "license": "MIT" }, "node_modules/array-includes": { - "version": "3.1.7", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -17152,6 +17173,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.findlastindex": { "version": "1.2.4", "dev": true, @@ -17205,15 +17246,19 @@ } }, "node_modules/array.prototype.tosorted": { - "version": "1.1.3", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/arraybuffer.prototype.slice": { @@ -17334,14 +17379,6 @@ "version": "3.5.1", "license": "MIT" }, - "node_modules/asynciterator.prototype": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - } - }, "node_modules/asynckit": { "version": "0.4.0", "dev": true, @@ -17358,7 +17395,6 @@ }, "node_modules/atob": { "version": "2.1.2", - "dev": true, "license": "(MIT OR Apache-2.0)", "bin": { "atob": "bin/atob.js" @@ -17377,8 +17413,12 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.6", - "license": "MIT", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -18076,6 +18116,16 @@ "version": "1.0.0", "license": "MIT" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "funding": [ @@ -18543,6 +18593,18 @@ "node-int64": "^0.4.0" } }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "license": "(MIT OR Apache-2.0)", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/buf-compare": { "version": "1.0.1", "license": "MIT", @@ -19036,6 +19098,33 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/canvg/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT", + "optional": true + }, "node_modules/capture-exit": { "version": "2.0.0", "dev": true, @@ -20619,6 +20708,16 @@ "isobject": "^3.0.1" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "license": "MIT", + "optional": true, + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-loader": { "version": "6.8.1", "dev": true, @@ -21617,6 +21716,57 @@ "node": ">=18" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/datamaps": { "version": "0.5.9", "license": "MIT", @@ -22609,10 +22759,25 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, + "node_modules/dom-to-image": { + "version": "2.6.0", + "resolved": "git+ssh://git@github.com/dmapper/dom-to-image.git#a7c386a8ea813930f05449ac71ab4be0c262dff3", + "license": "MIT" + }, "node_modules/dom-to-image-more": { "version": "3.2.0", "license": "MIT" }, + "node_modules/dom-to-pdf": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/dom-to-pdf/-/dom-to-pdf-0.3.2.tgz", + "integrity": "sha512-eHLQ/IK+2PQlRjybQ9UHYwpiTd/YZFKqGFyRCjVvi6CPlH58drWQnxf7HBCVRUyAjOtI3RG0kvLidPhC7dOhcQ==", + "license": "MIT", + "dependencies": { + "dom-to-image": "git+https://github.com/dmapper/dom-to-image.git", + "jspdf": "^2.5.1" + } + }, "node_modules/dom-walk": { "version": "0.1.1" }, @@ -22640,6 +22805,13 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.7.tgz", + "integrity": "sha512-2q4bEI+coQM8f5ez7kt2xclg1XsecaV9ASJk/54vwlfRRNQfDqJz2pzQ8t0Ix/ToBpXlVjrRIx7pFC/o8itG2Q==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optional": true + }, "node_modules/domutils": { "version": "3.1.0", "dev": true, @@ -23145,17 +23317,22 @@ } }, "node_modules/es-abstract": { - "version": "1.22.4", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, - "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.6", + "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", "get-intrinsic": "^1.2.4", @@ -23163,15 +23340,16 @@ "globalthis": "^1.0.3", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.1", + "hasown": "^2.0.2", "internal-slot": "^1.0.7", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", @@ -23179,17 +23357,17 @@ "object-keys": "^1.1.1", "object.assign": "^4.1.5", "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", + "safe-array-concat": "^1.1.2", "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.1", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -23253,25 +23431,25 @@ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, "node_modules/es-iterator-helpers": { - "version": "1.0.17", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", + "integrity": "sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==", "dev": true, - "license": "MIT", "dependencies": { - "asynciterator.prototype": "^1.0.0", "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.4", + "es-abstract": "^1.23.3", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", + "globalthis": "^1.0.4", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.0" + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" }, "engines": { "node": ">= 0.4" @@ -23282,14 +23460,27 @@ "devOptional": true, "license": "MIT" }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.2", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, - "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -24019,16 +24210,18 @@ "license": "MIT" }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", + "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", "dev": true, - "license": "ISC", "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.5", + "enhanced-resolve": "^5.15.0", + "eslint-module-utils": "^2.8.1", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", "is-glob": "^4.0.3" }, "engines": { @@ -24039,7 +24232,16 @@ }, "peerDependencies": { "eslint": "*", - "eslint-plugin-import": "*" + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } } }, "node_modules/eslint-import-resolver-typescript/node_modules/debug": { @@ -24084,9 +24286,10 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -24451,32 +24654,35 @@ "license": "0BSD" }, "node_modules/eslint-plugin-react": { - "version": "7.33.2", + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", "dev": true, - "license": "MIT", "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", + "es-iterator-helpers": "^1.1.0", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", + "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "node_modules/eslint-plugin-react-hooks": { @@ -24565,18 +24771,19 @@ } }, "node_modules/eslint-plugin-testing-library": { - "version": "6.2.2", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.4.0.tgz", + "integrity": "sha512-yeWF+YgCgvNyPNI9UKnG0FjeE2sk93N/3lsKqcmR8dSfeXJwFT5irnWo7NjLf152HkRzfoFjh3LsBUrhvFz4eA==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^5.58.0" + "@typescript-eslint/utils": "^5.62.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0", "npm": ">=6" }, "peerDependencies": { - "eslint": "^7.5.0 || ^8.0.0" + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/eslint-plugin-theme-colors": { @@ -25929,6 +26136,12 @@ "version": "6.0.0", "license": "MIT" }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, "node_modules/figures": { "version": "3.2.0", "dev": true, @@ -27088,9 +27301,10 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.2", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", "dev": true, - "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -27569,11 +27783,13 @@ } }, "node_modules/globalthis": { - "version": "1.0.3", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, - "license": "MIT", "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -27892,8 +28108,9 @@ } }, "node_modules/has-proto": { - "version": "1.0.1", - "license": "MIT", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -27995,8 +28212,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "license": "MIT", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -28659,6 +28877,20 @@ "node": ">=6" } }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "license": "MIT", + "optional": true, + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/htmlparser2": { "version": "8.0.2", "dev": true, @@ -28753,9 +28985,10 @@ "license": "MIT" }, "node_modules/http-proxy-middleware": { - "version": "2.0.6", + "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==", "dev": true, - "license": "MIT", "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -29448,8 +29681,9 @@ }, "node_modules/is-async-function": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, - "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -29489,6 +29723,27 @@ "dev": true, "license": "MIT" }, + "node_modules/is-bun-module": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", + "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "dev": true, + "dependencies": { + "semver": "^7.6.3" + } + }, + "node_modules/is-bun-module/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/is-callable": { "version": "1.2.7", "license": "MIT", @@ -29542,6 +29797,21 @@ "node": ">=0.10.0" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "license": "MIT", @@ -29612,8 +29882,9 @@ }, "node_modules/is-finalizationregistry": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -29744,8 +30015,12 @@ } }, "node_modules/is-map": { - "version": "2.0.2", - "license": "MIT", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -29765,9 +30040,10 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -29874,17 +30150,25 @@ } }, "node_modules/is-set": { - "version": "2.0.2", - "license": "MIT", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "license": "MIT", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -29983,8 +30267,12 @@ "license": "MIT" }, "node_modules/is-weakmap": { - "version": "2.0.1", - "license": "MIT", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -30001,11 +30289,15 @@ } }, "node_modules/is-weakset": { - "version": "2.0.2", - "license": "MIT", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -30339,15 +30631,19 @@ } }, "node_modules/iterator.prototype": { - "version": "1.1.2", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", "dev": true, - "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", "reflect.getprototypeof": "^1.0.4", "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/jackspeak": { @@ -33250,6 +33546,24 @@ "node": "*" } }, + "node_modules/jspdf": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz", + "integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.8.1" + }, + "optionalDependencies": { + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.5.4", + "html2canvas": "^1.0.0-rc.5" + } + }, "node_modules/jsprim": { "version": "1.4.2", "dev": true, @@ -34646,10 +34960,10 @@ } }, "node_modules/luxon": { - "version": "3.4.4", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", "license": "MIT", - "optional": true, - "peer": true, "engines": { "node": ">=12" } @@ -42033,26 +42347,29 @@ } }, "node_modules/object.entries": { - "version": "1.1.6", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.7", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -42089,18 +42406,6 @@ "es-errors": "^1.0.0" } }, - "node_modules/object.hasown": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.pick": { "version": "1.3.0", "dev": true, @@ -42113,13 +42418,14 @@ } }, "node_modules/object.values": { - "version": "1.1.7", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -43190,7 +43496,7 @@ }, "node_modules/performance-now": { "version": "2.1.0", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/periscopic": { @@ -43501,6 +43807,14 @@ "node": ">=0.10.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.33", "dev": true, @@ -44048,13 +44362,13 @@ } }, "node_modules/prettier-plugin-packagejson": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.2.tgz", - "integrity": "sha512-w+TmoLv2pIa+siplW1cCj2ujEXQQS6z7wmWLOiLQK/2QVl7Wy6xh/ZUpqQw8tbKMXDodmSW4GONxlA33xpdNOg==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.3.tgz", + "integrity": "sha512-ATMEEXr+ywls1kgrZEWl4SBPEm0uDdyDAjyNzUC0/Z8WZTD3RqbJcQDR+Dau+wYkW9KHK6zqQIsFyfn+9aduWg==", "dev": true, "dependencies": { "sort-package-json": "2.10.1", - "synckit": "0.9.1" + "synckit": "0.9.2" }, "peerDependencies": { "prettier": ">= 1.16.0" @@ -44745,7 +45059,7 @@ }, "node_modules/raf": { "version": "3.4.1", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "performance-now": "^2.1.0" @@ -46803,15 +47117,16 @@ "license": "MIT" }, "node_modules/reflect.getprototypeof": { - "version": "1.0.5", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0", - "get-intrinsic": "^1.2.3", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", "which-builtin-type": "^1.1.3" }, @@ -47248,8 +47563,9 @@ }, "node_modules/remark-gfm": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", "dev": true, - "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", @@ -48351,6 +48667,16 @@ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, "node_modules/rimraf": { "version": "6.0.1", "license": "ISC", @@ -48620,12 +48946,13 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.0", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -48638,8 +48965,9 @@ }, "node_modules/safe-array-concat/node_modules/isarray": { "version": "2.0.5", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "node_modules/safe-buffer": { "version": "5.1.2", @@ -48952,12 +49280,14 @@ } }, "node_modules/set-function-name": { - "version": "2.0.1", - "license": "MIT", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -50007,6 +50337,16 @@ "node": ">=8" } }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, "node_modules/static-eval": { "version": "2.1.0", "license": "MIT", @@ -50286,32 +50626,51 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.10", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "node_modules/string.prototype.trim": { - "version": "1.2.8", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -50321,26 +50680,31 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -50562,6 +50926,16 @@ "dev": true, "license": "MIT" }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/svgo": { "version": "3.2.0", "dev": true, @@ -50645,9 +51019,9 @@ "license": "MIT" }, "node_modules/synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, "dependencies": { "@pkgr/core": "^0.1.0", @@ -50661,9 +51035,9 @@ } }, "node_modules/synckit/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true }, "node_modules/tapable": { @@ -51023,6 +51397,16 @@ "node": ">=0.10" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "license": "MIT", + "optional": true, + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/text-table": { "version": "0.2.0", "license": "MIT" @@ -51746,11 +52130,12 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.1", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "is-typed-array": "^1.1.13" }, @@ -51759,14 +52144,16 @@ } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -51776,15 +52163,17 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, - "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -51794,13 +52183,20 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -52415,6 +52811,16 @@ "node": ">= 0.4.0" } }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "license": "MIT", + "optional": true, + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/uuid": { "version": "3.4.0", "dev": true, @@ -53560,12 +53966,13 @@ } }, "node_modules/which-builtin-type": { - "version": "1.1.3", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "dev": true, - "license": "MIT", "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -53574,8 +53981,8 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -53586,17 +53993,22 @@ }, "node_modules/which-builtin-type/node_modules/isarray": { "version": "2.0.5", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "node_modules/which-collection": { - "version": "1.0.1", - "license": "MIT", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -53943,14 +54355,15 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.14", - "license": "MIT", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -57692,7 +58105,7 @@ "d3-array": "^1.2.4", "d3-color": "^1.4.1", "d3-scale": "^3.0.0", - "deck.gl": "9.0.28", + "deck.gl": "9.0.34", "lodash": "^4.17.21", "moment": "^2.30.1", "mousetrap": "^1.6.5", @@ -58111,7 +58524,9 @@ } }, "plugins/legacy-preset-chart-nvd3/node_modules/dompurify": { - "version": "3.1.0", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", + "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==", "license": "(MPL-2.0 OR Apache-2.0)" }, "plugins/plugin-chart-echarts": { @@ -63384,6 +63799,12 @@ "fastq": "^1.6.0" } }, + "@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true + }, "@npmcli/agent": { "version": "2.2.2", "devOptional": true, @@ -64615,9 +65036,9 @@ } }, "@rjsf/utils": { - "version": "5.21.1", - "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.21.1.tgz", - "integrity": "sha512-KEwEtIswzKE2WTLRxvh5vwMwvNMTHnRSxwaRlz3QKz5/iQr9XGJTWcmArjIN3y0ypfLk+X6qZsboamQBIhTV3w==", + "version": "5.22.3", + "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.22.3.tgz", + "integrity": "sha512-/aWtYX2ruK3x/bGsePc25UEbSsJvLUAMQO1i306RQ3QQzWn4hbyenBfT4iMxh6Kaly6kmKavBlB7knpooCx4OQ==", "requires": { "json-schema-merge-allof": "^0.8.1", "jsonpointer": "^5.0.1", @@ -64634,9 +65055,9 @@ } }, "@rjsf/validator-ajv8": { - "version": "5.19.4", - "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.19.4.tgz", - "integrity": "sha512-meatFQFif92mlFUcmywbDElWSOUdLg6rIowisNaquktUxTRce2TL9TPd7vgcMdwFI1h9NiFok5q6V8v3XyyLLQ==", + "version": "5.22.3", + "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.22.3.tgz", + "integrity": "sha512-fHu+oPOckpSHMwKdPCP/h8TtcOJ4I45RxFR//cN1c+um6OtpE/0t9JkVWAtbQlNJffIrzacnJjH5NpGwssxjrA==", "requires": { "ajv": "^8.12.0", "ajv-formats": "^2.1.1", @@ -68412,7 +68833,7 @@ "d3-array": "^1.2.4", "d3-color": "^1.4.1", "d3-scale": "^3.0.0", - "deck.gl": "9.0.28", + "deck.gl": "9.0.34", "lodash": "^4.17.21", "moment": "^2.30.1", "mousetrap": "^1.6.5", @@ -68698,7 +69119,9 @@ }, "dependencies": { "dompurify": { - "version": "3.1.0" + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", + "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==" } } }, @@ -69830,6 +70253,12 @@ "@types/qs": { "version": "6.9.7" }, + "@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "optional": true + }, "@types/range-parser": { "version": "1.2.4" }, @@ -71406,7 +71835,9 @@ } }, "ace-builds": { - "version": "1.35.4" + "version": "1.36.3", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.36.3.tgz", + "integrity": "sha512-YcdwV2IIaJSfjkWAR1NEYN5IxBiXefTgwXsJ//UlaFrjXDX5hQpvPFvEePHz2ZBUfvO54RjHeRUQGX8MS5HaMQ==" }, "acorn": { "version": "8.11.3" @@ -72084,13 +72515,16 @@ "dev": true }, "array-includes": { - "version": "3.1.7", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" } }, @@ -72129,6 +72563,20 @@ "es-shim-unscopables": "^1.0.0" } }, + "array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + } + }, "array.prototype.findlastindex": { "version": "1.2.4", "dev": true, @@ -72161,13 +72609,15 @@ } }, "array.prototype.tosorted": { - "version": "1.1.3", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, "requires": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, @@ -72253,13 +72703,6 @@ "async-validator": { "version": "3.5.1" }, - "asynciterator.prototype": { - "version": "1.0.0", - "dev": true, - "requires": { - "has-symbols": "^1.0.3" - } - }, "asynckit": { "version": "0.4.0", "dev": true @@ -72270,8 +72713,7 @@ "peer": true }, "atob": { - "version": "2.1.2", - "dev": true + "version": "2.1.2" }, "atomic-sleep": { "version": "1.0.0", @@ -72280,7 +72722,12 @@ "dev": true }, "available-typed-arrays": { - "version": "1.0.6" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "requires": { + "possible-typed-array-names": "^1.0.0" + } }, "avvio": { "version": "8.4.0", @@ -72765,6 +73212,12 @@ "base16": { "version": "1.0.0" }, + "base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "optional": true + }, "base64-js": { "version": "1.5.1" }, @@ -73090,6 +73543,11 @@ "node-int64": "^0.4.0" } }, + "btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==" + }, "buf-compare": { "version": "1.0.1" }, @@ -73395,6 +73853,30 @@ "caniuse-lite": { "version": "1.0.30001639" }, + "canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "optional": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.38.1", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "optional": true + } + } + }, "capture-exit": { "version": "2.0.0", "dev": true, @@ -74470,6 +74952,15 @@ "isobject": "^3.0.1" } }, + "css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "optional": true, + "requires": { + "utrie": "^1.0.2" + } + }, "css-loader": { "version": "6.8.1", "dev": true, @@ -75157,6 +75648,39 @@ } } }, + "data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, "datamaps": { "version": "0.5.9", "requires": { @@ -75799,9 +76323,22 @@ "entities": "^4.2.0" } }, + "dom-to-image": { + "version": "git+ssh://git@github.com/dmapper/dom-to-image.git#a7c386a8ea813930f05449ac71ab4be0c262dff3", + "from": "dom-to-image@git+https://github.com/dmapper/dom-to-image.git" + }, "dom-to-image-more": { "version": "3.2.0" }, + "dom-to-pdf": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/dom-to-pdf/-/dom-to-pdf-0.3.2.tgz", + "integrity": "sha512-eHLQ/IK+2PQlRjybQ9UHYwpiTd/YZFKqGFyRCjVvi6CPlH58drWQnxf7HBCVRUyAjOtI3RG0kvLidPhC7dOhcQ==", + "requires": { + "dom-to-image": "git+https://github.com/dmapper/dom-to-image.git", + "jspdf": "^2.5.1" + } + }, "dom-walk": { "version": "0.1.1" }, @@ -75815,6 +76352,12 @@ "domelementtype": "^2.3.0" } }, + "dompurify": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.7.tgz", + "integrity": "sha512-2q4bEI+coQM8f5ez7kt2xclg1XsecaV9ASJk/54vwlfRRNQfDqJz2pzQ8t0Ix/ToBpXlVjrRIx7pFC/o8itG2Q==", + "optional": true + }, "domutils": { "version": "3.1.0", "dev": true, @@ -76183,16 +76726,22 @@ } }, "es-abstract": { - "version": "1.22.4", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, "requires": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.6", + "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", "get-intrinsic": "^1.2.4", @@ -76200,15 +76749,16 @@ "globalthis": "^1.0.3", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.1", + "hasown": "^2.0.2", "internal-slot": "^1.0.7", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", @@ -76216,17 +76766,17 @@ "object-keys": "^1.1.1", "object.assign": "^4.1.5", "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", + "safe-array-concat": "^1.1.2", "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.1", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.15" }, "dependencies": { "object-inspect": { @@ -76272,37 +76822,49 @@ } }, "es-iterator-helpers": { - "version": "1.0.17", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", + "integrity": "sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==", "dev": true, "requires": { - "asynciterator.prototype": "^1.0.0", "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.4", + "es-abstract": "^1.23.3", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", + "globalthis": "^1.0.4", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.0" + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" } }, "es-module-lexer": { "version": "1.5.4", "devOptional": true }, + "es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "requires": { + "es-errors": "^1.3.0" + } + }, "es-set-tostringtag": { - "version": "2.0.2", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "requires": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" } }, "es-shim-unscopables": { @@ -76861,15 +77423,18 @@ } }, "eslint-import-resolver-typescript": { - "version": "3.6.1", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", + "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", "dev": true, "requires": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.5", + "enhanced-resolve": "^5.15.0", + "eslint-module-utils": "^2.8.1", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", "is-glob": "^4.0.3" }, "dependencies": { @@ -76899,7 +77464,9 @@ } }, "eslint-module-utils": { - "version": "2.8.0", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dev": true, "requires": { "debug": "^3.2.7" @@ -77150,25 +77717,29 @@ } }, "eslint-plugin-react": { - "version": "7.33.2", + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", "dev": true, "requires": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", + "es-iterator-helpers": "^1.1.0", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", + "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "dependencies": { "doctrine": { @@ -77228,10 +77799,12 @@ } }, "eslint-plugin-testing-library": { - "version": "6.2.2", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.4.0.tgz", + "integrity": "sha512-yeWF+YgCgvNyPNI9UKnG0FjeE2sk93N/3lsKqcmR8dSfeXJwFT5irnWo7NjLf152HkRzfoFjh3LsBUrhvFz4eA==", "dev": true, "requires": { - "@typescript-eslint/utils": "^5.58.0" + "@typescript-eslint/utils": "^5.62.0" } }, "eslint-plugin-theme-colors": { @@ -77981,6 +78554,11 @@ "fetch-retry": { "version": "6.0.0" }, + "fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==" + }, "figures": { "version": "3.2.0", "dev": true, @@ -78722,7 +79300,9 @@ } }, "get-tsconfig": { - "version": "4.7.2", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", "dev": true, "requires": { "resolve-pkg-maps": "^1.0.0" @@ -79047,10 +79627,13 @@ "version": "11.12.0" }, "globalthis": { - "version": "1.0.3", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "requires": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" } }, "globby": { @@ -79250,7 +79833,9 @@ } }, "has-proto": { - "version": "1.0.1" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" }, "has-symbols": { "version": "1.0.3" @@ -79310,7 +79895,9 @@ } }, "hasown": { - "version": "2.0.1", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "requires": { "function-bind": "^1.1.2" } @@ -79739,6 +80326,16 @@ } } }, + "html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "optional": true, + "requires": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + } + }, "htmlparser2": { "version": "8.0.2", "dev": true, @@ -79802,7 +80399,9 @@ } }, "http-proxy-middleware": { - "version": "2.0.6", + "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==", "dev": true, "requires": { "@types/http-proxy": "^1.17.8", @@ -80235,6 +80834,8 @@ }, "is-async-function": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, "requires": { "has-tostringtag": "^1.0.0" @@ -80257,6 +80858,23 @@ "version": "1.1.6", "dev": true }, + "is-bun-module": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", + "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "dev": true, + "requires": { + "semver": "^7.6.3" + }, + "dependencies": { + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + } + } + }, "is-callable": { "version": "1.2.7" }, @@ -80289,6 +80907,15 @@ } } }, + "is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "requires": { + "is-typed-array": "^1.1.13" + } + }, "is-date-object": { "version": "1.0.5", "requires": { @@ -80327,6 +80954,8 @@ }, "is-finalizationregistry": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "dev": true, "requires": { "call-bind": "^1.0.2" @@ -80401,7 +81030,9 @@ "dev": true }, "is-map": { - "version": "2.0.2" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==" }, "is-nan": { "version": "1.3.2", @@ -80411,7 +81042,9 @@ } }, "is-negative-zero": { - "version": "2.0.2", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true }, "is-number": { @@ -80476,12 +81109,16 @@ } }, "is-set": { - "version": "2.0.2" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==" }, "is-shared-array-buffer": { - "version": "1.0.2", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "requires": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" } }, "is-ssh": { @@ -80539,7 +81176,9 @@ "version": "0.2.1" }, "is-weakmap": { - "version": "2.0.1" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==" }, "is-weakref": { "version": "1.0.2", @@ -80549,10 +81188,12 @@ } }, "is-weakset": { - "version": "2.0.2", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" } }, "is-what": { @@ -80772,7 +81413,9 @@ } }, "iterator.prototype": { - "version": "1.1.2", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", "dev": true, "requires": { "define-properties": "^1.2.1", @@ -82716,6 +83359,21 @@ "through": ">=2.2.7 <3" } }, + "jspdf": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz", + "integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==", + "requires": { + "@babel/runtime": "^7.23.2", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "canvg": "^3.0.6", + "core-js": "^3.38.1", + "dompurify": "^2.5.4", + "fflate": "^0.8.1", + "html2canvas": "^1.0.0-rc.5" + } + }, "jsprim": { "version": "1.4.2", "dev": true, @@ -83652,9 +84310,9 @@ } }, "luxon": { - "version": "3.4.4", - "optional": true, - "peer": true + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==" }, "lz-string": { "version": "1.5.0" @@ -87845,21 +88503,26 @@ } }, "object.entries": { - "version": "1.1.6", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "object.fromentries": { - "version": "2.0.7", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" } }, "object.getownpropertydescriptors": { @@ -87882,14 +88545,6 @@ "es-errors": "^1.0.0" } }, - "object.hasown": { - "version": "1.1.3", - "dev": true, - "requires": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, "object.pick": { "version": "1.3.0", "dev": true, @@ -87898,12 +88553,14 @@ } }, "object.values": { - "version": "1.1.7", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "objectorarray": { @@ -88595,7 +89252,7 @@ }, "performance-now": { "version": "2.1.0", - "dev": true + "devOptional": true }, "periscopic": { "version": "3.1.0", @@ -88801,6 +89458,11 @@ "version": "0.1.1", "dev": true }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==" + }, "postcss": { "version": "8.4.33", "dev": true, @@ -89075,13 +89737,13 @@ } }, "prettier-plugin-packagejson": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.2.tgz", - "integrity": "sha512-w+TmoLv2pIa+siplW1cCj2ujEXQQS6z7wmWLOiLQK/2QVl7Wy6xh/ZUpqQw8tbKMXDodmSW4GONxlA33xpdNOg==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.3.tgz", + "integrity": "sha512-ATMEEXr+ywls1kgrZEWl4SBPEm0uDdyDAjyNzUC0/Z8WZTD3RqbJcQDR+Dau+wYkW9KHK6zqQIsFyfn+9aduWg==", "dev": true, "requires": { "sort-package-json": "2.10.1", - "synckit": "0.9.1" + "synckit": "0.9.2" } }, "pretty-bytes": { @@ -89543,7 +90205,7 @@ }, "raf": { "version": "3.4.1", - "dev": true, + "devOptional": true, "requires": { "performance-now": "^2.1.0" } @@ -90889,14 +91551,16 @@ "version": "1.0.0-beta9-9-7" }, "reflect.getprototypeof": { - "version": "1.0.5", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "dev": true, "requires": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0", - "get-intrinsic": "^1.2.3", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", "which-builtin-type": "^1.1.3" } @@ -91193,6 +91857,8 @@ }, "remark-gfm": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", "dev": true, "requires": { "@types/mdast": "^4.0.0", @@ -91828,6 +92494,12 @@ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, + "rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "optional": true + }, "rimraf": { "version": "6.0.1", "requires": { @@ -91970,17 +92642,21 @@ } }, "safe-array-concat": { - "version": "1.1.0", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, "requires": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, "dependencies": { "isarray": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true } } @@ -92227,11 +92903,14 @@ } }, "set-function-name": { - "version": "2.0.1", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "requires": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" } }, "set-value": { @@ -92961,6 +93640,12 @@ } } }, + "stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "optional": true + }, "static-eval": { "version": "2.1.0", "requires": { @@ -93143,45 +93828,67 @@ } }, "string.prototype.matchall": { - "version": "4.0.10", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + } + }, + "string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" } }, "string.prototype.trim": { - "version": "1.2.8", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" } }, "string.prototype.trimend": { - "version": "1.0.7", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "string.prototype.trimstart": { - "version": "1.0.7", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "stringify-entities": { @@ -93305,6 +94012,12 @@ "version": "2.0.4", "dev": true }, + "svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "optional": true + }, "svgo": { "version": "3.2.0", "dev": true, @@ -93355,9 +94068,9 @@ "dev": true }, "synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, "requires": { "@pkgr/core": "^0.1.0", @@ -93365,9 +94078,9 @@ }, "dependencies": { "tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true } } @@ -93607,6 +94320,15 @@ "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true }, + "text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "optional": true, + "requires": { + "utrie": "^1.0.2" + } + }, "text-table": { "version": "0.2.0" }, @@ -94080,42 +94802,55 @@ } }, "typed-array-buffer": { - "version": "1.0.1", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, "requires": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "is-typed-array": "^1.1.13" } }, "typed-array-byte-length": { - "version": "1.0.0", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" } }, "typed-array-byte-offset": { - "version": "1.0.0", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" } }, "typed-array-length": { - "version": "1.0.4", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" } }, "typedarray": { @@ -94480,6 +95215,15 @@ "version": "1.0.1", "dev": true }, + "utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "optional": true, + "requires": { + "base64-arraybuffer": "^1.0.2" + } + }, "uuid": { "version": "3.4.0", "dev": true @@ -95236,11 +95980,13 @@ } }, "which-builtin-type": { - "version": "1.1.3", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "dev": true, "requires": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -95249,23 +95995,27 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" }, "dependencies": { "isarray": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true } } }, "which-collection": { - "version": "1.0.1", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" } }, "which-module": { @@ -95467,13 +96217,15 @@ } }, "which-typed-array": { - "version": "1.1.14", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "requires": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" } }, "wide-align": { diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 736c294de0ea6..434f95032512a 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -65,7 +65,7 @@ "prettier": "npm run _prettier -- --write", "prettier-check": "npm run _prettier -- --check", "prod": "npm run build", - "prune": "rm -rf ./{packages,plugins}/*/{lib,esm,tsconfig.tsbuildinfo,package-lock.json}", + "prune": "rm -rf ./{packages,plugins}/*/{node_modules,lib,esm,tsconfig.tsbuildinfo,package-lock.json} ./.temp_cache", "storybook": "cross-env NODE_ENV=development BABEL_ENV=development storybook dev -p 6006", "tdd": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=4096\" jest --watch", "test": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=4096\" jest --max-workers=50%", @@ -89,7 +89,7 @@ "@reduxjs/toolkit": "^1.9.3", "@rjsf/core": "^5.21.1", "@rjsf/utils": "^5.19.3", - "@rjsf/validator-ajv8": "^5.19.3", + "@rjsf/validator-ajv8": "^5.22.3", "@scarf/scarf": "^1.3.0", "@superset-ui/chart-controls": "file:./packages/superset-ui-chart-controls", "@superset-ui/core": "file:./packages/superset-ui-core", @@ -125,7 +125,7 @@ "@visx/tooltip": "^3.0.0", "@visx/xychart": "^3.5.1", "abortcontroller-polyfill": "^1.7.5", - "ace-builds": "^1.35.4", + "ace-builds": "^1.36.3", "antd": "4.10.3", "antd-v5": "npm:antd@^5.18.0", "babel-plugin-typescript-to-proptypes": "^2.0.0", @@ -137,6 +137,7 @@ "d3-scale": "^2.1.2", "dayjs": "^1.11.13", "dom-to-image-more": "^3.2.0", + "dom-to-pdf": "^0.3.2", "emotion-rgba": "0.0.12", "fast-glob": "^3.3.2", "fs-extra": "^11.2.0", @@ -152,6 +153,7 @@ "json-bigint": "^1.0.0", "json-stringify-pretty-compact": "^2.0.0", "lodash": "^4.17.21", + "luxon": "^3.5.0", "mapbox-gl": "^2.10.0", "markdown-to-jsx": "^7.4.7", "match-sorter": "^6.3.4", @@ -295,7 +297,7 @@ "eslint": "^8.56.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^7.2.0", - "eslint-import-resolver-typescript": "^3.6.1", + "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-cypress": "^3.5.0", "eslint-plugin-file-progress": "^1.5.0", "eslint-plugin-import": "^2.24.2", @@ -305,11 +307,11 @@ "eslint-plugin-lodash": "^7.4.0", "eslint-plugin-no-only-tests": "^3.3.0", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.22.0", + "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-prefer-function-component": "^3.3.0", "eslint-plugin-storybook": "^0.8.0", - "eslint-plugin-testing-library": "^6.2.2", + "eslint-plugin-testing-library": "^6.4.0", "eslint-plugin-theme-colors": "file:tools/eslint-plugin-theme-colors", "eslint-plugin-translation-vars": "file:tools/eslint-plugin-translation-vars", "exports-loader": "^5.0.0", @@ -335,7 +337,7 @@ "open-cli": "^8.0.0", "po2json": "^0.4.5", "prettier": "3.3.3", - "prettier-plugin-packagejson": "^2.5.2", + "prettier-plugin-packagejson": "^2.5.3", "process": "^0.11.10", "react-resizable": "^3.0.5", "react-test-renderer": "^16.14.0", diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/labelUtils.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/labelUtils.tsx index 66b25416f8b52..03af5c13e8695 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/labelUtils.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/labelUtils.tsx @@ -55,8 +55,7 @@ const TooltipSection = ({ text: ReactNode; }) => ( - {label} - {text} + {label}: {text} ); @@ -71,12 +70,7 @@ export const getColumnTypeTooltipNode = (column: ColumnMeta): ReactNode => { return null; } - return ( - - ); + return ; }; export const getColumnTooltipNode = ( diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/constants.ts b/superset-frontend/packages/superset-ui-chart-controls/src/constants.ts index d31843690b763..6534258c66f56 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/constants.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/constants.ts @@ -80,3 +80,6 @@ export const DEFAULT_XAXIS_SORT_SERIES_DATA: SortSeriesData = { }; export const DEFAULT_DATE_PATTERN = /\d{4}-\d{2}-\d{2}/g; + +// When moment fails to parse a date +export const INVALID_DATE = 'Invalid date'; diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/sections/timeComparison.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/sections/timeComparison.tsx index 17239de87ff76..901c34abc8508 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/sections/timeComparison.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/sections/timeComparison.tsx @@ -18,7 +18,12 @@ */ import { t, ComparisonType } from '@superset-ui/core'; -import { ControlPanelSectionConfig } from '../types'; +import { + ControlPanelSectionConfig, + ControlPanelState, + ControlState, +} from '../types'; +import { INVALID_DATE } from '..'; const fullChoices = [ ['1 day ago', t('1 day ago')], @@ -94,9 +99,28 @@ export const timeComparisonControls: ({ name: 'start_date_offset', config: { type: 'TimeOffsetControl', - label: t('shift start date'), + label: t('Shift start date'), visibility: ({ controls }) => controls?.time_compare.value === 'custom', + mapStateToProps: ( + state: ControlPanelState, + controlState: ControlState, + ) => { + const { form_data } = state; + const { time_compare } = form_data; + const newState = { ...controlState }; + if ( + time_compare === 'custom' && + (controlState.value === '' || controlState.value === INVALID_DATE) + ) { + newState.externalValidationErrors = [ + t('A date is required when using custom date shift'), + ]; + } else { + newState.externalValidationErrors = []; + } + return newState; + }, }, }, ], diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/utils/D3Formatting.ts b/superset-frontend/packages/superset-ui-chart-controls/src/utils/D3Formatting.ts index 5541c4a4b4574..d7fb542c6b6d8 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/utils/D3Formatting.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/utils/D3Formatting.ts @@ -57,6 +57,7 @@ export const D3_FORMAT_OPTIONS: [string, string][] = [ ...d3Formatted, ['DURATION', t('Duration in ms (66000 => 1m 6s)')], ['DURATION_SUB', t('Duration in ms (1.40008 => 1ms 400µs 80ns)')], + ['DURATION_COL', t('Duration in ms (10500 => 0:10.5)')], ['MEMORY_DECIMAL', t('Memory in bytes - decimal (1024B => 1.024kB)')], ['MEMORY_BINARY', t('Memory in bytes - binary (1024B => 1KiB)')], ]; diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/components/labelUtils.test.tsx b/superset-frontend/packages/superset-ui-chart-controls/test/components/labelUtils.test.tsx index d32081b8988b8..9b5b760f79151 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/test/components/labelUtils.test.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/test/components/labelUtils.test.tsx @@ -90,7 +90,7 @@ test('should get column datatype rendered as tooltip when column has a type', () , ); - expect(screen.getByText('Column datatype')).toBeVisible(); + expect(screen.getByText('Column type')).toBeVisible(); expect(screen.getByText('text')).toBeVisible(); }); diff --git a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartMetadata.ts b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartMetadata.ts index dcb1de62a5c62..9a9716a22be01 100644 --- a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartMetadata.ts +++ b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartMetadata.ts @@ -50,6 +50,9 @@ export interface ChartMetadataConfig { labelExplanation?: string | null; queryObjectCount?: number; parseMethod?: ParseMethod; + // suppressContextMenu: true hides the default context menu for the chart. + // This is useful for viz plugins that define their own context menu. + suppressContextMenu?: boolean; } export default class ChartMetadata { @@ -91,6 +94,8 @@ export default class ChartMetadata { parseMethod: ParseMethod; + suppressContextMenu?: boolean; + constructor(config: ChartMetadataConfig) { const { name, @@ -111,6 +116,7 @@ export default class ChartMetadata { labelExplanation = null, queryObjectCount = 1, parseMethod = 'json-bigint', + suppressContextMenu = false, } = config; this.name = name; @@ -140,6 +146,7 @@ export default class ChartMetadata { this.labelExplanation = labelExplanation; this.queryObjectCount = queryObjectCount; this.parseMethod = parseMethod; + this.suppressContextMenu = suppressContextMenu; } canBeAnnotationType(type: string): boolean { diff --git a/superset-frontend/packages/superset-ui-core/src/hooks/useChangeEffect/useChangeEffect.test.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useChangeEffect/useChangeEffect.test.ts index 32c984e48769b..1c1a96125b92e 100644 --- a/superset-frontend/packages/superset-ui-core/src/hooks/useChangeEffect/useChangeEffect.test.ts +++ b/superset-frontend/packages/superset-ui-core/src/hooks/useChangeEffect/useChangeEffect.test.ts @@ -24,8 +24,8 @@ test('call callback the first time with undefined and value', () => { renderHook(props => useChangeEffect(props.value, props.callback), { initialProps: { value: 'value', callback }, }); - expect(callback).toBeCalledTimes(1); - expect(callback).nthCalledWith(1, undefined, 'value'); + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenNthCalledWith(1, undefined, 'value'); }); test('do not call callback 2 times if the value do not change', () => { @@ -37,7 +37,7 @@ test('do not call callback 2 times if the value do not change', () => { }, ); hook.rerender({ value: 'value', callback }); - expect(callback).toBeCalledTimes(1); + expect(callback).toHaveBeenCalledTimes(1); }); test('call callback whenever the value changes', () => { @@ -49,6 +49,6 @@ test('call callback whenever the value changes', () => { }, ); hook.rerender({ value: 'value-2', callback }); - expect(callback).toBeCalledTimes(2); - expect(callback).nthCalledWith(2, 'value', 'value-2'); + expect(callback).toHaveBeenCalledTimes(2); + expect(callback).toHaveBeenNthCalledWith(2, 'value', 'value-2'); }); diff --git a/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidMount/useComponentDidMount.test.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidMount/useComponentDidMount.test.ts index 6d7d6cd71282a..7edf9e723296b 100644 --- a/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidMount/useComponentDidMount.test.ts +++ b/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidMount/useComponentDidMount.test.ts @@ -22,7 +22,7 @@ import { useComponentDidMount } from './useComponentDidMount'; test('the effect should only be executed on the first render', () => { const effect = jest.fn(); const hook = renderHook(() => useComponentDidMount(effect)); - expect(effect).toBeCalledTimes(1); + expect(effect).toHaveBeenCalledTimes(1); hook.rerender(); - expect(effect).toBeCalledTimes(1); + expect(effect).toHaveBeenCalledTimes(1); }); diff --git a/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidUpdate/useComponentDidUpdate.test.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidUpdate/useComponentDidUpdate.test.ts index a1615ec2793c0..1c191b07beae0 100644 --- a/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidUpdate/useComponentDidUpdate.test.ts +++ b/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidUpdate/useComponentDidUpdate.test.ts @@ -24,8 +24,8 @@ test('the effect should not be executed on the first render', () => { const hook = renderHook(props => useComponentDidUpdate(props.effect), { initialProps: { effect }, }); - expect(effect).toBeCalledTimes(0); + expect(effect).toHaveBeenCalledTimes(0); const changedEffect = jest.fn(); hook.rerender({ effect: changedEffect }); - expect(changedEffect).toBeCalledTimes(1); + expect(changedEffect).toHaveBeenCalledTimes(1); }); diff --git a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts index 8801706c55ff6..be28944a9178d 100644 --- a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts +++ b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts @@ -60,6 +60,8 @@ export enum FeatureFlag { UseAnalagousColors = 'USE_ANALAGOUS_COLORS', ForceSqlLabRunAsync = 'SQLLAB_FORCE_RUN_ASYNC', SlackEnableAvatars = 'SLACK_ENABLE_AVATARS', + EnableDashboardScreenshotEndpoints = 'ENABLE_DASHBOARD_SCREENSHOT_ENDPOINTS', + EnableDashboardDownloadWebDriverScreenshot = 'ENABLE_DASHBOARD_DOWNLOAD_WEBDRIVER_SCREENSHOT', } export type ScheduleQueriesProps = { diff --git a/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts b/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts index b93a416e7ffaa..17efe6692f3b5 100644 --- a/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts @@ -192,7 +192,7 @@ describe('LabelsColorMap', () => { labelsColorMap.updateColorMap(categoricalNamespace, 'testColors'); const colorMap = labelsColorMap.getColorMap(); expect(Object.fromEntries(colorMap)).not.toEqual({}); - expect(getAnalogousColorsSpy).not.toBeCalled(); + expect(getAnalogousColorsSpy).not.toHaveBeenCalled(); }); it('should use analagous colors', () => { @@ -207,7 +207,7 @@ describe('LabelsColorMap', () => { labelsColorMap.updateColorMap(categoricalNamespace, 'testColors'); const colorMap = labelsColorMap.getColorMap(); expect(Object.fromEntries(colorMap)).not.toEqual({}); - expect(getAnalogousColorsSpy).toBeCalled(); + expect(getAnalogousColorsSpy).toHaveBeenCalled(); }); }); diff --git a/superset-frontend/packages/superset-ui-core/test/models/Registry.test.ts b/superset-frontend/packages/superset-ui-core/test/models/Registry.test.ts index 6f2067eec3129..7b3f2d1f89ebd 100644 --- a/superset-frontend/packages/superset-ui-core/test/models/Registry.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/models/Registry.test.ts @@ -396,31 +396,31 @@ describe('Registry', () => { it('calls the listener when a value is registered', () => { registry.registerValue('foo', 'bar'); - expect(listener).toBeCalledWith(['foo']); + expect(listener).toHaveBeenCalledWith(['foo']); }); it('calls the listener when a loader is registered', () => { registry.registerLoader('foo', () => 'bar'); - expect(listener).toBeCalledWith(['foo']); + expect(listener).toHaveBeenCalledWith(['foo']); }); it('calls the listener when a value is overridden', () => { registry.registerValue('foo', 'bar'); listener.mockClear(); registry.registerValue('foo', 'baz'); - expect(listener).toBeCalledWith(['foo']); + expect(listener).toHaveBeenCalledWith(['foo']); }); it('calls the listener when a value is removed', () => { registry.registerValue('foo', 'bar'); listener.mockClear(); registry.remove('foo'); - expect(listener).toBeCalledWith(['foo']); + expect(listener).toHaveBeenCalledWith(['foo']); }); it('does not call the listener when a value is not actually removed', () => { registry.remove('foo'); - expect(listener).not.toBeCalled(); + expect(listener).not.toHaveBeenCalled(); }); it('calls the listener when registry is cleared', () => { @@ -428,13 +428,13 @@ describe('Registry', () => { registry.registerLoader('fluz', () => 'baz'); listener.mockClear(); registry.clear(); - expect(listener).toBeCalledWith(['foo', 'fluz']); + expect(listener).toHaveBeenCalledWith(['foo', 'fluz']); }); it('removes listeners correctly', () => { registry.removeListener(listener); registry.registerValue('foo', 'bar'); - expect(listener).not.toBeCalled(); + expect(listener).not.toHaveBeenCalled(); }); describe('with a broken listener', () => { @@ -456,10 +456,10 @@ describe('Registry', () => { registry.addListener(lastListener); registry.registerValue('foo', 'bar'); - expect(listener).toBeCalledWith(['foo']); - expect(errorListener).toBeCalledWith(['foo']); - expect(lastListener).toBeCalledWith(['foo']); - expect(console.error).toBeCalled(); + expect(listener).toHaveBeenCalledWith(['foo']); + expect(errorListener).toHaveBeenCalledWith(['foo']); + expect(lastListener).toHaveBeenCalledWith(['foo']); + expect(console.error).toHaveBeenCalled(); }); }); }); diff --git a/superset-frontend/packages/superset-ui-core/test/query/buildQueryContext.test.ts b/superset-frontend/packages/superset-ui-core/test/query/buildQueryContext.test.ts index 4fe70f9188158..4918da15866c0 100644 --- a/superset-frontend/packages/superset-ui-core/test/query/buildQueryContext.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/query/buildQueryContext.test.ts @@ -138,7 +138,7 @@ describe('buildQueryContext', () => { }, () => [{}], ); - expect(spyNormalizeTimeColumn).toBeCalled(); + expect(spyNormalizeTimeColumn).toHaveBeenCalled(); spyNormalizeTimeColumn.mockRestore(); }); }); diff --git a/superset-frontend/packages/superset-ui-core/test/translation/TranslatorSingleton.test.ts b/superset-frontend/packages/superset-ui-core/test/translation/TranslatorSingleton.test.ts index af0d6f5915524..2aa78faeed267 100644 --- a/superset-frontend/packages/superset-ui-core/test/translation/TranslatorSingleton.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/translation/TranslatorSingleton.test.ts @@ -80,7 +80,7 @@ describe('TranslatorSingleton', () => { expect(t('second')).toEqual('second'); resetTranslation(); expect(t('second')).toEqual('second'); - expect(console.warn).toBeCalledTimes(2); + expect(console.warn).toHaveBeenCalledTimes(2); restoreConsole(); }); }); diff --git a/superset-frontend/packages/superset-ui-switchboard/src/switchboard.test.ts b/superset-frontend/packages/superset-ui-switchboard/src/switchboard.test.ts index 9e36f541e1cd9..915fe0cc4234f 100644 --- a/superset-frontend/packages/superset-ui-switchboard/src/switchboard.test.ts +++ b/superset-frontend/packages/superset-ui-switchboard/src/switchboard.test.ts @@ -294,7 +294,7 @@ describe('comms', () => { }); port2.start(); - await expect(ours.get('someMethod')).rejects.toThrowError( + await expect(ours.get('someMethod')).rejects.toThrow( 'Unexpected response message', ); }); diff --git a/superset-frontend/plugins/legacy-plugin-chart-country-map/scripts/Country Map GeoJSON Generator.ipynb b/superset-frontend/plugins/legacy-plugin-chart-country-map/scripts/Country Map GeoJSON Generator.ipynb index b3ad9631b3d1f..2969a7f96e43e 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-country-map/scripts/Country Map GeoJSON Generator.ipynb +++ b/superset-frontend/plugins/legacy-plugin-chart-country-map/scripts/Country Map GeoJSON Generator.ipynb @@ -2648,6 +2648,9 @@ "replace_name(vietnam_copy, 'Hau Giang', 'Hậu Giang')\n", "replace_name(vietnam_copy, 'Ha Noi', 'Hà Nội')\n", "replace_name(vietnam_copy, 'Can Tho', 'Cần Thơ')\n", + "replace_name(vietnam_copy, 'Đông Nam Bộ', 'Đồng Nai')\n", + "replace_name(vietnam_copy, 'Đông Bắc', 'Bắc Kạn')\n", + "replace_name(vietnam_copy, 'Đồng Bằng Sông Hồng', 'Hưng Yên')\n", "for i in vietnam_copy['name']:\n", " print(i)" ] diff --git a/superset-frontend/plugins/legacy-plugin-chart-country-map/src/countries/vietnam.geojson b/superset-frontend/plugins/legacy-plugin-chart-country-map/src/countries/vietnam.geojson index 748ec3a64af7f..9ed539bc7b9f1 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-country-map/src/countries/vietnam.geojson +++ b/superset-frontend/plugins/legacy-plugin-chart-country-map/src/countries/vietnam.geojson @@ -39,7 +39,7 @@ { "type": "Feature", "properties": { "ISO": "VN-49", "NAME_1": "Vĩnh Long" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 105.996567502348185, 9.888559491461711 ], [ 105.93287194100003, 9.95538971600007 ], [ 105.838510089810569, 10.004751968856691 ], [ 105.692236363417408, 10.123180853713393 ], [ 105.707894321965341, 10.174547226873017 ], [ 105.727531365979701, 10.185631822550533 ], [ 105.818998651266725, 10.143127956989588 ], [ 105.867884555727642, 10.140725001757403 ], [ 105.900957472908999, 10.160103665152008 ], [ 105.914600050751687, 10.213950507010281 ], [ 105.882922397550544, 10.238936062049618 ], [ 105.849022658069146, 10.301438706830822 ], [ 105.984569940050676, 10.284178778727664 ], [ 106.100738560436184, 10.249090480841005 ], [ 106.15788821700005, 10.195379950000074 ], [ 106.182139519000032, 10.133042710000041 ], [ 106.246429884000065, 10.077460028000075 ], [ 106.134018182293232, 9.993679713847712 ], [ 106.132571242368897, 9.945827338161109 ], [ 105.996567502348185, 9.888559491461711 ] ] ] } }, { "type": "Feature", "properties": { "ISO": "VN-51", "NAME_1": "Trà Vinh" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 106.246429884000065, 10.077460028000075 ], [ 106.500987175000034, 9.834051825000074 ], [ 106.537852410000028, 9.751166083000044 ], [ 106.574961785000028, 9.739081122000073 ], [ 106.563161655000044, 9.614325262000079 ], [ 106.497243686000047, 9.549994208000044 ], [ 106.398203972000033, 9.542059637000079 ], [ 106.250336134000065, 9.63117096600007 ], [ 106.064707879000025, 9.804266669000071 ], [ 105.996567502348185, 9.888559491461711 ], [ 106.132571242368897, 9.945827338161109 ], [ 106.134018182293232, 9.993679713847712 ], [ 106.246429884000065, 10.077460028000075 ] ] ] } }, { "type": "Feature", "properties": { "ISO": "VN-50", "NAME_1": "Bến Tre" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 106.422373893840074, 10.316961981110524 ], [ 106.480316602000073, 10.280829169000071 ], [ 106.720876498000052, 10.199693101000037 ], [ 106.797618035000028, 10.157212632000039 ], [ 106.791270379000025, 10.110174872000073 ], [ 106.737071160000028, 10.05414459800005 ], [ 106.704112175000034, 10.048895575000074 ], [ 106.69662519600007, 10.083644924000055 ], [ 106.668711785000028, 10.032416083000044 ], [ 106.684092644000032, 10.01203034100007 ], [ 106.664235873000052, 10.006089585000041 ], [ 106.648936394000032, 9.974351304000038 ], [ 106.607432488000029, 9.974839585000041 ], [ 106.468923373000052, 10.058986721000053 ], [ 106.359873894000032, 10.220689195000091 ], [ 106.292002800000034, 10.261704820000091 ], [ 106.349375847000033, 10.214829820000091 ], [ 106.36850019600007, 10.155910549000055 ], [ 106.461680535000028, 10.035711981000077 ], [ 106.696299675000034, 9.896551825000074 ], [ 106.668711785000028, 9.842840887000079 ], [ 106.676442905000044, 9.866766669000071 ], [ 106.662608269000032, 9.883734442000048 ], [ 106.637868686000047, 9.825995184000078 ], [ 106.586761915000068, 9.822943427000041 ], [ 106.504405144000032, 9.905462958000044 ], [ 106.395030144000032, 9.974351304000038 ], [ 106.136485222000033, 10.234564520000049 ], [ 105.954907667554778, 10.28851959939999 ], [ 105.973155143894758, 10.31334056231708 ], [ 106.003428581263961, 10.321071681412946 ], [ 106.10718834706455, 10.296250718495855 ], [ 106.354340039860915, 10.338975327149626 ], [ 106.422373893840074, 10.316961981110524 ] ] ], [ [ [ 106.498057488000029, 9.891180731000077 ], [ 106.544118686000047, 9.838039455000057 ], [ 106.535655144000032, 9.829169012000079 ], [ 106.422373894000032, 9.939032294000071 ], [ 106.498057488000029, 9.891180731000077 ] ] ] ] } }, -{ "type": "Feature", "properties": { "ISO": "VN-39", "NAME_1": "Đông Nam Bộ" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 106.997813347000033, 10.624904690000051 ], [ 106.984141472000033, 10.566880601000037 ], [ 106.964128881242857, 10.605376922007338 ], [ 106.892500259879057, 10.670073740810494 ], [ 106.836468193152541, 10.66083133799583 ], [ 106.757029250299638, 10.705393378501583 ], [ 106.751138136915415, 10.772495225474245 ], [ 106.793822869629707, 10.752625637463211 ], [ 106.828962844359751, 10.77086741839662 ], [ 106.877745396033163, 10.760790513971017 ], [ 106.885341830860739, 10.788179023343218 ], [ 106.832270136257762, 10.917344265525401 ], [ 106.787518345095521, 10.980673733505967 ], [ 106.787518345095521, 11.034675604995186 ], [ 106.827309197961085, 11.055527044937151 ], [ 106.902084995925804, 11.025968126128078 ], [ 106.954691604334016, 11.064001979807529 ], [ 106.974587029867507, 11.122422187234122 ], [ 106.933866001015076, 11.214742133242851 ], [ 106.964768507860299, 11.283626816924027 ], [ 107.080213657834008, 11.402740994001647 ], [ 107.104294875308199, 11.475423895996016 ], [ 107.308520136295215, 11.566219386815249 ], [ 107.382520787004694, 11.559501451131041 ], [ 107.398023715921681, 11.505964666735963 ], [ 107.458795200837812, 11.482529405307787 ], [ 107.443188918233943, 11.441214098152102 ], [ 107.456676467345062, 11.410414944094384 ], [ 107.52680138627494, 11.402508450004973 ], [ 107.609535354273135, 11.361684068365037 ], [ 107.548247105419534, 11.289156196001613 ], [ 107.430941604371526, 11.038086248781326 ], [ 107.459777052768743, 11.008837389234088 ], [ 107.531348911622956, 11.000129910367036 ], [ 107.557393832959008, 10.979666043153372 ], [ 107.588399692591679, 10.91176321050375 ], [ 107.5907768094022, 10.85086253527777 ], [ 107.516569452218391, 10.756062120570391 ], [ 107.482669711837673, 10.798410956500447 ], [ 107.457865024850946, 10.801511541924128 ], [ 107.342471551720678, 10.683740952882658 ], [ 107.300148553313022, 10.696401678794416 ], [ 107.288779737694711, 10.759007677262503 ], [ 107.266558873093459, 10.774433091813705 ], [ 107.151010370332301, 10.727665919946219 ], [ 107.133440382967251, 10.675214342068216 ], [ 107.040526157755949, 10.636792913861882 ], [ 107.025318916934452, 10.635272493031096 ], [ 107.013194207000026, 10.672674872000073 ], [ 106.984141472000033, 10.699367580000057 ], [ 106.97974694100003, 10.684759833000044 ], [ 107.01140384200005, 10.655259507000039 ], [ 106.997813347000033, 10.624904690000051 ] ] ] } }, +{ "type": "Feature", "properties": { "ISO": "VN-39", "NAME_1": "Đồng Nai" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 106.997813347000033, 10.624904690000051 ], [ 106.984141472000033, 10.566880601000037 ], [ 106.964128881242857, 10.605376922007338 ], [ 106.892500259879057, 10.670073740810494 ], [ 106.836468193152541, 10.66083133799583 ], [ 106.757029250299638, 10.705393378501583 ], [ 106.751138136915415, 10.772495225474245 ], [ 106.793822869629707, 10.752625637463211 ], [ 106.828962844359751, 10.77086741839662 ], [ 106.877745396033163, 10.760790513971017 ], [ 106.885341830860739, 10.788179023343218 ], [ 106.832270136257762, 10.917344265525401 ], [ 106.787518345095521, 10.980673733505967 ], [ 106.787518345095521, 11.034675604995186 ], [ 106.827309197961085, 11.055527044937151 ], [ 106.902084995925804, 11.025968126128078 ], [ 106.954691604334016, 11.064001979807529 ], [ 106.974587029867507, 11.122422187234122 ], [ 106.933866001015076, 11.214742133242851 ], [ 106.964768507860299, 11.283626816924027 ], [ 107.080213657834008, 11.402740994001647 ], [ 107.104294875308199, 11.475423895996016 ], [ 107.308520136295215, 11.566219386815249 ], [ 107.382520787004694, 11.559501451131041 ], [ 107.398023715921681, 11.505964666735963 ], [ 107.458795200837812, 11.482529405307787 ], [ 107.443188918233943, 11.441214098152102 ], [ 107.456676467345062, 11.410414944094384 ], [ 107.52680138627494, 11.402508450004973 ], [ 107.609535354273135, 11.361684068365037 ], [ 107.548247105419534, 11.289156196001613 ], [ 107.430941604371526, 11.038086248781326 ], [ 107.459777052768743, 11.008837389234088 ], [ 107.531348911622956, 11.000129910367036 ], [ 107.557393832959008, 10.979666043153372 ], [ 107.588399692591679, 10.91176321050375 ], [ 107.5907768094022, 10.85086253527777 ], [ 107.516569452218391, 10.756062120570391 ], [ 107.482669711837673, 10.798410956500447 ], [ 107.457865024850946, 10.801511541924128 ], [ 107.342471551720678, 10.683740952882658 ], [ 107.300148553313022, 10.696401678794416 ], [ 107.288779737694711, 10.759007677262503 ], [ 107.266558873093459, 10.774433091813705 ], [ 107.151010370332301, 10.727665919946219 ], [ 107.133440382967251, 10.675214342068216 ], [ 107.040526157755949, 10.636792913861882 ], [ 107.025318916934452, 10.635272493031096 ], [ 107.013194207000026, 10.672674872000073 ], [ 106.984141472000033, 10.699367580000057 ], [ 106.97974694100003, 10.684759833000044 ], [ 107.01140384200005, 10.655259507000039 ], [ 106.997813347000033, 10.624904690000051 ] ] ] } }, { "type": "Feature", "properties": { "ISO": "VN-40", "NAME_1": "Bình Thuận" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 108.905964763452928, 11.323376750700559 ], [ 108.838063998000052, 11.330755927000041 ], [ 108.787852410000028, 11.300685940000051 ], [ 108.729340040000068, 11.181545315000051 ], [ 108.656260613000029, 11.19281647300005 ], [ 108.57740319100003, 11.17914459800005 ], [ 108.531260613000029, 11.153265692000048 ], [ 108.500336134000065, 11.120835679000038 ], [ 108.47234134200005, 11.053168036000045 ], [ 108.36882571700005, 11.022772528000075 ], [ 108.34498131600003, 10.953802802000041 ], [ 108.315440300000034, 10.944322007000039 ], [ 108.30005944100003, 10.91282786700009 ], [ 108.285329623000052, 10.943345445000091 ], [ 108.258636915000068, 10.95180898600006 ], [ 108.106455925000034, 10.918158270000049 ], [ 108.06568444100003, 10.867987372000073 ], [ 107.998301629000025, 10.699367580000057 ], [ 107.882334832000026, 10.716986395000049 ], [ 107.768321160000028, 10.650213934000078 ], [ 107.586517774000072, 10.573513088000084 ], [ 107.516569452218391, 10.756062120570391 ], [ 107.5907768094022, 10.85086253527777 ], [ 107.588399692591679, 10.91176321050375 ], [ 107.544991490364964, 10.99214590101252 ], [ 107.476985304927837, 11.001447659082203 ], [ 107.430941604371526, 11.038086248781326 ], [ 107.511453485190145, 11.220865789724428 ], [ 107.597288038612021, 11.357575791689442 ], [ 107.756348098186152, 11.31491689739687 ], [ 108.010182733146564, 11.301481025129192 ], [ 108.045891147758198, 11.283704332189188 ], [ 108.0528674658608, 11.211021430194819 ], [ 108.066044955710083, 11.203399156046203 ], [ 108.131829054866955, 11.269364122356365 ], [ 108.250529819895235, 11.306519476892333 ], [ 108.324892205810613, 11.356258042974275 ], [ 108.338689813284191, 11.379305732573471 ], [ 108.314660271754121, 11.466897284282254 ], [ 108.341170281982897, 11.507928372396464 ], [ 108.386490513026729, 11.523844713362791 ], [ 108.513717888869451, 11.527720445142393 ], [ 108.580432164013132, 11.505215358801763 ], [ 108.620171340035256, 11.564023138956657 ], [ 108.666886835059358, 11.562834581450772 ], [ 108.704920688738753, 11.536712143950297 ], [ 108.721508824172872, 11.476638291923621 ], [ 108.762901645694342, 11.458603217464486 ], [ 108.771893345401509, 11.407779445764788 ], [ 108.867908156036549, 11.387987372119539 ], [ 108.905964763452928, 11.323376750700559 ] ] ], [ [ [ 108.942556186000047, 10.551947333000044 ], [ 108.958994988000029, 10.537543036000045 ], [ 108.960785352000073, 10.502875067000048 ], [ 108.930186394000032, 10.514553127000056 ], [ 108.929453972000033, 10.544826565000051 ], [ 108.942556186000047, 10.551947333000044 ] ] ] ] } }, { "type": "Feature", "properties": { "ISO": "VN-36", "NAME_1": "Ninh Thuận" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 109.20386803488185, 11.788682359303436 ], [ 109.242930535000028, 11.735663153000075 ], [ 109.13599694100003, 11.570217190000051 ], [ 109.067067905000044, 11.583807684000078 ], [ 109.043467644000032, 11.638495184000078 ], [ 109.020274285000028, 11.632798570000091 ], [ 109.04037519600007, 11.601507880000042 ], [ 109.04037519600007, 11.542873440000051 ], [ 109.012461785000028, 11.542873440000051 ], [ 109.028330925000034, 11.474269924000055 ], [ 109.022471550000034, 11.367621161000045 ], [ 109.005625847000033, 11.343654690000051 ], [ 108.96607506600003, 11.31476471600007 ], [ 108.933360222000033, 11.31118398600006 ], [ 108.905964763452928, 11.323376750700559 ], [ 108.867908156036549, 11.387987372119539 ], [ 108.778611281085716, 11.401965846746407 ], [ 108.762901645694342, 11.458603217464486 ], [ 108.715152622795244, 11.486301785199203 ], [ 108.6969625178059, 11.547770901206093 ], [ 108.620171340035256, 11.564023138956657 ], [ 108.606993850185972, 11.614381821763629 ], [ 108.610094435609653, 11.640142524058206 ], [ 108.683319939963212, 11.727113959041958 ], [ 108.637379592194407, 11.839200141173535 ], [ 108.681304559257967, 11.973171292021505 ], [ 108.694792108369086, 12.155330715340199 ], [ 108.719183384205792, 12.181143093578896 ], [ 108.792253858928404, 12.145538030855448 ], [ 108.890955844736425, 11.943121445897987 ], [ 109.0504293145612, 11.898033758850886 ], [ 109.085982701340527, 11.819382229106566 ], [ 109.114094680225264, 11.797962348383635 ], [ 109.20386803488185, 11.788682359303436 ] ] ] } }, { "type": "Feature", "properties": { "ISO": "VN-32", "NAME_1": "Phú Yên" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 109.237071160000028, 13.698594468000067 ], [ 109.247569207000026, 13.622707424000055 ], [ 109.303884311000047, 13.568793036000045 ], [ 109.28679446700005, 13.557603257000039 ], [ 109.29420006600003, 13.530340887000079 ], [ 109.218516472000033, 13.646958726000037 ], [ 109.210134311000047, 13.630804755000042 ], [ 109.28679446700005, 13.50922272300005 ], [ 109.314219597000033, 13.52289459800005 ], [ 109.303721550000034, 13.479885158000059 ], [ 109.339691602000073, 13.46548086100006 ], [ 109.307383660000028, 13.406805731000077 ], [ 109.273203972000033, 13.431057033000059 ], [ 109.30046634200005, 13.461371161000045 ], [ 109.262543165000068, 13.489325262000079 ], [ 109.245127800000034, 13.485174872000073 ], [ 109.232188347000033, 13.393133856000077 ], [ 109.280039910000028, 13.352769273000092 ], [ 109.299327019000032, 13.36469147300005 ], [ 109.307383660000028, 13.352769273000092 ], [ 109.305674675000034, 13.333889065000051 ], [ 109.28679446700005, 13.331040757000039 ], [ 109.29420006600003, 13.297552802000041 ], [ 109.273203972000033, 13.310614325000074 ], [ 109.258962436000047, 13.297552802000041 ], [ 109.29420006600003, 13.235500393000052 ], [ 109.303721550000034, 13.303168036000045 ], [ 109.318125847000033, 13.288885809000078 ], [ 109.307383660000028, 13.133042710000041 ], [ 109.328379754000025, 13.084662177000041 ], [ 109.465017123000052, 12.913316148000092 ], [ 109.462901238000029, 12.862127997000073 ], [ 109.43091881600003, 12.845119533000059 ], [ 109.450043165000068, 12.873236395000049 ], [ 109.438243035000028, 12.878607489000046 ], [ 109.384613477000073, 12.833970445000091 ], [ 109.342659540205545, 12.853091741990283 ], [ 109.195691765762319, 12.846813055877817 ], [ 109.073890415310359, 12.754079697819805 ], [ 109.03730350065598, 12.752658596317133 ], [ 108.861603632401682, 12.806996365489852 ], [ 108.739182164325371, 12.880351060153316 ], [ 108.660840692044246, 12.99623545969871 ], [ 108.665491571079087, 13.038997708577369 ], [ 108.687815790266484, 13.071295478503544 ], [ 108.845015496967562, 13.174570828081244 ], [ 108.87483279819503, 13.211312771467192 ], [ 108.821709425849292, 13.430498359012063 ], [ 108.825636835371597, 13.557519029279774 ], [ 108.909714389607359, 13.537830308421974 ], [ 108.977823927831935, 13.5425587018226 ], [ 109.080711704681391, 13.58707794808879 ], [ 109.163135614317127, 13.673300076037663 ], [ 109.237071160000028, 13.698594468000067 ] ] ] } }, @@ -56,8 +56,8 @@ { "type": "Feature", "properties": { "ISO": "VN-70", "NAME_1": "Vĩnh Phúc" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 105.429391440662414, 21.276437788273313 ], [ 105.457470330791068, 21.31172272382463 ], [ 105.392151319627658, 21.408771064133305 ], [ 105.343678827216081, 21.43468679515945 ], [ 105.317427199405699, 21.514139308782035 ], [ 105.460364210639739, 21.497163601518992 ], [ 105.577721389430508, 21.543827419699653 ], [ 105.764221633421585, 21.384922389756468 ], [ 105.779879591969575, 21.179120999434588 ], [ 105.762671339810424, 21.104965318194843 ], [ 105.670170525749143, 21.157623603446552 ], [ 105.494522333438908, 21.173694973144507 ], [ 105.455816685291722, 21.208576565456099 ], [ 105.429391440662414, 21.276437788273313 ] ] ] } }, { "type": "Feature", "properties": { "ISO": "VN-68", "NAME_1": "Phú Thọ" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 105.317427199405699, 21.514139308782035 ], [ 105.343678827216081, 21.43468679515945 ], [ 105.392151319627658, 21.408771064133305 ], [ 105.457780389153584, 21.300405585049702 ], [ 105.429391440662414, 21.276437788273313 ], [ 105.414682245289328, 21.307226874420678 ], [ 105.353807407585748, 21.301413276301616 ], [ 105.343162063278555, 21.238212999530276 ], [ 105.284871047061131, 21.191549181349615 ], [ 105.305955030999826, 21.126669419757889 ], [ 105.284871047061131, 21.054374091391196 ], [ 105.329881219742447, 20.981406969456032 ], [ 105.332671746803612, 20.918826809409723 ], [ 105.138109979092235, 20.940479234129327 ], [ 105.042043491613811, 21.00858877235396 ], [ 104.942256301087355, 21.053598945035276 ], [ 104.873629998925253, 21.137624823326917 ], [ 104.865775180779906, 21.250201930974299 ], [ 104.828516472557112, 21.329602769552139 ], [ 104.895127394913288, 21.365414536951278 ], [ 104.919311965174984, 21.397919013351782 ], [ 104.889959751041658, 21.567055976452139 ], [ 104.946597120860417, 21.640255642383977 ], [ 105.111754999393668, 21.703946845570442 ], [ 105.233194614639729, 21.618732407974221 ], [ 105.317427199405699, 21.514139308782035 ] ] ] } }, { "type": "Feature", "properties": { "ISO": "VN-HN", "NAME_1": "Hà Nội" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 105.785822382197125, 20.568305569346535 ], [ 105.679782343080603, 20.637655341021173 ], [ 105.629656203371042, 20.742119249004134 ], [ 105.515968051684183, 20.828625596893744 ], [ 105.505736119426331, 20.862499497953479 ], [ 105.533486363105112, 20.927120877126754 ], [ 105.504495884177686, 20.987246405996814 ], [ 105.437109817264229, 21.018562323092738 ], [ 105.307918735761007, 21.011921901774315 ], [ 105.290968866020307, 21.038199368006417 ], [ 105.286834750922992, 21.075561428117396 ], [ 105.305955030999826, 21.126669419757889 ], [ 105.284871047061131, 21.191549181349615 ], [ 105.343162063278555, 21.238212999530276 ], [ 105.353807407585748, 21.301413276301616 ], [ 105.414682245289328, 21.307226874420678 ], [ 105.455816685291722, 21.208576565456099 ], [ 105.494522333438908, 21.173694973144507 ], [ 105.670170525749143, 21.157623603446552 ], [ 105.762671339810424, 21.104965318194843 ], [ 105.779879591969575, 21.179120999434588 ], [ 105.772128126611733, 21.362468980259223 ], [ 105.805046014162201, 21.373088487044015 ], [ 105.84835086540005, 21.363631700242763 ], [ 105.920801223397689, 21.328052475940979 ], [ 105.94607099837782, 21.265782376055768 ], [ 105.920956252129315, 21.208731594187725 ], [ 105.922041456847694, 21.150466417291284 ], [ 105.939094680275218, 21.108918565239605 ], [ 106.010304803024212, 21.045692450046488 ], [ 106.012785271722862, 21.016908678492712 ], [ 106.004723748901824, 20.991303004929705 ], [ 105.912429641314873, 20.965929877162068 ], [ 105.895324741943227, 20.914356798427491 ], [ 105.924728632020731, 20.886709905737519 ], [ 105.915065138745092, 20.809634508026136 ], [ 105.956147901904103, 20.786819363322934 ], [ 105.981314324996049, 20.717185369908862 ], [ 106.007204217600531, 20.713232122864156 ], [ 105.976508417229638, 20.681011868203143 ], [ 105.825509882275185, 20.660341295414412 ], [ 105.785822382197125, 20.568305569346535 ] ] ] } }, -{ "type": "Feature", "properties": { "ISO": "VN-53", "NAME_1": "Đông Bắc" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 105.557515903735919, 21.950882676794095 ], [ 105.494987421432313, 22.101209418180076 ], [ 105.494677362170478, 22.268563544571919 ], [ 105.519843785262424, 22.340290432157701 ], [ 105.609295688944826, 22.469972439176729 ], [ 105.607021925821186, 22.517643947709985 ], [ 105.567644484105642, 22.592238878521414 ], [ 105.648466425085417, 22.677944240734121 ], [ 105.724947543594226, 22.724142970921378 ], [ 105.773833448954463, 22.713704332189138 ], [ 105.765255162195956, 22.617301947926535 ], [ 105.815122918587804, 22.505267441739022 ], [ 105.86147667840595, 22.47501089093987 ], [ 105.895014682681392, 22.474700833476675 ], [ 106.048183627972037, 22.540226549315776 ], [ 106.107921584113797, 22.530563056040194 ], [ 106.137738886240584, 22.43183523181051 ], [ 106.162078485233849, 22.408839219954018 ], [ 106.192980992079072, 22.406694648039547 ], [ 106.220266147764448, 22.320808416874911 ], [ 106.260005323786629, 22.262103990406843 ], [ 106.190448845637661, 22.111777249020804 ], [ 106.123476189874225, 22.054313056002741 ], [ 106.113967727128852, 21.948117988154593 ], [ 106.035936314109563, 21.928015855247509 ], [ 106.001468133847254, 21.887759915287859 ], [ 105.915530226738554, 21.834688218886185 ], [ 105.839152460117873, 21.814172674829081 ], [ 105.813727654607533, 21.779265244995031 ], [ 105.78706261564713, 21.827737739205304 ], [ 105.772903273866973, 21.977806098172891 ], [ 105.734869419288202, 22.019741522952927 ], [ 105.699832798244984, 22.033125719276484 ], [ 105.6450557803999, 22.019508978956196 ], [ 105.584387649170651, 21.956954657331551 ], [ 105.557515903735919, 21.950882676794095 ] ] ] } }, -{ "type": "Feature", "properties": { "ISO": "VN-66", "NAME_1": "Đồng Bằng Sông Hồng" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 106.257369826356353, 20.695894680395156 ], [ 106.206468540290871, 20.667214259830189 ], [ 106.138669061328073, 20.666826687101889 ], [ 106.112882522410416, 20.649566758998731 ], [ 106.112365756674308, 20.631609198006061 ], [ 106.059655796377854, 20.616623033026542 ], [ 106.02699629124578, 20.663286851207204 ], [ 106.030200230356286, 20.708090318313509 ], [ 105.981314324996049, 20.717185369908862 ], [ 105.956147901904103, 20.786819363322934 ], [ 105.915065138745092, 20.809634508026136 ], [ 105.924728632020731, 20.886709905737519 ], [ 105.895324741943227, 20.914356798427491 ], [ 105.912429641314873, 20.965929877162068 ], [ 106.022758824260279, 20.997736721572437 ], [ 106.152156610439192, 20.997814235938222 ], [ 106.159598015635879, 20.926190701139944 ], [ 106.125749952997865, 20.851208198499535 ], [ 106.126576776197226, 20.813536078227401 ], [ 106.257369826356353, 20.695894680395156 ] ] ] } }, +{ "type": "Feature", "properties": { "ISO": "VN-53", "NAME_1": "Bắc Kạn" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 105.557515903735919, 21.950882676794095 ], [ 105.494987421432313, 22.101209418180076 ], [ 105.494677362170478, 22.268563544571919 ], [ 105.519843785262424, 22.340290432157701 ], [ 105.609295688944826, 22.469972439176729 ], [ 105.607021925821186, 22.517643947709985 ], [ 105.567644484105642, 22.592238878521414 ], [ 105.648466425085417, 22.677944240734121 ], [ 105.724947543594226, 22.724142970921378 ], [ 105.773833448954463, 22.713704332189138 ], [ 105.765255162195956, 22.617301947926535 ], [ 105.815122918587804, 22.505267441739022 ], [ 105.86147667840595, 22.47501089093987 ], [ 105.895014682681392, 22.474700833476675 ], [ 106.048183627972037, 22.540226549315776 ], [ 106.107921584113797, 22.530563056040194 ], [ 106.137738886240584, 22.43183523181051 ], [ 106.162078485233849, 22.408839219954018 ], [ 106.192980992079072, 22.406694648039547 ], [ 106.220266147764448, 22.320808416874911 ], [ 106.260005323786629, 22.262103990406843 ], [ 106.190448845637661, 22.111777249020804 ], [ 106.123476189874225, 22.054313056002741 ], [ 106.113967727128852, 21.948117988154593 ], [ 106.035936314109563, 21.928015855247509 ], [ 106.001468133847254, 21.887759915287859 ], [ 105.915530226738554, 21.834688218886185 ], [ 105.839152460117873, 21.814172674829081 ], [ 105.813727654607533, 21.779265244995031 ], [ 105.78706261564713, 21.827737739205304 ], [ 105.772903273866973, 21.977806098172891 ], [ 105.734869419288202, 22.019741522952927 ], [ 105.699832798244984, 22.033125719276484 ], [ 105.6450557803999, 22.019508978956196 ], [ 105.584387649170651, 21.956954657331551 ], [ 105.557515903735919, 21.950882676794095 ] ] ] } }, +{ "type": "Feature", "properties": { "ISO": "VN-66", "NAME_1": "Hưng Yên" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 106.257369826356353, 20.695894680395156 ], [ 106.206468540290871, 20.667214259830189 ], [ 106.138669061328073, 20.666826687101889 ], [ 106.112882522410416, 20.649566758998731 ], [ 106.112365756674308, 20.631609198006061 ], [ 106.059655796377854, 20.616623033026542 ], [ 106.02699629124578, 20.663286851207204 ], [ 106.030200230356286, 20.708090318313509 ], [ 105.981314324996049, 20.717185369908862 ], [ 105.956147901904103, 20.786819363322934 ], [ 105.915065138745092, 20.809634508026136 ], [ 105.924728632020731, 20.886709905737519 ], [ 105.895324741943227, 20.914356798427491 ], [ 105.912429641314873, 20.965929877162068 ], [ 106.022758824260279, 20.997736721572437 ], [ 106.152156610439192, 20.997814235938222 ], [ 106.159598015635879, 20.926190701139944 ], [ 106.125749952997865, 20.851208198499535 ], [ 106.126576776197226, 20.813536078227401 ], [ 106.257369826356353, 20.695894680395156 ] ] ] } }, { "type": "Feature", "properties": { "ISO": "VN-56", "NAME_1": "Bắc Ninh" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 106.152156610439192, 20.997814235938222 ], [ 106.004723748901824, 20.991303004929705 ], [ 106.010304803024212, 21.045692450046488 ], [ 105.939094680275218, 21.108918565239605 ], [ 105.922041456847694, 21.150466417291284 ], [ 105.920956252129315, 21.208731594187725 ], [ 105.944985792760065, 21.247488919178238 ], [ 106.046633335260196, 21.206431993541628 ], [ 106.227552525128885, 21.177880764185886 ], [ 106.298039178365343, 21.134059149909831 ], [ 106.315815871305347, 21.050524197133996 ], [ 106.295041944829848, 21.000527249532922 ], [ 106.22646732041045, 20.985515245232364 ], [ 106.152156610439192, 20.997814235938222 ] ] ] } }, { "type": "Feature", "properties": { "ISO": "VN-54", "NAME_1": "Bắc Giang" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 107.065330844742675, 21.360531113919762 ], [ 106.998616571397633, 21.314668281416061 ], [ 106.980633172882563, 21.230564886959939 ], [ 106.947870314963041, 21.189688829375939 ], [ 106.759199659736453, 21.161680203278763 ], [ 106.54582767121002, 21.193719590786486 ], [ 106.487950067041936, 21.228006903895505 ], [ 106.422165968784384, 21.23095245968824 ], [ 106.329510125991476, 21.18800934545493 ], [ 106.298039178365343, 21.134059149909831 ], [ 106.227552525128885, 21.177880764185886 ], [ 106.046633335260196, 21.206431993541628 ], [ 105.944985792760065, 21.247488919178238 ], [ 105.920801223397689, 21.328052475940979 ], [ 105.971082390939557, 21.408771064133305 ], [ 106.035471226116158, 21.419493922806282 ], [ 106.067148879317301, 21.461377672541516 ], [ 106.071903111139648, 21.502589626909753 ], [ 106.038726841170728, 21.620205186320277 ], [ 106.050354039207491, 21.632685045078745 ], [ 106.143785028356319, 21.620980333575517 ], [ 106.161303338877929, 21.602635198955227 ], [ 106.165489129919365, 21.51713654231753 ], [ 106.291941359406167, 21.477474879761871 ], [ 106.352919549897251, 21.423860581900328 ], [ 106.398704868934487, 21.411070664779345 ], [ 106.477976516303158, 21.448303534580418 ], [ 106.522108188941729, 21.544912625317409 ], [ 106.580399205159154, 21.599095363959862 ], [ 106.658740675641639, 21.607363593255229 ], [ 106.747727492229956, 21.549253445090415 ], [ 106.82792931468606, 21.597157498519721 ], [ 106.921980422358558, 21.445022081104128 ], [ 107.00683312384956, 21.441766466049557 ], [ 107.024093051952718, 21.376163234945295 ], [ 107.065330844742675, 21.360531113919762 ] ] ] } }, { "type": "Feature", "properties": { "ISO": "VN-69", "NAME_1": "Thái Nguyên" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 105.577721389430508, 21.543827419699653 ], [ 105.537052037421574, 21.578683172690262 ], [ 105.518293491651264, 21.635501410561631 ], [ 105.534364862248538, 21.866779283237292 ], [ 105.557515903735919, 21.950882676794095 ], [ 105.584387649170651, 21.956954657331551 ], [ 105.626865676309876, 22.010439764883245 ], [ 105.683709750804326, 22.030748603365339 ], [ 105.717196080035023, 22.030335191315999 ], [ 105.772903273866973, 21.977806098172891 ], [ 105.785305617360336, 21.83784048115325 ], [ 105.80690636613582, 21.780040392250271 ], [ 105.839152460117873, 21.814172674829081 ], [ 105.899407180197159, 21.825954902496733 ], [ 106.001468133847254, 21.887759915287859 ], [ 106.035936314109563, 21.928015855247509 ], [ 106.113967727128852, 21.948117988154593 ], [ 106.141924677281963, 21.805336004752803 ], [ 106.181353794042309, 21.785388902375928 ], [ 106.256698032787938, 21.684878241437673 ], [ 106.16750451062461, 21.57077667950017 ], [ 106.143785028356319, 21.620980333575517 ], [ 106.041517369131213, 21.628421738772204 ], [ 106.071903111139648, 21.502589626909753 ], [ 106.067148879317301, 21.461377672541516 ], [ 106.035471226116158, 21.419493922806282 ], [ 105.971082390939557, 21.408771064133305 ], [ 105.920801223397689, 21.328052475940979 ], [ 105.84835086540005, 21.363631700242763 ], [ 105.805046014162201, 21.373088487044015 ], [ 105.772128126611733, 21.362468980259223 ], [ 105.740037063159889, 21.417556057366141 ], [ 105.577721389430508, 21.543827419699653 ] ] ] } }, diff --git a/superset-frontend/plugins/legacy-preset-chart-deckgl/package.json b/superset-frontend/plugins/legacy-preset-chart-deckgl/package.json index 08425170fff89..0c7e66b2466a7 100644 --- a/superset-frontend/plugins/legacy-preset-chart-deckgl/package.json +++ b/superset-frontend/plugins/legacy-preset-chart-deckgl/package.json @@ -31,7 +31,7 @@ "d3-array": "^1.2.4", "d3-color": "^1.4.1", "d3-scale": "^3.0.0", - "deck.gl": "9.0.28", + "deck.gl": "9.0.34", "lodash": "^4.17.21", "moment": "^2.30.1", "mousetrap": "^1.6.5", diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BoxPlot/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BoxPlot/transformProps.ts index 8150c3e3e14b6..5eb80b1a6fed5 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BoxPlot/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BoxPlot/transformProps.ts @@ -229,10 +229,10 @@ export default function transformProps( `Median: ${numberFormatter(value[3])}`, `1st Quartile: ${numberFormatter(value[2])}`, `Min: ${numberFormatter(value[1])}`, - `# Observations: ${numberFormatter(value[7])}`, + `# Observations: ${value[7]}`, ]; if (value[8].length > 0) { - stats.push(`# Outliers: ${numberFormatter(value[8].length)}`); + stats.push(`# Outliers: ${value[8].length}`); } return headline + stats.join('
'); }, diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Graph/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Graph/transformProps.ts index 5d50a5af7bfd4..100d21349e416 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Graph/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Graph/transformProps.ts @@ -198,6 +198,7 @@ export default function transformProps( const refs: Refs = {}; const metricLabel = getMetricLabel(metric); const colorFn = CategoricalColorNamespace.getScale(colorScheme as string); + const firstColor = colorFn.range()[0]; const nodes: { [name: string]: number } = {}; const categories: Set = new Set(); const echartNodes: EChartGraphNode[] = []; @@ -207,7 +208,12 @@ export default function transformProps( * Get the node id of an existing node, * or create a new node if it doesn't exist. */ - function getOrCreateNode(name: string, col: string, category?: string) { + function getOrCreateNode( + name: string, + col: string, + category?: string, + color?: string, + ) { if (!(name in nodes)) { nodes[name] = echartNodes.length; echartNodes.push({ @@ -221,6 +227,7 @@ export default function transformProps( ...getDefaultTooltip(refs), ...DEFAULT_GRAPH_SERIES_OPTION.tooltip, }, + itemStyle: { color }, }); } const node = echartNodes[nodes[name]]; @@ -248,8 +255,25 @@ export default function transformProps( const targetCategoryName = targetCategory ? getCategoryName(targetCategory, link[targetCategory]) : undefined; - const sourceNode = getOrCreateNode(sourceName, source, sourceCategoryName); - const targetNode = getOrCreateNode(targetName, target, targetCategoryName); + const sourceNodeColor = sourceCategoryName + ? colorFn(sourceCategoryName) + : firstColor; + const targetNodeColor = targetCategoryName + ? colorFn(targetCategoryName) + : firstColor; + + const sourceNode = getOrCreateNode( + sourceName, + source, + sourceCategoryName, + sourceNodeColor, + ); + const targetNode = getOrCreateNode( + targetName, + target, + targetCategoryName, + targetNodeColor, + ); sourceNode.value += value; targetNode.value += value; @@ -258,7 +282,9 @@ export default function transformProps( source: sourceNode.id, target: targetNode.id, value, - lineStyle: {}, + lineStyle: { + color: sourceNodeColor, + }, emphasis: {}, select: {}, }); diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts index e12cdfe6f8101..d4d19f9c2f6af 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts @@ -62,6 +62,7 @@ import { extractDataTotalValues, extractSeries, extractShowValueIndexes, + extractTooltipKeys, getAxisType, getColtypesMapping, getLegendProps, @@ -584,9 +585,13 @@ export default function transformProps( : params.value[0]; const forecastValue: any[] = richTooltip ? params : [params]; - if (richTooltip && tooltipSortByMetric) { - forecastValue.sort((a, b) => b.data[1] - a.data[1]); - } + const sortedKeys = extractTooltipKeys( + forecastValue, + // horizontal mode is not supported in mixed series chart + 1, + richTooltip, + tooltipSortByMetric, + ); const rows: string[][] = []; const forecastValues = @@ -594,44 +599,46 @@ export default function transformProps( const keys = Object.keys(forecastValues); let focusedRow; - keys.forEach(key => { - const value = forecastValues[key]; - // if there are no dimensions, key is a verbose name of a metric, - // otherwise it is a comma separated string where the first part is metric name - let formatterKey; - if (primarySeries.has(key)) { - formatterKey = - groupby.length === 0 ? inverted[key] : labelMap[key]?.[0]; - } else { - formatterKey = - groupbyB.length === 0 ? inverted[key] : labelMapB[key]?.[0]; - } - const tooltipFormatter = getFormatter( - customFormatters, - formatter, - metrics, - formatterKey, - !!contributionMode, - ); - const tooltipFormatterSecondary = getFormatter( - customFormattersSecondary, - formatterSecondary, - metricsB, - formatterKey, - !!contributionMode, - ); - const row = formatForecastTooltipSeries({ - ...value, - seriesName: key, - formatter: primarySeries.has(key) - ? tooltipFormatter - : tooltipFormatterSecondary, + sortedKeys + .filter(key => keys.includes(key)) + .forEach(key => { + const value = forecastValues[key]; + // if there are no dimensions, key is a verbose name of a metric, + // otherwise it is a comma separated string where the first part is metric name + let formatterKey; + if (primarySeries.has(key)) { + formatterKey = + groupby.length === 0 ? inverted[key] : labelMap[key]?.[0]; + } else { + formatterKey = + groupbyB.length === 0 ? inverted[key] : labelMapB[key]?.[0]; + } + const tooltipFormatter = getFormatter( + customFormatters, + formatter, + metrics, + formatterKey, + !!contributionMode, + ); + const tooltipFormatterSecondary = getFormatter( + customFormattersSecondary, + formatterSecondary, + metricsB, + formatterKey, + !!contributionMode, + ); + const row = formatForecastTooltipSeries({ + ...value, + seriesName: key, + formatter: primarySeries.has(key) + ? tooltipFormatter + : tooltipFormatterSecondary, + }); + rows.push(row); + if (key === focusedSeries) { + focusedRow = rows.length - 1; + } }); - rows.push(row); - if (key === focusedSeries) { - focusedRow = rows.length - 1; - } - }); return tooltipHtml(rows, tooltipFormatter(xValue), focusedRow); }, }, diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts index c0da444bfe802..b552ceba5c49e 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts @@ -65,6 +65,7 @@ import { extractDataTotalValues, extractSeries, extractShowValueIndexes, + extractTooltipKeys, getAxisType, getColtypesMapping, getLegendProps, @@ -251,7 +252,7 @@ export default function transformProps( legendState, }); const seriesContexts = extractForecastSeriesContexts( - Object.values(rawSeries).map(series => series.name as string), + rawSeries.map(series => series.name as string), ); const isAreaExpand = stack === StackControlsValue.Expand; const xAxisDataType = dataTypes?.[xAxisLabel] ?? dataTypes?.[xAxisOrig]; @@ -543,11 +544,12 @@ export default function transformProps( ? params[0].value[xIndex] : params.value[xIndex]; const forecastValue: any[] = richTooltip ? params : [params]; - - if (richTooltip && tooltipSortByMetric) { - forecastValue.sort((a, b) => b.data[yIndex] - a.data[yIndex]); - } - + const sortedKeys = extractTooltipKeys( + forecastValue, + yIndex, + richTooltip, + tooltipSortByMetric, + ); const forecastValues: Record = extractForecastValuesFromTooltipParams(forecastValue, isHorizontal); @@ -570,24 +572,28 @@ export default function transformProps( const showPercentage = showTotal && !forcePercentFormatter; const keys = Object.keys(forecastValues); let focusedRow; - keys.forEach(key => { - const value = forecastValues[key]; - if (value.observation === 0 && stack) { - return; - } - const row = formatForecastTooltipSeries({ - ...value, - seriesName: key, - formatter, + sortedKeys + .filter(key => keys.includes(key)) + .forEach(key => { + const value = forecastValues[key]; + if (value.observation === 0 && stack) { + return; + } + const row = formatForecastTooltipSeries({ + ...value, + seriesName: key, + formatter, + }); + if (showPercentage && value.observation !== undefined) { + row.push( + percentFormatter.format(value.observation / (total || 1)), + ); + } + rows.push(row); + if (key === focusedSeries) { + focusedRow = rows.length - 1; + } }); - if (showPercentage && value.observation !== undefined) { - row.push(percentFormatter.format(value.observation / (total || 1))); - } - rows.push(row); - if (key === focusedSeries) { - focusedRow = rows.length - 1; - } - }); if (stack) { rows.reverse(); if (focusedRow !== undefined) { diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts index 13d36b71418ba..0aa0ae988ee98 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts @@ -642,3 +642,22 @@ export function getTimeCompareStackId( }) || defaultId ); } + +const TOOLTIP_SERIES_KEY = 'seriesId'; +export function extractTooltipKeys( + forecastValue: any[], + yIndex: number, + richTooltip?: boolean, + tooltipSortByMetric?: boolean, +): string[] { + if (richTooltip && tooltipSortByMetric) { + return forecastValue + .slice() + .sort((a, b) => b.data[yIndex] - a.data[yIndex]) + .map(value => value[TOOLTIP_SERIES_KEY]); + } + if (richTooltip) { + return forecastValue.map(s => s[TOOLTIP_SERIES_KEY]); + } + return [forecastValue[0][TOOLTIP_SERIES_KEY]]; +} diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/Graph/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/Graph/transformProps.test.ts index e7f0b47946f8c..034194fd06525 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/Graph/transformProps.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/Graph/transformProps.test.ts @@ -74,6 +74,9 @@ describe('EchartsGraph transformProps', () => { col: 'source_column', category: undefined, id: '0', + itemStyle: { + color: '#1f77b4', + }, label: { show: true }, name: 'source_value_1', select: { @@ -88,6 +91,9 @@ describe('EchartsGraph transformProps', () => { col: 'target_column', category: undefined, id: '1', + itemStyle: { + color: '#1f77b4', + }, label: { show: true }, name: 'target_value_1', select: { @@ -102,6 +108,9 @@ describe('EchartsGraph transformProps', () => { col: 'source_column', category: undefined, id: '2', + itemStyle: { + color: '#1f77b4', + }, label: { show: true }, name: 'source_value_2', select: { @@ -116,6 +125,9 @@ describe('EchartsGraph transformProps', () => { col: 'target_column', category: undefined, id: '3', + itemStyle: { + color: '#1f77b4', + }, label: { show: true }, name: 'target_value_2', select: { @@ -132,7 +144,7 @@ describe('EchartsGraph transformProps', () => { links: [ { emphasis: { lineStyle: { width: 12 } }, - lineStyle: { width: 6 }, + lineStyle: { width: 6, color: '#1f77b4' }, select: { lineStyle: { opacity: 1, width: 9.600000000000001 }, }, @@ -142,7 +154,7 @@ describe('EchartsGraph transformProps', () => { }, { emphasis: { lineStyle: { width: 5 } }, - lineStyle: { width: 1.5 }, + lineStyle: { width: 1.5, color: '#1f77b4' }, select: { lineStyle: { opacity: 1, width: 5 } }, source: '2', target: '3', @@ -217,6 +229,9 @@ describe('EchartsGraph transformProps', () => { data: [ { id: '0', + itemStyle: { + color: '#1f77b4', + }, col: 'source_column', name: 'source_value', value: 11, @@ -228,6 +243,9 @@ describe('EchartsGraph transformProps', () => { }, { id: '1', + itemStyle: { + color: '#ff7f0e', + }, col: 'target_column', name: 'target_value', value: 11, diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts index efc0ac745aedf..7054f6019ad30 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts @@ -31,6 +31,7 @@ import { extractGroupbyLabel, extractSeries, extractShowValueIndexes, + extractTooltipKeys, formatSeriesName, getAxisType, getChartPadding, @@ -1072,3 +1073,29 @@ describe('getTimeCompareStackId', () => { expect(result).toEqual('123'); }); }); + +const forecastValue = [ + { + data: [0, 1], + seriesId: 'foo', + }, + { + data: [0, 2], + seriesId: 'bar', + }, +]; + +test('extractTooltipKeys with rich tooltip', () => { + const result = extractTooltipKeys(forecastValue, 1, true, false); + expect(result).toEqual(['foo', 'bar']); +}); + +test('extractTooltipKeys with rich tooltip and sorting by metrics', () => { + const result = extractTooltipKeys(forecastValue, 1, true, true); + expect(result).toEqual(['bar', 'foo']); +}); + +test('extractTooltipKeys with non-rich tooltip', () => { + const result = extractTooltipKeys(forecastValue, 1, false, false); + expect(result).toEqual(['foo']); +}); diff --git a/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/controlPanel.tsx index e5dea8c4682a8..cda65f5527815 100644 --- a/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/controlPanel.tsx @@ -16,6 +16,13 @@ * specific language governing permissions and limitations * under the License. */ +import { + ControlPanelConfig, + D3_TIME_FORMAT_OPTIONS, + Dataset, + getStandardizedControls, + sharedControls, +} from '@superset-ui/chart-controls'; import { ensureIsArray, isAdhocColumn, @@ -25,13 +32,6 @@ import { t, validateNonEmpty, } from '@superset-ui/core'; -import { - ControlPanelConfig, - D3_TIME_FORMAT_OPTIONS, - sharedControls, - Dataset, - getStandardizedControls, -} from '@superset-ui/chart-controls'; import { MetricsLayoutEnum } from '../types'; const config: ControlPanelConfig = { @@ -436,7 +436,9 @@ const config: ControlPanelConfig = { label: t('Render columns in HTML format'), renderTrigger: true, default: true, - description: t('Render data in HTML format if applicable.'), + description: t( + 'Renders table cells as HTML when applicable. For example, HTML <a> tags will be rendered as hyperlinks.', + ), }, }, ], diff --git a/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx index 0d27c73c48c39..e67bdfcea0c89 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx @@ -18,32 +18,32 @@ * under the License. */ import { - ensureIsArray, - GenericDataType, - isAdhocColumn, - isPhysicalColumn, - QueryFormColumn, - QueryMode, - SMART_DATE_ID, - t, -} from '@superset-ui/core'; -import { + ColumnMeta, ColumnOption, ControlConfig, ControlPanelConfig, ControlPanelsContainerProps, - ControlStateMapping, - D3_TIME_FORMAT_OPTIONS, - QueryModeLabel, - sharedControls, ControlPanelState, ControlState, + ControlStateMapping, + D3_TIME_FORMAT_OPTIONS, Dataset, - ColumnMeta, defineSavedMetrics, getStandardizedControls, + QueryModeLabel, sections, + sharedControls, } from '@superset-ui/chart-controls'; +import { + ensureIsArray, + GenericDataType, + isAdhocColumn, + isPhysicalColumn, + QueryFormColumn, + QueryMode, + SMART_DATE_ID, + t, +} from '@superset-ui/core'; import { isEmpty } from 'lodash'; import { PAGE_SIZE_OPTIONS } from './consts'; @@ -466,7 +466,9 @@ const config: ControlPanelConfig = { label: t('Render columns in HTML format'), renderTrigger: true, default: true, - description: t('Render data in HTML format if applicable.'), + description: t( + 'Renders table cells as HTML when applicable. For example, HTML <a> tags will be rendered as hyperlinks.', + ), }, }, ], diff --git a/superset-frontend/spec/fixtures/mockSliceEntities.js b/superset-frontend/spec/fixtures/mockSliceEntities.js index 2737d35d01d40..1a7bdad02429f 100644 --- a/superset-frontend/spec/fixtures/mockSliceEntities.js +++ b/superset-frontend/spec/fixtures/mockSliceEntities.js @@ -17,6 +17,7 @@ * under the License. */ import { datasourceId } from 'spec/fixtures/mockDatasource'; +import { DatasourceType } from '@superset-ui/core'; import { sliceId } from './mockChartQueries'; export const filterId = 127; @@ -47,8 +48,8 @@ export const sliceEntitiesForChart = { }, viz_type: 'pie', datasource: datasourceId, - description: null, - description_markeddown: '', + description: '', + description_markdown: '', modified: '23 hours ago', changed_on: 1529453332615, }, @@ -79,10 +80,18 @@ export const sliceEntitiesForDashboard = { }, viz_type: 'filter_box', datasource: '2__table', - description: null, - description_markeddown: '', + description: '', + description_markdown: '', modified: '23 hours ago', changed_on: 1529453332615, + changed_on_humanized: '', + datasource_id: 0, + datasource_type: DatasourceType.Query, + datasource_url: '', + datasource_name: '', + owners: [{ id: 0 }], + created_by: { id: 0 }, + thumbnail_url: '', }, 128: { slice_id: 128, @@ -91,10 +100,18 @@ export const sliceEntitiesForDashboard = { form_data: {}, viz_type: 'big_number', datasource: '2__table', - description: null, - description_markeddown: '', + description: '', + description_markdown: '', modified: '23 hours ago', changed_on: 1529453332628, + changed_on_humanized: '', + datasource_id: 0, + datasource_type: DatasourceType.Query, + datasource_url: '', + datasource_name: '', + owners: [{ id: 0 }], + created_by: { id: 0 }, + thumbnail_url: '', }, 129: { slice_id: 129, @@ -103,10 +120,19 @@ export const sliceEntitiesForDashboard = { form_data: {}, viz_type: 'table', datasource: '2__table', - description: null, - description_markeddown: '', + description: '', + description_markdown: 'dd', modified: '23 hours ago', changed_on: 1529453332637, + changed_on_humanized: '', + + datasource_id: 0, + datasource_type: DatasourceType.Query, + datasource_url: '', + datasource_name: '', + owners: [{ id: 0 }], + created_by: { id: 0 }, + thumbnail_url: '', }, 130: { slice_id: 130, @@ -115,10 +141,19 @@ export const sliceEntitiesForDashboard = { form_data: {}, viz_type: 'line', datasource: '2__table', - description: null, - description_markeddown: '', + description: '', + description_markdown: '', modified: '23 hours ago', changed_on: 1529453332645, + changed_on_humanized: '', + + datasource_id: 0, + datasource_type: DatasourceType.SlTable, + datasource_url: '', + datasource_name: '', + owners: [{ id: 0 }], + created_by: { id: 0 }, + thumbnail_url: '', }, 131: { slice_id: 131, @@ -127,10 +162,19 @@ export const sliceEntitiesForDashboard = { form_data: {}, viz_type: 'world_map', datasource: '2__table', - description: null, - description_markeddown: '', + description: '', + description_markdown: '', modified: '23 hours ago', changed_on: 1529453332654, + changed_on_humanized: '', + + datasource_id: 0, + datasource_type: DatasourceType.Table, + datasource_url: '', + datasource_name: '', + owners: [{ id: 0 }], + created_by: { id: 0 }, + thumbnail_url: '', }, 132: { slice_id: 132, @@ -139,10 +183,19 @@ export const sliceEntitiesForDashboard = { form_data: {}, viz_type: 'bubble', datasource: '2__table', - description: null, - description_markeddown: '', + description: '', + description_markdown: '', modified: '23 hours ago', changed_on: 1529453332663, + changed_on_humanized: '', + + datasource_id: 0, + datasource_type: DatasourceType.Query, + datasource_url: '', + datasource_name: '', + owners: [{ id: 0 }], + created_by: { id: 0 }, + thumbnail_url: '', }, 133: { slice_id: 133, @@ -151,10 +204,19 @@ export const sliceEntitiesForDashboard = { form_data: {}, viz_type: 'sunburst_v2', datasource: '2__table', - description: null, - description_markeddown: '', + description: '', + description_markdown: '', modified: '23 hours ago', changed_on: 1529453332673, + changed_on_humanized: '', + + datasource_id: 0, + datasource_type: DatasourceType.Query, + datasource_url: '', + datasource_name: '', + owners: [{ id: 0 }], + created_by: { id: 0 }, + thumbnail_url: '', }, 134: { slice_id: 134, @@ -163,10 +225,19 @@ export const sliceEntitiesForDashboard = { form_data: {}, viz_type: 'area', datasource: '2__table', - description: null, - description_markeddown: '', + description: '', + description_markdown: '', modified: '23 hours ago', changed_on: 1529453332680, + changed_on_humanized: '', + + datasource_id: 0, + datasource_type: DatasourceType.Dataset, + datasource_url: '', + datasource_name: '', + owners: [{ id: 0 }], + created_by: { id: 0 }, + thumbnail_url: '', }, 135: { slice_id: 135, @@ -175,10 +246,19 @@ export const sliceEntitiesForDashboard = { form_data: {}, viz_type: 'box_plot', datasource: '2__table', - description: null, - description_markeddown: '', + description: '', + description_markdown: '', modified: '23 hours ago', changed_on: 1529453332688, + changed_on_humanized: '', + + datasource_id: 0, + datasource_type: DatasourceType.Table, + datasource_url: '', + datasource_name: '', + owners: [{ id: 0 }], + created_by: { id: 0 }, + thumbnail_url: '', }, 136: { slice_id: 136, @@ -187,10 +267,19 @@ export const sliceEntitiesForDashboard = { form_data: {}, viz_type: 'treemap_v2', datasource: '2__table', - description: null, - description_markeddown: '', + description: '', + description_markdown: '', modified: '23 hours ago', changed_on: 1529453332700, + changed_on_humanized: '', + + datasource_id: 0, + datasource_type: DatasourceType.Table, + datasource_url: '', + datasource_name: '', + owners: [{ id: 0 }], + created_by: { id: 0 }, + thumbnail_url: '', }, }, isLoading: false, diff --git a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx index ec77f08242010..d522d73d90203 100644 --- a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx +++ b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx @@ -127,7 +127,7 @@ describe('ShareSqlLabQuery', () => { const storeQuerySpy = jest.spyOn(utils, 'storeQuery'); userEvent.click(button); expect(storeQuerySpy.mock.calls).toHaveLength(1); - expect(storeQuerySpy).toBeCalledWith(expected); + expect(storeQuerySpy).toHaveBeenCalledWith(expected); storeQuerySpy.mockRestore(); }); @@ -142,7 +142,7 @@ describe('ShareSqlLabQuery', () => { const storeQuerySpy = jest.spyOn(utils, 'storeQuery'); userEvent.click(button); expect(storeQuerySpy.mock.calls).toHaveLength(1); - expect(storeQuerySpy).toBeCalledWith(expected); + expect(storeQuerySpy).toHaveBeenCalledWith(expected); storeQuerySpy.mockRestore(); }); }); diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx index 731053ac0b0b0..cab82cd02f5c2 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx +++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx @@ -56,7 +56,8 @@ import Mousetrap from 'mousetrap'; import Button from 'src/components/Button'; import Timer from 'src/components/Timer'; import ResizableSidebar from 'src/components/ResizableSidebar'; -import { AntdDropdown, AntdSwitch, Skeleton } from 'src/components'; +import { AntdDropdown, Skeleton } from 'src/components'; +import { Switch } from 'src/components/Switch'; import { Input } from 'src/components/Input'; import { Menu } from 'src/components/Menu'; import Icons from 'src/components/Icons'; @@ -698,7 +699,7 @@ const SqlEditor: FC = ({ {' '} {t('Render HTML')}{' '} - {' '} @@ -706,7 +707,7 @@ const SqlEditor: FC = ({ {' '} {t('Autocomplete')}{' '} - {' '} diff --git a/superset-frontend/src/components/Card/index.tsx b/superset-frontend/src/components/Card/index.tsx index 71acde079d016..855f50c273f51 100644 --- a/superset-frontend/src/components/Card/index.tsx +++ b/superset-frontend/src/components/Card/index.tsx @@ -28,6 +28,8 @@ const Card = ({ padded, ...props }: CardProps) => ( ({ + // 'border-radius': `${theme.gridUnit}px`, + border: `1px solid ${theme.colors.grayscale.light2}`, '.antd5-card-body': { padding: padded ? theme.gridUnit * 4 : theme.gridUnit, }, @@ -35,4 +37,6 @@ const Card = ({ padded, ...props }: CardProps) => ( /> ); -export default Card; +export default Object.assign(Card, { + Meta: AntdCard.Meta, +}); diff --git a/superset-frontend/src/components/Chart/Chart.tsx b/superset-frontend/src/components/Chart/Chart.tsx index 7c90bb5ba5c3a..3526a26b3f9ce 100644 --- a/superset-frontend/src/components/Chart/Chart.tsx +++ b/superset-frontend/src/components/Chart/Chart.tsx @@ -133,7 +133,6 @@ const defaultProps: Partial = { const Styles = styled.div<{ height: number; width?: number }>` min-height: ${p => p.height}px; position: relative; - text-align: center; .chart-tooltip { opacity: 0.75; @@ -167,6 +166,7 @@ const LoadingDiv = styled.div` const MessageSpan = styled.span` display: block; + text-align: center; margin: ${({ theme }) => theme.gridUnit * 4}px auto; width: fit-content; color: ${({ theme }) => theme.colors.grayscale.base}; diff --git a/superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx b/superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx index 9df0e73bc9e6c..e5a94ba97f61f 100644 --- a/superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx +++ b/superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx @@ -39,7 +39,6 @@ import { useTheme, } from '@superset-ui/core'; import { RootState } from 'src/dashboard/types'; -import { findPermission } from 'src/utils/findPermission'; import { Menu } from 'src/components/Menu'; import { AntdDropdown as Dropdown } from 'src/components/index'; import { updateDataMask } from 'src/dataMask/actions'; @@ -47,6 +46,7 @@ import { DrillDetailMenuItems } from '../DrillDetail'; import { getMenuAdjustedY } from '../utils'; import { MenuItemTooltip } from '../DisabledMenuItemTooltip'; import { DrillByMenuItems } from '../DrillBy/DrillByMenuItems'; +import { usePermissions } from './usePermissions'; export enum ContextMenuItem { CrossFilter, @@ -88,23 +88,8 @@ const ChartContextMenu = ( ) => { const theme = useTheme(); const dispatch = useDispatch(); - const canExplore = useSelector((state: RootState) => - findPermission('can_explore', 'Superset', state.user?.roles), - ); - const canWriteExploreFormData = useSelector((state: RootState) => - findPermission('can_write', 'ExploreFormDataRestApi', state.user?.roles), - ); - const canDatasourceSamples = useSelector((state: RootState) => - findPermission('can_samples', 'Datasource', state.user?.roles), - ); - const canDownload = useSelector((state: RootState) => - findPermission('can_csv', 'Superset', state.user?.roles), - ); - const canDrill = useSelector((state: RootState) => - findPermission('can_drill', 'Dashboard', state.user?.roles), - ); - const canDrillBy = (canExplore || canDrill) && canWriteExploreFormData; - const canDrillToDetail = (canExplore || canDrill) && canDatasourceSamples; + const { canDrillToDetail, canDrillBy, canDownload } = usePermissions(); + const crossFiltersEnabled = useSelector( ({ dashboardInfo }) => dashboardInfo.crossFiltersEnabled, ); diff --git a/superset-frontend/src/components/Chart/ChartContextMenu/usePermissions.ts b/superset-frontend/src/components/Chart/ChartContextMenu/usePermissions.ts new file mode 100644 index 0000000000000..ef45cdf0b4a2f --- /dev/null +++ b/superset-frontend/src/components/Chart/ChartContextMenu/usePermissions.ts @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { useSelector } from 'react-redux'; +import { RootState } from 'src/dashboard/types'; +import { findPermission } from 'src/utils/findPermission'; + +export const usePermissions = () => { + const canExplore = useSelector((state: RootState) => + findPermission('can_explore', 'Superset', state.user?.roles), + ); + const canWriteExploreFormData = useSelector((state: RootState) => + findPermission('can_write', 'ExploreFormDataRestApi', state.user?.roles), + ); + const canDatasourceSamples = useSelector((state: RootState) => + findPermission('can_samples', 'Datasource', state.user?.roles), + ); + const canDownload = useSelector((state: RootState) => + findPermission('can_csv', 'Superset', state.user?.roles), + ); + const canDrill = useSelector((state: RootState) => + findPermission('can_drill', 'Dashboard', state.user?.roles), + ); + const canDrillBy = (canExplore || canDrill) && canWriteExploreFormData; + const canDrillToDetail = (canExplore || canDrill) && canDatasourceSamples; + + return { + canExplore, + canWriteExploreFormData, + canDatasourceSamples, + canDownload, + canDrill, + canDrillBy, + canDrillToDetail, + }; +}; diff --git a/superset-frontend/src/components/Chart/ChartRenderer.jsx b/superset-frontend/src/components/Chart/ChartRenderer.jsx index b9cd6caf4fb94..df228104cb382 100644 --- a/superset-frontend/src/components/Chart/ChartRenderer.jsx +++ b/superset-frontend/src/components/Chart/ChartRenderer.jsx @@ -84,9 +84,13 @@ const defaultProps = { class ChartRenderer extends Component { constructor(props) { super(props); + const suppressContextMenu = getChartMetadataRegistry().get( + props.formData.viz_type ?? props.vizType, + )?.suppressContextMenu; this.state = { showContextMenu: props.source === ChartSource.Dashboard && + !suppressContextMenu && (isFeatureEnabled(FeatureFlag.DrillToDetail) || isFeatureEnabled(FeatureFlag.DashboardCrossFilters)), inContextMenu: false, diff --git a/superset-frontend/src/components/Chart/ChartRenderer.test.jsx b/superset-frontend/src/components/Chart/ChartRenderer.test.jsx index 53b35b6cf4157..12556eef775f0 100644 --- a/superset-frontend/src/components/Chart/ChartRenderer.test.jsx +++ b/superset-frontend/src/components/Chart/ChartRenderer.test.jsx @@ -17,8 +17,9 @@ * under the License. */ import { render } from 'spec/helpers/testing-library'; - +import { ChartMetadata, getChartMetadataRegistry } from '@superset-ui/core'; import ChartRenderer from 'src/components/Chart/ChartRenderer'; +import { ChartSource } from 'src/types/ChartSource'; jest.mock('@superset-ui/core', () => ({ ...jest.requireActual('@superset-ui/core'), @@ -40,8 +41,16 @@ const requiredProps = { testControl: 'bar', }, vizType: 'table', + source: ChartSource.Dashboard, }; +beforeAll(() => { + window.featureFlags = { DRILL_TO_DETAIL: true }; +}); +afterAll(() => { + window.featureFlags = {}; +}); + test('should render SuperChart', () => { const { getByTestId } = render( , @@ -57,3 +66,24 @@ test('should use latestQueryFormData instead of formData when chartIsStale is tr JSON.stringify({ testControl: 'bar' }), ); }); + +test('should render chart context menu', () => { + const { getByTestId } = render(); + expect(getByTestId('mock-chart-context-menu')).toBeInTheDocument(); +}); + +test('should not render chart context menu if the context menu is suppressed for given viz plugin', () => { + getChartMetadataRegistry().registerValue( + 'chart_without_context_menu', + new ChartMetadata({ + name: 'chart with suppressed context menu', + thumbnail: '.png', + useLegacyApi: false, + suppressContextMenu: true, + }), + ); + const { queryByTestId } = render( + , + ); + expect(queryByTestId('mock-chart-context-menu')).not.toBeInTheDocument(); +}); diff --git a/superset-frontend/src/components/CronPicker/CronPicker.test.tsx b/superset-frontend/src/components/CronPicker/CronPicker.test.tsx index 9eef6f21f459b..48203a2dc8863 100644 --- a/superset-frontend/src/components/CronPicker/CronPicker.test.tsx +++ b/superset-frontend/src/components/CronPicker/CronPicker.test.tsx @@ -28,7 +28,7 @@ test('Should send correct props to ReactCronPicker', () => { myCustomProp: 'myCustomProp', }; render(); - expect(spy).toBeCalledWith( + expect(spy).toHaveBeenCalledWith( expect.objectContaining({ className: expect.any(String), locale: expect.anything(), diff --git a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx index aa9cac748b06f..44d0bff0e04bd 100644 --- a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx +++ b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx @@ -219,9 +219,9 @@ test('Refresh should work', async () => { await waitFor(() => { expect(fetchMock.calls(databaseApiRoute).length).toBe(1); expect(fetchMock.calls(schemaApiRoute).length).toBe(1); - expect(props.handleError).toBeCalledTimes(0); - expect(props.onDbChange).toBeCalledTimes(0); - expect(props.onSchemaChange).toBeCalledTimes(0); + expect(props.handleError).toHaveBeenCalledTimes(0); + expect(props.onDbChange).toHaveBeenCalledTimes(0); + expect(props.onSchemaChange).toHaveBeenCalledTimes(0); }); // click schema reload @@ -230,9 +230,9 @@ test('Refresh should work', async () => { await waitFor(() => { expect(fetchMock.calls(databaseApiRoute).length).toBe(1); expect(fetchMock.calls(schemaApiRoute).length).toBe(2); - expect(props.handleError).toBeCalledTimes(0); - expect(props.onDbChange).toBeCalledTimes(0); - expect(props.onSchemaChange).toBeCalledTimes(0); + expect(props.handleError).toHaveBeenCalledTimes(0); + expect(props.onDbChange).toHaveBeenCalledTimes(0); + expect(props.onSchemaChange).toHaveBeenCalledTimes(0); }); }); diff --git a/superset-frontend/src/components/Datasource/DatasourceEditor.jsx b/superset-frontend/src/components/Datasource/DatasourceEditor.jsx index 3fa99f34f83cc..d30b67ad2a751 100644 --- a/superset-frontend/src/components/Datasource/DatasourceEditor.jsx +++ b/superset-frontend/src/components/Datasource/DatasourceEditor.jsx @@ -895,7 +895,8 @@ class DatasourceEditor extends PureComponent { fieldKey="default_endpoint" label={t('Default URL')} description={t( - 'Default URL to redirect to when accessing from the dataset list page', + `Default URL to redirect to when accessing from the dataset list page. + Accepts relative URLs such as /superset/dashboard/{id}/`, )} control={} /> diff --git a/superset-frontend/src/components/DeleteModal/DeleteModal.test.tsx b/superset-frontend/src/components/DeleteModal/DeleteModal.test.tsx index ae966f48ed263..7e9b3c439ebba 100644 --- a/superset-frontend/src/components/DeleteModal/DeleteModal.test.tsx +++ b/superset-frontend/src/components/DeleteModal/DeleteModal.test.tsx @@ -45,8 +45,8 @@ test('Calling "onHide"', () => { }; const modal = ; render(modal); - expect(props.onHide).toBeCalledTimes(0); - expect(props.onConfirm).toBeCalledTimes(0); + expect(props.onHide).toHaveBeenCalledTimes(0); + expect(props.onConfirm).toHaveBeenCalledTimes(0); // type "del" in the input userEvent.type(screen.getByTestId('delete-modal-input'), 'del'); @@ -55,8 +55,8 @@ test('Calling "onHide"', () => { // close the modal expect(screen.getByText('×')).toBeVisible(); userEvent.click(screen.getByText('×')); - expect(props.onHide).toBeCalledTimes(1); - expect(props.onConfirm).toBeCalledTimes(0); + expect(props.onHide).toHaveBeenCalledTimes(1); + expect(props.onConfirm).toHaveBeenCalledTimes(0); // confirm input has been cleared expect(screen.getByTestId('delete-modal-input')).toHaveValue(''); @@ -71,19 +71,19 @@ test('Calling "onConfirm" only after typing "delete" in the input', () => { open: true, }; render(); - expect(props.onHide).toBeCalledTimes(0); - expect(props.onConfirm).toBeCalledTimes(0); + expect(props.onHide).toHaveBeenCalledTimes(0); + expect(props.onConfirm).toHaveBeenCalledTimes(0); expect(screen.getByTestId('delete-modal-input')).toBeVisible(); - expect(props.onConfirm).toBeCalledTimes(0); + expect(props.onConfirm).toHaveBeenCalledTimes(0); // do not execute "onConfirm" if you have not typed "delete" userEvent.click(screen.getByText('Delete')); - expect(props.onConfirm).toBeCalledTimes(0); + expect(props.onConfirm).toHaveBeenCalledTimes(0); // execute "onConfirm" if you have typed "delete" userEvent.type(screen.getByTestId('delete-modal-input'), 'delete'); userEvent.click(screen.getByText('Delete')); - expect(props.onConfirm).toBeCalledTimes(1); + expect(props.onConfirm).toHaveBeenCalledTimes(1); // confirm input has been cleared expect(screen.getByTestId('delete-modal-input')).toHaveValue(''); diff --git a/superset-frontend/src/components/FaveStar/FaveStar.test.tsx b/superset-frontend/src/components/FaveStar/FaveStar.test.tsx index 028edde2e4e57..9bccc4b7c9833 100644 --- a/superset-frontend/src/components/FaveStar/FaveStar.test.tsx +++ b/superset-frontend/src/components/FaveStar/FaveStar.test.tsx @@ -37,20 +37,20 @@ test('render right content', async () => { screen.getByRole('img', { name: 'favorite-selected' }), ).toBeInTheDocument(); - expect(props.saveFaveStar).toBeCalledTimes(0); + expect(props.saveFaveStar).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button')); - expect(props.saveFaveStar).toBeCalledTimes(1); - expect(props.saveFaveStar).toBeCalledWith(props.itemId, true); + expect(props.saveFaveStar).toHaveBeenCalledTimes(1); + expect(props.saveFaveStar).toHaveBeenCalledWith(props.itemId, true); rerender(); expect( await findByRole('img', { name: 'favorite-unselected' }), ).toBeInTheDocument(); - expect(props.saveFaveStar).toBeCalledTimes(1); + expect(props.saveFaveStar).toHaveBeenCalledTimes(1); userEvent.click(screen.getByRole('button')); - expect(props.saveFaveStar).toBeCalledTimes(2); - expect(props.saveFaveStar).toBeCalledWith(props.itemId, false); + expect(props.saveFaveStar).toHaveBeenCalledTimes(2); + expect(props.saveFaveStar).toHaveBeenCalledWith(props.itemId, false); }); test('render content on tooltip', async () => { @@ -87,9 +87,9 @@ test('Call fetchFaveStar on first render and on itemId change', async () => { expect( await findByRole('img', { name: 'favorite-unselected' }), ).toBeInTheDocument(); - expect(props.fetchFaveStar).toBeCalledTimes(1); - expect(props.fetchFaveStar).toBeCalledWith(props.itemId); + expect(props.fetchFaveStar).toHaveBeenCalledTimes(1); + expect(props.fetchFaveStar).toHaveBeenCalledWith(props.itemId); rerender(); - expect(props.fetchFaveStar).toBeCalledTimes(2); + expect(props.fetchFaveStar).toHaveBeenCalledTimes(2); }); diff --git a/superset-frontend/src/components/ListView/ListView.test.tsx b/superset-frontend/src/components/ListView/ListView.test.tsx index ad76ad8c7a6cf..dd5b6de2a3241 100644 --- a/superset-frontend/src/components/ListView/ListView.test.tsx +++ b/superset-frontend/src/components/ListView/ListView.test.tsx @@ -61,7 +61,7 @@ test('redirects to first page when page index is invalid', async () => { }); await waitFor(() => { expect(window.location.search).toEqual('?pageIndex=0'); - expect(fetchData).toBeCalledTimes(2); + expect(fetchData).toHaveBeenCalledTimes(2); expect(fetchData).toHaveBeenCalledWith( expect.objectContaining({ pageIndex: 9 }), ); diff --git a/superset-frontend/src/components/ListViewCard/index.tsx b/superset-frontend/src/components/ListViewCard/index.tsx index ae026495d29d3..8d897d5bd32c0 100644 --- a/superset-frontend/src/components/ListViewCard/index.tsx +++ b/superset-frontend/src/components/ListViewCard/index.tsx @@ -18,8 +18,10 @@ */ import { ReactNode, ComponentType, ReactElement, FC } from 'react'; import { styled, useTheme } from '@superset-ui/core'; -import { Skeleton, AntdCard } from 'src/components'; +import { Skeleton, Card } from 'src/components'; import { Tooltip } from 'src/components/Tooltip'; +import { theme as supersetTheme } from 'src/preamble'; +import { ConfigProvider } from 'antd-v5'; import ImageLoader, { BackgroundPosition } from './ImageLoader'; import CertifiedBadge from '../CertifiedBadge'; @@ -29,19 +31,20 @@ const ActionsWrapper = styled.div` justify-content: flex-end; `; -const StyledCard = styled(AntdCard)` +// Styling part 1: Override Card tokens when possible +const listViewCardTheme = { + components: { + Card: { + colorBgContainer: supersetTheme.colors.grayscale.light5, + }, + }, +}; + +// Styling part 2: Use CSS when necessary +const StyledCard = styled(Card)` ${({ theme }) => ` - border: 1px solid ${theme.colors.grayscale.light2}; - border-radius: ${theme.gridUnit}px; overflow: hidden; - .ant-card-body { - padding: ${theme.gridUnit * 4}px - ${theme.gridUnit * 2}px; - } - .ant-card-meta-detail > div:not(:last-child) { - margin-bottom: 0; - } .gradient-container { position: relative; height: 100%; @@ -188,98 +191,101 @@ function ListViewCard({ const Link = url && linkComponent ? linkComponent : AnchorLink; const theme = useTheme(); return ( - - -
- -
- - - {!loading && coverLeft && ( - {coverLeft} - )} - {!loading && coverRight && ( - {coverRight} - )} - - - ) - } - > - {loading && ( - - - -
- {' '} - + + +
+ +
+ + + {!loading && coverLeft && ( + {coverLeft} + )} + {!loading && coverRight && ( + {coverRight} + )} + + + ) + } + > + {loading && ( + + + +
+ {' '} + +
+
+ + } + description={ + + } + /> + )} + {!loading && ( + + {subtitle || null} +
+ + + {certifiedBy && ( + <> + {' '} + + )} + {title} + + + {titleRight && {titleRight}} +
+ {actions} +
- - } - description={ - - } - /> - )} - {!loading && ( - - {subtitle || null} -
- - - {certifiedBy && ( - <> - {' '} - - )} - {title} - - - {titleRight && {titleRight}} -
- {actions} -
-
- - } - description={description} - avatar={avatar || null} - /> - )} -
+ } + description={description} + avatar={avatar || null} + /> + )} + + ); } diff --git a/superset-frontend/src/components/Pagination/Ellipsis.test.tsx b/superset-frontend/src/components/Pagination/Ellipsis.test.tsx index 81c7301fa9ead..1caf0ae555a82 100644 --- a/superset-frontend/src/components/Pagination/Ellipsis.test.tsx +++ b/superset-frontend/src/components/Pagination/Ellipsis.test.tsx @@ -24,15 +24,15 @@ import { Ellipsis } from './Ellipsis'; test('Ellipsis - click when the button is enabled', () => { const click = jest.fn(); render(); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button')); - expect(click).toBeCalledTimes(1); + expect(click).toHaveBeenCalledTimes(1); }); test('Ellipsis - click when the button is disabled', () => { const click = jest.fn(); render(); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button')); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); }); diff --git a/superset-frontend/src/components/Pagination/Item.test.tsx b/superset-frontend/src/components/Pagination/Item.test.tsx index 08622f9def6cd..096053656e0db 100644 --- a/superset-frontend/src/components/Pagination/Item.test.tsx +++ b/superset-frontend/src/components/Pagination/Item.test.tsx @@ -28,9 +28,9 @@ test('Item - click when the item is not active', () => {
, ); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button')); - expect(click).toBeCalledTimes(1); + expect(click).toHaveBeenCalledTimes(1); expect(screen.getByTestId('test')).toBeInTheDocument(); }); @@ -41,8 +41,8 @@ test('Item - click when the item is active', () => {
, ); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button')); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); expect(screen.getByTestId('test')).toBeInTheDocument(); }); diff --git a/superset-frontend/src/components/Pagination/Next.test.tsx b/superset-frontend/src/components/Pagination/Next.test.tsx index bf675749cdea1..b50efb2da6ff0 100644 --- a/superset-frontend/src/components/Pagination/Next.test.tsx +++ b/superset-frontend/src/components/Pagination/Next.test.tsx @@ -24,15 +24,15 @@ import { Next } from './Next'; test('Next - click when the button is enabled', () => { const click = jest.fn(); render(); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button')); - expect(click).toBeCalledTimes(1); + expect(click).toHaveBeenCalledTimes(1); }); test('Next - click when the button is disabled', () => { const click = jest.fn(); render(); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button')); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); }); diff --git a/superset-frontend/src/components/Pagination/Prev.test.tsx b/superset-frontend/src/components/Pagination/Prev.test.tsx index e414fa48a84e5..8339a57e6ccd1 100644 --- a/superset-frontend/src/components/Pagination/Prev.test.tsx +++ b/superset-frontend/src/components/Pagination/Prev.test.tsx @@ -24,15 +24,15 @@ import { Prev } from './Prev'; test('Prev - click when the button is enabled', () => { const click = jest.fn(); render(); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button')); - expect(click).toBeCalledTimes(1); + expect(click).toHaveBeenCalledTimes(1); }); test('Prev - click when the button is disabled', () => { const click = jest.fn(); render(); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button')); - expect(click).toBeCalledTimes(0); + expect(click).toHaveBeenCalledTimes(0); }); diff --git a/superset-frontend/src/components/Select/Select.tsx b/superset-frontend/src/components/Select/Select.tsx index bebb788879794..91f9515448dc2 100644 --- a/superset-frontend/src/components/Select/Select.tsx +++ b/superset-frontend/src/components/Select/Select.tsx @@ -608,8 +608,9 @@ const Select = forwardRef( {header} )} { /> ); }; +const defaultCheckedValue = true; InteractiveSwitch.args = { - checked: false, + checked: defaultCheckedValue, disabled: false, loading: false, title: 'Switch', + defaultChecked: defaultCheckedValue, + autoFocus: true, }; InteractiveSwitch.argTypes = { diff --git a/superset-frontend/src/components/Switch/Switch.test.tsx b/superset-frontend/src/components/Switch/Switch.test.tsx new file mode 100644 index 0000000000000..0e8e762d041ea --- /dev/null +++ b/superset-frontend/src/components/Switch/Switch.test.tsx @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { render, screen } from 'spec/helpers/testing-library'; +import { Switch } from '.'; + +const mockedProps = { + label: 'testLabel', + dataTest: 'dataTest', + checked: false, +}; + +test('should render', () => { + const { container } = render(); + expect(container).toBeInTheDocument(); +}); + +test('should have the correct checked prop', () => { + render(); + + const switchElement = screen.getByRole('switch'); + + expect(switchElement).toBeInTheDocument(); + expect(switchElement).not.toBeChecked(); +}); diff --git a/superset-frontend/src/components/Switch/index.tsx b/superset-frontend/src/components/Switch/index.tsx index 875b66f5871aa..b4d89e8505790 100644 --- a/superset-frontend/src/components/Switch/index.tsx +++ b/superset-frontend/src/components/Switch/index.tsx @@ -16,14 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { styled } from '@superset-ui/core'; -import BaseSwitch, { SwitchProps } from 'antd/lib/switch'; +import { SwitchProps } from 'antd-v5/lib/switch'; +import { Switch as AntdSwitch } from 'antd-v5'; -const StyledSwitch = styled(BaseSwitch)` - .ant-switch-checked { - background-color: ${({ theme }) => theme.colors.primary.base}; - } -`; - -export const Switch = (props: SwitchProps) => ; +export const Switch = (props: SwitchProps) => ; export type { SwitchProps }; diff --git a/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx b/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx index f30eeb2d52219..edb71341f240b 100644 --- a/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx +++ b/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.DaylightSavingTime.test.tsx @@ -35,10 +35,13 @@ const loadComponent = (mockCurrentTime?: string) => { return new Promise>(resolve => { const { default: TimezoneSelector } = module.require('./index'); resolve(TimezoneSelector); - jest.useRealTimers(); }); }; +afterEach(() => { + jest.useRealTimers(); +}); + test('render timezones in correct order for daylight saving time', async () => { const TimezoneSelector = await loadComponent('2022-07-01'); const onTimezoneChange = jest.fn(); diff --git a/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.test.tsx b/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.test.tsx index cc422ba85e4b8..5083b6bcd0a60 100644 --- a/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.test.tsx +++ b/superset-frontend/src/components/TimezoneSelector/TimezoneSelector.test.tsx @@ -35,7 +35,6 @@ const loadComponent = (mockCurrentTime?: string) => { return new Promise>(resolve => { const { default: TimezoneSelector } = module.require('./index'); resolve(TimezoneSelector); - jest.useRealTimers(); }); }; @@ -49,6 +48,10 @@ const openSelectMenu = () => { jest.spyOn(moment.tz, 'guess').mockReturnValue('America/New_York'); +afterEach(() => { + jest.useRealTimers(); +}); + test('use the timezone from `moment` if no timezone provided', async () => { const TimezoneSelector = await loadComponent('2022-01-01'); const onTimezoneChange = jest.fn(); @@ -96,10 +99,9 @@ test('render timezones in correct order for standard time', async () => { await waitForElementToBeRemoved(() => screen.queryByLabelText('Loading')); openSelectMenu(); const options = await getSelectOptions(); - expect(options[0]).toHaveTextContent('GMT -04:00 (Eastern Daylight Time)'); + expect(options[0]).toHaveTextContent('GMT -05:00 (Eastern Standard Time)'); expect(options[1]).toHaveTextContent('GMT -11:00 (Pacific/Pago_Pago)'); expect(options[2]).toHaveTextContent('GMT -10:00 (Hawaii Standard Time)'); - expect(options[3]).toHaveTextContent('GMT -09:30 (Pacific/Marquesas)'); }); test('can select a timezone values and returns canonical timezone name', async () => { @@ -116,8 +118,8 @@ test('can select a timezone values and returns canonical timezone name', async ( const searchInput = screen.getByRole('combobox'); // search for mountain time - await userEvent.type(searchInput, 'mou', { delay: 10 }); - const findTitle = 'GMT -06:00 (Mountain Daylight Time)'; + await userEvent.type(searchInput, 'mou'); + const findTitle = 'GMT -07:00 (Mountain Standard Time)'; const selectOption = await screen.findByTitle(findTitle); userEvent.click(selectOption); expect(onTimezoneChange).toHaveBeenCalledTimes(1); diff --git a/superset-frontend/src/components/index.ts b/superset-frontend/src/components/index.ts index 16b6138c18775..d06d3274f4a16 100644 --- a/superset-frontend/src/components/index.ts +++ b/superset-frontend/src/components/index.ts @@ -25,7 +25,7 @@ export { default as Select } from './Select/Select'; export { default as AsyncSelect } from './Select/AsyncSelect'; export { default as Button } from './Button'; - +export { default as Card } from './Card'; /* * Components that don't conflict with the ones in src/components. * As Superset progresses to support full theming, this list should @@ -57,7 +57,7 @@ export { * or extending the components in src/components. */ export { - Breadcrumb as AntdBreadcrumb, + Breadcrumb as AntdBreadcrumb, // TODO: Make this a real Component Card as AntdCard, Checkbox as AntdCheckbox, Collapse as AntdCollapse, @@ -67,7 +67,6 @@ export { Modal as AntdModal, Select as AntdSelect, Slider as AntdSlider, - Switch as AntdSwitch, Tabs as AntdTabs, Tooltip as AntdTooltip, } from 'antd'; diff --git a/superset-frontend/src/constants.ts b/superset-frontend/src/constants.ts index b7d34ad738694..c4fd0e94f9c3f 100644 --- a/superset-frontend/src/constants.ts +++ b/superset-frontend/src/constants.ts @@ -148,7 +148,7 @@ export const DEFAULT_COMMON_BOOTSTRAP_DATA: CommonBootstrapData = { locale: 'en', feature_flags: {}, language_pack: { - domain: '', + domain: 'superset', locale_data: { superset: { '': { diff --git a/superset-frontend/src/dashboard/actions/dashboardInfo.ts b/superset-frontend/src/dashboard/actions/dashboardInfo.ts index 14659b9fc33eb..ea25e8c715c89 100644 --- a/superset-frontend/src/dashboard/actions/dashboardInfo.ts +++ b/superset-frontend/src/dashboard/actions/dashboardInfo.ts @@ -29,11 +29,17 @@ import { import { onSave } from './dashboardState'; export const DASHBOARD_INFO_UPDATED = 'DASHBOARD_INFO_UPDATED'; +export const DASHBOARD_INFO_FILTERS_CHANGED = 'DASHBOARD_INFO_FILTERS_CHANGED'; // updates partially changed dashboard info export function dashboardInfoChanged(newInfo: { metadata: any }) { return { type: DASHBOARD_INFO_UPDATED, newInfo }; } + +export function nativeFiltersConfigChanged(newInfo: Record) { + return { type: DASHBOARD_INFO_FILTERS_CHANGED, newInfo }; +} + export const SAVE_CHART_CONFIG_BEGIN = 'SAVE_CHART_CONFIG_BEGIN'; export const SAVE_CHART_CONFIG_COMPLETE = 'SAVE_CHART_CONFIG_COMPLETE'; export const SAVE_CHART_CONFIG_FAIL = 'SAVE_CHART_CONFIG_FAIL'; diff --git a/superset-frontend/src/dashboard/actions/dashboardState.js b/superset-frontend/src/dashboard/actions/dashboardState.js index 945dda32a319f..d9d095dfb7b2f 100644 --- a/superset-frontend/src/dashboard/actions/dashboardState.js +++ b/superset-frontend/src/dashboard/actions/dashboardState.js @@ -63,7 +63,7 @@ import { } from './dashboardInfo'; import { fetchDatasourceMetadata, setDatasources } from './datasources'; import { updateDirectPathToFilter } from './dashboardFilters'; -import { SET_FILTER_CONFIG_COMPLETE } from './nativeFilters'; +import { SET_IN_SCOPE_STATUS_OF_FILTERS } from './nativeFilters'; import getOverwriteItems from '../util/getOverwriteItems'; import { applyColors, @@ -337,7 +337,7 @@ export function saveDashboardRequest(data, id, saveType) { } if (metadata.native_filter_configuration) { dispatch({ - type: SET_FILTER_CONFIG_COMPLETE, + type: SET_IN_SCOPE_STATUS_OF_FILTERS, filterConfig: metadata.native_filter_configuration, }); } diff --git a/superset-frontend/src/dashboard/actions/nativeFilters.ts b/superset-frontend/src/dashboard/actions/nativeFilters.ts index 968805dbb7605..9ec73af425651 100644 --- a/superset-frontend/src/dashboard/actions/nativeFilters.ts +++ b/superset-frontend/src/dashboard/actions/nativeFilters.ts @@ -16,31 +16,39 @@ * specific language governing permissions and limitations * under the License. */ -import { FilterConfiguration, Filters, makeApi } from '@superset-ui/core'; +import { + Filter, + FilterConfiguration, + Filters, + makeApi, +} from '@superset-ui/core'; import { Dispatch } from 'redux'; import { cloneDeep } from 'lodash'; -import { - SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL, - setDataMaskForFilterConfigComplete, -} from 'src/dataMask/actions'; +import { setDataMaskForFilterChangesComplete } from 'src/dataMask/actions'; import { HYDRATE_DASHBOARD } from './hydrate'; -import { dashboardInfoChanged } from './dashboardInfo'; -import { DashboardInfo } from '../types'; +import { + dashboardInfoChanged, + nativeFiltersConfigChanged, +} from './dashboardInfo'; +import { SaveFilterChangesType } from '../components/nativeFilters/FiltersConfigModal/types'; -export const SET_FILTER_CONFIG_BEGIN = 'SET_FILTER_CONFIG_BEGIN'; -export interface SetFilterConfigBegin { - type: typeof SET_FILTER_CONFIG_BEGIN; +export const SET_NATIVE_FILTERS_CONFIG_BEGIN = + 'SET_NATIVE_FILTERS_CONFIG_BEGIN'; +export interface SetNativeFiltersConfigBegin { + type: typeof SET_NATIVE_FILTERS_CONFIG_BEGIN; filterConfig: FilterConfiguration; } -export const SET_FILTER_CONFIG_COMPLETE = 'SET_FILTER_CONFIG_COMPLETE'; -export interface SetFilterConfigComplete { - type: typeof SET_FILTER_CONFIG_COMPLETE; - filterConfig: FilterConfiguration; +export const SET_NATIVE_FILTERS_CONFIG_COMPLETE = + 'SET_NATIVE_FILTERS_CONFIG_COMPLETE'; +export interface SetNativeFiltersConfigComplete { + type: typeof SET_NATIVE_FILTERS_CONFIG_COMPLETE; + filterChanges: Filter[]; } -export const SET_FILTER_CONFIG_FAIL = 'SET_FILTER_CONFIG_FAIL'; -export interface SetFilterConfigFail { - type: typeof SET_FILTER_CONFIG_FAIL; + +export const SET_NATIVE_FILTERS_CONFIG_FAIL = 'SET_NATIVE_FILTERS_CONFIG_FAIL'; +export interface SetNativeFiltersConfigFail { + type: typeof SET_NATIVE_FILTERS_CONFIG_FAIL; filterConfig: FilterConfiguration; } export const SET_IN_SCOPE_STATUS_OF_FILTERS = 'SET_IN_SCOPE_STATUS_OF_FILTERS'; @@ -49,60 +57,45 @@ export interface SetInScopeStatusOfFilters { filterConfig: FilterConfiguration; } +const isFilterChangesEmpty = (filterChanges: SaveFilterChangesType) => + Object.values(filterChanges).every( + array => Array.isArray(array) && !array.length, + ); + export const setFilterConfiguration = - (filterConfig: FilterConfiguration) => + (filterChanges: SaveFilterChangesType) => async (dispatch: Dispatch, getState: () => any) => { + if (isFilterChangesEmpty(filterChanges)) { + return; + } + + const { id } = getState().dashboardInfo; + const oldFilters = getState().nativeFilters?.filters; + dispatch({ - type: SET_FILTER_CONFIG_BEGIN, - filterConfig, + type: SET_NATIVE_FILTERS_CONFIG_BEGIN, + filterChanges, }); - const { id, metadata } = getState().dashboardInfo; - const oldFilters = getState().nativeFilters?.filters; - // TODO extract this out when makeApi supports url parameters - const updateDashboard = makeApi< - Partial, - { result: DashboardInfo } + const updateFilters = makeApi< + SaveFilterChangesType, + { result: SaveFilterChangesType } >({ method: 'PUT', - endpoint: `/api/v1/dashboard/${id}`, + endpoint: `/api/v1/dashboard/${id}/filters`, }); - - const mergedFilterConfig = filterConfig.map(filter => { - const oldFilter = oldFilters[filter.id]; - if (!oldFilter) { - return filter; - } - return { ...oldFilter, ...filter }; - }); - try { - const response = await updateDashboard({ - json_metadata: JSON.stringify({ - ...metadata, - native_filter_configuration: mergedFilterConfig, - }), - }); - dispatch( - dashboardInfoChanged({ - metadata: JSON.parse(response.result.json_metadata), - }), - ); + const response = await updateFilters(filterChanges); + dispatch(nativeFiltersConfigChanged(response.result)); dispatch({ - type: SET_FILTER_CONFIG_COMPLETE, - filterConfig: mergedFilterConfig, + type: SET_NATIVE_FILTERS_CONFIG_COMPLETE, + filterChanges: response.result, }); - dispatch( - setDataMaskForFilterConfigComplete(mergedFilterConfig, oldFilters), - ); + dispatch(setDataMaskForFilterChangesComplete(filterChanges, oldFilters)); } catch (err) { dispatch({ - type: SET_FILTER_CONFIG_FAIL, - filterConfig: mergedFilterConfig, - }); - dispatch({ - type: SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL, - filterConfig: mergedFilterConfig, + type: SET_NATIVE_FILTERS_CONFIG_FAIL, + filterConfig: filterChanges, }); } }; @@ -221,9 +214,9 @@ export function updateCascadeParentIds( } export type AnyFilterAction = - | SetFilterConfigBegin - | SetFilterConfigComplete - | SetFilterConfigFail + | SetNativeFiltersConfigBegin + | SetNativeFiltersConfigComplete + | SetNativeFiltersConfigFail | SetInScopeStatusOfFilters | SetBootstrapData | SetFocusedNativeFilter diff --git a/superset-frontend/src/dashboard/components/Dashboard.jsx b/superset-frontend/src/dashboard/components/Dashboard.jsx index 1953889c5d418..5bdce6d72ecfa 100644 --- a/superset-frontend/src/dashboard/components/Dashboard.jsx +++ b/superset-frontend/src/dashboard/components/Dashboard.jsx @@ -62,6 +62,7 @@ const propTypes = { impressionId: PropTypes.string.isRequired, timeout: PropTypes.number, userId: PropTypes.string, + children: PropTypes.node, }; const defaultProps = { @@ -212,7 +213,7 @@ class Dashboard extends PureComponent { applyFilters() { const { appliedFilters } = this; - const { activeFilters, ownDataCharts, datasources, slices } = this.props; + const { activeFilters, ownDataCharts, slices } = this.props; // refresh charts if a filter was removed, added, or changed @@ -224,6 +225,7 @@ class Dashboard extends PureComponent { ownDataCharts, this.appliedOwnDataCharts, ); + [...allKeys].forEach(filterKey => { if ( !currFilterKeys.includes(filterKey) && @@ -231,22 +233,12 @@ class Dashboard extends PureComponent { ) { // filterKey is removed? affectedChartIds.push( - ...getRelatedCharts( - appliedFilters, - activeFilters, - slices, - datasources, - )[filterKey], + ...getRelatedCharts(filterKey, appliedFilters[filterKey], slices), ); } else if (!appliedFilterKeys.includes(filterKey)) { // filterKey is newly added? affectedChartIds.push( - ...getRelatedCharts( - activeFilters, - appliedFilters, - slices, - datasources, - )[filterKey], + ...getRelatedCharts(filterKey, activeFilters[filterKey], slices), ); } else { // if filterKey changes value, @@ -261,12 +253,7 @@ class Dashboard extends PureComponent { ) ) { affectedChartIds.push( - ...getRelatedCharts( - activeFilters, - appliedFilters, - slices, - datasources, - )[filterKey], + ...getRelatedCharts(filterKey, activeFilters[filterKey], slices), ); } diff --git a/superset-frontend/src/dashboard/components/Dashboard.test.jsx b/superset-frontend/src/dashboard/components/Dashboard.test.jsx index cd76787a21209..e3421ee04057d 100644 --- a/superset-frontend/src/dashboard/components/Dashboard.test.jsx +++ b/superset-frontend/src/dashboard/components/Dashboard.test.jsx @@ -157,9 +157,7 @@ describe('Dashboard', () => { }); it('should call refresh when native filters changed', () => { - getRelatedCharts.mockReturnValue({ - [NATIVE_FILTER_ID]: [230], - }); + getRelatedCharts.mockReturnValue([230]); wrapper.setProps({ activeFilters: { ...OVERRIDE_FILTERS, @@ -191,13 +189,7 @@ describe('Dashboard', () => { }); it('should call refresh if a filter is added', () => { - getRelatedCharts.mockReturnValue({ - '1_region': [1], - '2_country_name': [1, 2], - '3_region': [1], - '3_country_name': [], - gender: [1], - }); + getRelatedCharts.mockReturnValue([1]); const newFilter = { gender: { values: ['boy', 'girl'], scope: [1] }, }; @@ -209,12 +201,7 @@ describe('Dashboard', () => { }); it('should call refresh if a filter is removed', () => { - getRelatedCharts.mockReturnValue({ - '1_region': [1], - '2_country_name': [1, 2], - '3_region': [1], - '3_country_name': [], - }); + getRelatedCharts.mockReturnValue([]); wrapper.setProps({ activeFilters: {}, }); @@ -223,6 +210,7 @@ describe('Dashboard', () => { }); it('should call refresh if a filter is changed', () => { + getRelatedCharts.mockReturnValue([1]); const newFilters = { ...OVERRIDE_FILTERS, '1_region': { values: ['Canada'], scope: [1] }, @@ -236,6 +224,7 @@ describe('Dashboard', () => { }); it('should call refresh with multiple chart ids', () => { + getRelatedCharts.mockReturnValue([1, 2]); const newFilters = { ...OVERRIDE_FILTERS, '2_country_name': { values: ['New Country'], scope: [1, 2] }, @@ -262,6 +251,7 @@ describe('Dashboard', () => { }); it('should call refresh with empty [] if a filter is changed but scope is not applicable', () => { + getRelatedCharts.mockReturnValue([]); const newFilters = { ...OVERRIDE_FILTERS, '3_country_name': { values: ['CHINA'], scope: [] }, diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/DetailsPanel.test.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/DetailsPanel.test.tsx index 6419d9e2ad6d3..460adbd81092f 100644 --- a/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/DetailsPanel.test.tsx +++ b/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/DetailsPanel.test.tsx @@ -123,10 +123,10 @@ test('Should render "appliedCrossFilterIndicators"', async () => { screen.getByRole('button', { name: 'Clinical Stage' }), ).toBeInTheDocument(); - expect(props.onHighlightFilterSource).toBeCalledTimes(0); + expect(props.onHighlightFilterSource).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button', { name: 'Clinical Stage' })); - expect(props.onHighlightFilterSource).toBeCalledTimes(1); - expect(props.onHighlightFilterSource).toBeCalledWith([ + expect(props.onHighlightFilterSource).toHaveBeenCalledTimes(1); + expect(props.onHighlightFilterSource).toHaveBeenCalledWith([ 'ROOT_ID', 'TABS-wUKya7eQ0Z', 'TAB-BCIJF4NvgQ', @@ -153,10 +153,10 @@ test('Should render "appliedIndicators"', async () => { expect(await screen.findByText('Applied filters (1)')).toBeInTheDocument(); expect(screen.getByRole('button', { name: 'Country' })).toBeInTheDocument(); - expect(props.onHighlightFilterSource).toBeCalledTimes(0); + expect(props.onHighlightFilterSource).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button', { name: 'Country' })); - expect(props.onHighlightFilterSource).toBeCalledTimes(1); - expect(props.onHighlightFilterSource).toBeCalledWith([ + expect(props.onHighlightFilterSource).toHaveBeenCalledTimes(1); + expect(props.onHighlightFilterSource).toHaveBeenCalledWith([ 'ROOT_ID', 'TABS-wUKya7eQ0Z', 'TAB-BCIJF4NvgQ', diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/FilterIndicator.test.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/FilterIndicator.test.tsx index 79340f41e72d3..563adfa8b8f69 100644 --- a/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/FilterIndicator.test.tsx +++ b/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/FilterIndicator.test.tsx @@ -51,9 +51,9 @@ test('Should call "onClick"', () => { const props = createProps(); render(); - expect(props.onClick).toBeCalledTimes(0); + expect(props.onClick).toHaveBeenCalledTimes(0); userEvent.click(screen.getByRole('button', { name: 'Vaccine Approach' })); - expect(props.onClick).toBeCalledTimes(1); + expect(props.onClick).toHaveBeenCalledTimes(1); }); test('Should render "value"', () => { diff --git a/superset-frontend/src/dashboard/components/Header/Header.test.tsx b/superset-frontend/src/dashboard/components/Header/Header.test.tsx index 79f9cdf308824..9a2c414d00f7a 100644 --- a/superset-frontend/src/dashboard/components/Header/Header.test.tsx +++ b/superset-frontend/src/dashboard/components/Header/Header.test.tsx @@ -315,10 +315,10 @@ test('should NOT render the fave icon on anonymous user', () => { setup(anonymousUserProps); expect(() => screen.getByRole('img', { name: 'favorite-unselected' }), - ).toThrowError('Unable to find'); - expect(() => - screen.getByRole('img', { name: 'favorite-selected' }), - ).toThrowError('Unable to find'); + ).toThrow('Unable to find'); + expect(() => screen.getByRole('img', { name: 'favorite-selected' })).toThrow( + 'Unable to find', + ); }); test('should fave', async () => { @@ -373,3 +373,48 @@ test('should render an extension component if one is supplied', () => { screen.getByText('dashboard.nav.right extension component'), ).toBeInTheDocument(); }); + +test('should NOT render MetadataBar when in edit mode', () => { + const mockedProps = { + ...createProps(), + editMode: true, + dashboardInfo: { + ...createProps().dashboardInfo, + userId: '123', + }, + }; + setup(mockedProps); + expect( + screen.queryByText(mockedProps.dashboardInfo.changed_on_delta_humanized), + ).not.toBeInTheDocument(); +}); + +test('should NOT render MetadataBar when embedded', () => { + const mockedProps = { + ...createProps(), + editMode: false, + dashboardInfo: { + ...createProps().dashboardInfo, + userId: undefined, + }, + }; + setup(mockedProps); + expect( + screen.queryByText(mockedProps.dashboardInfo.changed_on_delta_humanized), + ).not.toBeInTheDocument(); +}); + +test('should render MetadataBar when not in edit mode and not embedded', () => { + const mockedProps = { + ...createProps(), + editMode: false, + dashboardInfo: { + ...createProps().dashboardInfo, + userId: '123', + }, + }; + setup(mockedProps); + expect( + screen.getByText(mockedProps.dashboardInfo.changed_on_delta_humanized), + ).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx index 3a0d25d600695..c62a1f74fb861 100644 --- a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx +++ b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx @@ -66,9 +66,13 @@ const createProps = (): HeaderDropdownProps => ({ userCanCurate: false, lastModifiedTime: 0, isDropdownVisible: true, + setIsDropdownVisible: jest.fn(), + directPathToChild: [], manageEmbedded: jest.fn(), dataMask: {}, logEvent: jest.fn(), + refreshLimit: 0, + refreshWarning: '', }); const editModeOnProps = { diff --git a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.tsx similarity index 77% rename from superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx rename to superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.tsx index 50cdb67813568..d5ae7aaee2a00 100644 --- a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx +++ b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.tsx @@ -17,7 +17,6 @@ * under the License. */ import { PureComponent } from 'react'; -import PropTypes from 'prop-types'; import { isEmpty } from 'lodash'; import { connect } from 'react-redux'; import { t } from '@superset-ui/core'; @@ -35,73 +34,38 @@ import FilterScopeModal from 'src/dashboard/components/filterscope/FilterScopeMo import getDashboardUrl from 'src/dashboard/util/getDashboardUrl'; import { getActiveFilters } from 'src/dashboard/util/activeDashboardFilters'; import { getUrlParam } from 'src/utils/urlUtils'; -import { MenuKeys } from 'src/dashboard/types'; +import { MenuKeys, RootState } from 'src/dashboard/types'; +import { HeaderDropdownProps } from 'src/dashboard/components/Header/types'; -const propTypes = { - addSuccessToast: PropTypes.func.isRequired, - addDangerToast: PropTypes.func.isRequired, - dashboardInfo: PropTypes.object.isRequired, - dashboardId: PropTypes.number, - dashboardTitle: PropTypes.string, - dataMask: PropTypes.object.isRequired, - customCss: PropTypes.string, - colorNamespace: PropTypes.string, - colorScheme: PropTypes.string, - directPathToChild: PropTypes.array, - onChange: PropTypes.func.isRequired, - updateCss: PropTypes.func.isRequired, - forceRefreshAllCharts: PropTypes.func.isRequired, - refreshFrequency: PropTypes.number, - shouldPersistRefreshFrequency: PropTypes.bool.isRequired, - setRefreshFrequency: PropTypes.func.isRequired, - startPeriodicRender: PropTypes.func.isRequired, - editMode: PropTypes.bool.isRequired, - userCanEdit: PropTypes.bool, - userCanShare: PropTypes.bool, - userCanSave: PropTypes.bool, - userCanCurate: PropTypes.bool.isRequired, - isLoading: PropTypes.bool.isRequired, - layout: PropTypes.object.isRequired, - expandedSlices: PropTypes.object, - onSave: PropTypes.func.isRequired, - showPropertiesModal: PropTypes.func.isRequired, - manageEmbedded: PropTypes.func.isRequired, - logEvent: PropTypes.func, - refreshLimit: PropTypes.number, - refreshWarning: PropTypes.string, - lastModifiedTime: PropTypes.number.isRequired, -}; - -const defaultProps = { - colorNamespace: undefined, - colorScheme: undefined, - refreshLimit: 0, - refreshWarning: null, -}; - -const mapStateToProps = state => ({ +const mapStateToProps = (state: RootState) => ({ directPathToChild: state.dashboardState.directPathToChild, }); -export class HeaderActionsDropdown extends PureComponent { - static discardChanges() { - window.location.reload(); - } +interface HeaderActionsDropdownState { + css: string; + showReportSubMenu: boolean | null; +} - constructor(props) { +export class HeaderActionsDropdown extends PureComponent< + HeaderDropdownProps, + HeaderActionsDropdownState +> { + static defaultProps = { + colorNamespace: undefined, + colorScheme: undefined, + refreshLimit: 0, + refreshWarning: null, + }; + + constructor(props: HeaderDropdownProps) { super(props); this.state = { - css: props.customCss, + css: props.customCss || '', showReportSubMenu: null, }; - - this.changeCss = this.changeCss.bind(this); - this.changeRefreshInterval = this.changeRefreshInterval.bind(this); - this.handleMenuClick = this.handleMenuClick.bind(this); - this.setShowReportSubMenu = this.setShowReportSubMenu.bind(this); } - UNSAFE_componentWillReceiveProps(nextProps) { + UNSAFE_componentWillReceiveProps(nextProps: HeaderDropdownProps) { if (this.props.customCss !== nextProps.customCss) { this.setState({ css: nextProps.customCss }, () => { injectCustomCss(nextProps.customCss); @@ -109,23 +73,21 @@ export class HeaderActionsDropdown extends PureComponent { } } - setShowReportSubMenu(show) { - this.setState({ - showReportSubMenu: show, - }); - } + setShowReportSubMenu = (show: boolean) => { + this.setState({ showReportSubMenu: show }); + }; - changeCss(css) { + changeCss = (css: string) => { this.props.onChange(); this.props.updateCss(css); - } + }; - changeRefreshInterval(refreshInterval, isPersistent) { + changeRefreshInterval = (refreshInterval: number, isPersistent: boolean) => { this.props.setRefreshFrequency(refreshInterval, isPersistent); this.props.startPeriodicRender(refreshInterval * 1000); - } + }; - handleMenuClick({ key }) { + handleMenuClick = ({ key }: Record) => { switch (key) { case MenuKeys.RefreshDashboard: this.props.forceRefreshAllCharts(); @@ -139,7 +101,7 @@ export class HeaderActionsDropdown extends PureComponent { pathname: window.location.pathname, filters: getActiveFilters(), hash: window.location.hash, - standalone: !getUrlParam(URL_PARAMS.standalone), + standalone: getUrlParam(URL_PARAMS.standalone), }); window.location.replace(url); break; @@ -151,7 +113,7 @@ export class HeaderActionsDropdown extends PureComponent { default: break; } - } + }; render() { const { @@ -244,8 +206,8 @@ export class HeaderActionsDropdown extends PureComponent { {userCanSave && ( {userCanShare && ( @@ -338,15 +300,16 @@ export class HeaderActionsDropdown extends PureComponent { {editMode && !isEmpty(dashboardInfo?.metadata?.filter_scopes) && ( {t('Set filter mapping')} + } /> )} { const { dashboardInfoChanged, dashboardTitleChanged } = this.props; @@ -548,12 +549,12 @@ class Header extends PureComponent { dashboardId={dashboardInfo.id} isPublished={isPublished} savePublished={this.props.savePublished} - canEdit={userCanEdit} - canSave={userCanSaveAs} + userCanEdit={userCanEdit} + userCanSave={userCanSaveAs} visible={!editMode} /> ), - !editMode && ( + !editMode && !isEmbedded && ( void; + addSuccessToast: (msg: string) => void; addDangerToast: () => void; customCss: string; colorNamespace?: string; @@ -47,20 +47,24 @@ export interface HeaderDropdownProps { onChange: () => void; onSave: () => void; refreshFrequency: number; - setRefreshFrequency: () => void; + setRefreshFrequency: (refreshInterval: number, isPersistent: boolean) => void; shouldPersistRefreshFrequency: boolean; showPropertiesModal: () => void; - startPeriodicRender: () => void; - updateCss: () => void; + startPeriodicRender: (interval: number) => void; + updateCss: (css: string) => void; userCanEdit: boolean; userCanSave: boolean; userCanShare: boolean; userCanCurate: boolean; - isDropdownVisible: boolean; manageEmbedded: () => void; dataMask: any; lastModifiedTime: number; logEvent: () => void; + setIsDropdownVisible: (visible: boolean) => void; + isDropdownVisible: boolean; + refreshLimit: number; + refreshWarning: string; + directPathToChild: string[]; } export interface HeaderProps { @@ -82,7 +86,7 @@ export interface HeaderProps { onSave: () => void; fetchFaveStar: () => void; saveFaveStar: () => void; - savePublished: () => void; + savePublished: (dashboardId: number, isPublished: boolean) => void; updateDashboardTitle: () => void; editMode: boolean; setEditMode: () => void; diff --git a/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.jsx b/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.jsx index 297c78a2c55c2..0d8421f2522ba 100644 --- a/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.jsx +++ b/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.jsx @@ -143,7 +143,7 @@ describe.skip('PropertiesModal', () => { const spy = jest.spyOn(Modal, 'error'); expect(() => modalInstance.onColorSchemeChange('THIS_WILL_NOT_WORK'), - ).toThrowError('A valid color scheme is required'); + ).toThrow('A valid color scheme is required'); expect(spy).toHaveBeenCalled(); }); }); diff --git a/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx b/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx index 7025b94f1693c..37ad242b8d813 100644 --- a/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx +++ b/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx @@ -181,7 +181,7 @@ test('should render - FeatureFlag disabled', async () => { expect(screen.getAllByRole('textbox')).toHaveLength(4); expect(screen.getByRole('combobox')).toBeInTheDocument(); - expect(spyColorSchemeControlWrapper).toBeCalledWith( + expect(spyColorSchemeControlWrapper).toHaveBeenCalledWith( expect.objectContaining({ colorScheme: 'supersetColors' }), {}, ); @@ -222,7 +222,7 @@ test('should render - FeatureFlag enabled', async () => { expect(screen.getAllByRole('textbox')).toHaveLength(4); expect(screen.getAllByRole('combobox')).toHaveLength(3); - expect(spyColorSchemeControlWrapper).toBeCalledWith( + expect(spyColorSchemeControlWrapper).toHaveBeenCalledWith( expect.objectContaining({ colorScheme: 'supersetColors' }), {}, ); @@ -255,11 +255,11 @@ test('should close modal', async () => { await screen.findByTestId('dashboard-edit-properties-form'), ).toBeInTheDocument(); - expect(props.onHide).not.toBeCalled(); + expect(props.onHide).not.toHaveBeenCalled(); userEvent.click(screen.getByRole('button', { name: 'Cancel' })); - expect(props.onHide).toBeCalledTimes(1); + expect(props.onHide).toHaveBeenCalledTimes(1); userEvent.click(screen.getByRole('button', { name: 'Close' })); - expect(props.onHide).toBeCalledTimes(2); + expect(props.onHide).toHaveBeenCalledTimes(2); }); test('submitting with onlyApply:false', async () => { @@ -293,13 +293,13 @@ test('submitting with onlyApply:false', async () => { await screen.findByTestId('dashboard-edit-properties-form'), ).toBeInTheDocument(); - expect(props.onHide).not.toBeCalled(); - expect(props.onSubmit).not.toBeCalled(); + expect(props.onHide).not.toHaveBeenCalled(); + expect(props.onSubmit).not.toHaveBeenCalled(); userEvent.click(screen.getByRole('button', { name: 'Save' })); await waitFor(() => { - expect(props.onSubmit).toBeCalledTimes(1); - expect(props.onSubmit).toBeCalledWith({ + expect(props.onSubmit).toHaveBeenCalledTimes(1); + expect(props.onSubmit).toHaveBeenCalledWith({ certificationDetails: 'Sample certification', certifiedBy: 'John Doe', colorScheme: 'supersetColors', @@ -332,12 +332,12 @@ test('submitting with onlyApply:true', async () => { await screen.findByTestId('dashboard-edit-properties-form'), ).toBeInTheDocument(); - expect(props.onHide).not.toBeCalled(); - expect(props.onSubmit).not.toBeCalled(); + expect(props.onHide).not.toHaveBeenCalled(); + expect(props.onSubmit).not.toHaveBeenCalled(); userEvent.click(screen.getByRole('button', { name: 'Apply' })); await waitFor(() => { - expect(props.onSubmit).toBeCalledTimes(1); + expect(props.onSubmit).toHaveBeenCalledTimes(1); }); }); diff --git a/superset-frontend/src/dashboard/components/PublishedStatus/PublishedStatus.test.tsx b/superset-frontend/src/dashboard/components/PublishedStatus/PublishedStatus.test.tsx index c0437cee6c9a8..28661317e515b 100644 --- a/superset-frontend/src/dashboard/components/PublishedStatus/PublishedStatus.test.tsx +++ b/superset-frontend/src/dashboard/components/PublishedStatus/PublishedStatus.test.tsx @@ -24,8 +24,8 @@ const defaultProps = { dashboardId: 1, isPublished: false, savePublished: jest.fn(), - canEdit: false, - canSave: false, + userCanEdit: false, + userCanSave: false, }; test('renders with unpublished status and readonly permissions', async () => { @@ -44,8 +44,8 @@ test('renders with unpublished status and write permissions', async () => { render( , ); @@ -69,8 +69,8 @@ test('renders with published status and write permissions', async () => { , ); diff --git a/superset-frontend/src/dashboard/components/PublishedStatus/index.jsx b/superset-frontend/src/dashboard/components/PublishedStatus/index.tsx similarity index 80% rename from superset-frontend/src/dashboard/components/PublishedStatus/index.jsx rename to superset-frontend/src/dashboard/components/PublishedStatus/index.tsx index c96654214614c..3fdb0de11a645 100644 --- a/superset-frontend/src/dashboard/components/PublishedStatus/index.jsx +++ b/superset-frontend/src/dashboard/components/PublishedStatus/index.tsx @@ -17,17 +17,17 @@ * under the License. */ import { Component } from 'react'; -import PropTypes from 'prop-types'; import { t } from '@superset-ui/core'; import { Tooltip } from 'src/components/Tooltip'; import Label from 'src/components/Label'; +import { HeaderProps, HeaderDropdownProps } from '../Header/types'; -const propTypes = { - dashboardId: PropTypes.number, - isPublished: PropTypes.bool.isRequired, - savePublished: PropTypes.func.isRequired, - canEdit: PropTypes.bool, - canSave: PropTypes.bool, +export type DashboardPublishedStatusType = { + dashboardId: HeaderDropdownProps['dashboardId']; + userCanEdit: HeaderDropdownProps['userCanEdit']; + userCanSave: HeaderDropdownProps['userCanSave']; + isPublished: HeaderProps['isPublished']; + savePublished: HeaderProps['savePublished']; }; const draftButtonTooltip = t( @@ -44,8 +44,9 @@ const publishedTooltip = t( 'This dashboard is published. Click to make it a draft.', ); -export default class PublishedStatus extends Component { - componentDidMount() { +export default class PublishedStatus extends Component { + constructor(props: DashboardPublishedStatusType) { + super(props); this.togglePublished = this.togglePublished.bind(this); } @@ -54,10 +55,12 @@ export default class PublishedStatus extends Component { } render() { + const { isPublished, userCanEdit, userCanSave } = this.props; + // Show everybody the draft badge - if (!this.props.isPublished) { + if (!isPublished) { // if they can edit the dash, make the badge a button - if (this.props.canEdit && this.props.canSave) { + if (userCanEdit && userCanSave) { return ( fn => { - // eslint-disable-next-line no-param-reassign - fn.throttle = jest.fn(); - return fn; -}); +jest.mock( + 'lodash/debounce', + () => (fn: { throttle: jest.Mock }) => { + // eslint-disable-next-line no-param-reassign + fn.throttle = jest.fn(); + return fn; + }, +); describe('SliceAdder', () => { - const props = { - ...mockSliceEntities, + const props: SliceAdderProps = { + slices: { + ...mockSliceEntities.slices, + }, fetchSlices: jest.fn(), updateSlices: jest.fn(), selectedSliceIds: [127, 128], userId: 1, + dashboardId: 0, + editMode: false, + errorMessage: '', + isLoading: false, + lastUpdated: 0, }; const errorProps = { ...props, errorMessage: 'this is error', }; - describe('SliceAdder.sortByComparator', () => { it('should sort by timestamp descending', () => { const sortedTimestamps = Object.values(props.slices) @@ -84,72 +94,88 @@ describe('SliceAdder', () => { }); it('componentDidMount', () => { - sinon.spy(SliceAdder.prototype, 'componentDidMount'); - sinon.spy(props, 'fetchSlices'); - + const componentDidMountSpy = sinon.spy( + SliceAdder.prototype, + 'componentDidMount', + ); + const fetchSlicesSpy = sinon.spy(props, 'fetchSlices'); shallow(, { lifecycleExperimental: true, }); - expect(SliceAdder.prototype.componentDidMount.calledOnce).toBe(true); - expect(props.fetchSlices.calledOnce).toBe(true); - SliceAdder.prototype.componentDidMount.restore(); - props.fetchSlices.restore(); + expect(componentDidMountSpy.calledOnce).toBe(true); + + expect(fetchSlicesSpy.calledOnce).toBe(true); + + componentDidMountSpy.restore(); + fetchSlicesSpy.restore(); }); describe('UNSAFE_componentWillReceiveProps', () => { - let wrapper; + let wrapper: ShallowWrapper; + let setStateSpy: sinon.SinonSpy; + beforeEach(() => { wrapper = shallow(); wrapper.setState({ filteredSlices: Object.values(props.slices) }); - sinon.spy(wrapper.instance(), 'setState'); + setStateSpy = sinon.spy(wrapper.instance() as SliceAdder, 'setState'); }); afterEach(() => { - wrapper.instance().setState.restore(); + setStateSpy.restore(); }); it('fetch slices should update state', () => { - wrapper.instance().UNSAFE_componentWillReceiveProps({ + const instance = wrapper.instance() as SliceAdder; + instance.UNSAFE_componentWillReceiveProps({ ...props, lastUpdated: new Date().getTime(), }); - expect(wrapper.instance().setState.calledOnce).toBe(true); + expect(setStateSpy.calledOnce).toBe(true); - const stateKeys = Object.keys( - wrapper.instance().setState.lastCall.args[0], - ); + const stateKeys = Object.keys(setStateSpy.lastCall.args[0]); expect(stateKeys).toContain('filteredSlices'); }); it('select slices should update state', () => { - wrapper.instance().UNSAFE_componentWillReceiveProps({ + const instance = wrapper.instance() as SliceAdder; + + instance.UNSAFE_componentWillReceiveProps({ ...props, selectedSliceIds: [127], }); - expect(wrapper.instance().setState.calledOnce).toBe(true); - const stateKeys = Object.keys( - wrapper.instance().setState.lastCall.args[0], - ); + expect(setStateSpy.calledOnce).toBe(true); + + const stateKeys = Object.keys(setStateSpy.lastCall.args[0]); expect(stateKeys).toContain('selectedSliceIdsSet'); }); }); describe('should rerun filter and sort', () => { - let wrapper; - let spy; + let wrapper: ShallowWrapper; + let spy: jest.Mock; + beforeEach(() => { - spy = props.fetchSlices; - wrapper = shallow(); - wrapper.setState({ filteredSlices: Object.values(props.slices) }); + spy = jest.fn(); + const fetchSlicesProps: SliceAdderProps = { + ...props, + fetchSlices: spy, + }; + wrapper = shallow(); + wrapper.setState({ + filteredSlices: Object.values(fetchSlicesProps.slices), + }); }); + afterEach(() => { spy.mockReset(); }); it('searchUpdated', () => { const newSearchTerm = 'new search term'; - wrapper.instance().handleChange(newSearchTerm); + + (wrapper.instance() as SliceAdder).handleChange(newSearchTerm); + expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalledWith( props.userId, @@ -160,7 +186,9 @@ describe('SliceAdder', () => { it('handleSelect', () => { const newSortBy = 'viz_type'; - wrapper.instance().handleSelect(newSortBy); + + (wrapper.instance() as SliceAdder).handleSelect(newSortBy); + expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalledWith(props.userId, '', newSortBy); }); diff --git a/superset-frontend/src/dashboard/components/SliceAdder.jsx b/superset-frontend/src/dashboard/components/SliceAdder.tsx similarity index 82% rename from superset-frontend/src/dashboard/components/SliceAdder.jsx rename to superset-frontend/src/dashboard/components/SliceAdder.tsx index b610fe152ce13..09f6270f83088 100644 --- a/superset-frontend/src/dashboard/components/SliceAdder.jsx +++ b/superset-frontend/src/dashboard/components/SliceAdder.tsx @@ -18,9 +18,9 @@ */ /* eslint-env browser */ import { Component } from 'react'; -import PropTypes from 'prop-types'; import AutoSizer from 'react-virtualized-auto-sizer'; import { FixedSizeList as List } from 'react-window'; +// @ts-ignore import { createFilter } from 'react-search-input'; import { t, styled, css } from '@superset-ui/core'; import { Input } from 'src/components/Input'; @@ -41,31 +41,40 @@ import { NEW_CHART_ID, NEW_COMPONENTS_SOURCE_ID, } from 'src/dashboard/util/constants'; -import { slicePropShape } from 'src/dashboard/util/propShapes'; import { debounce, pickBy } from 'lodash'; import Checkbox from 'src/components/Checkbox'; import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls'; +import { Dispatch } from 'redux'; +import { Slice } from 'src/dashboard/types'; import AddSliceCard from './AddSliceCard'; import AddSliceDragPreview from './dnd/AddSliceDragPreview'; import DragDroppable from './dnd/DragDroppable'; -const propTypes = { - fetchSlices: PropTypes.func.isRequired, - updateSlices: PropTypes.func.isRequired, - isLoading: PropTypes.bool.isRequired, - slices: PropTypes.objectOf(slicePropShape).isRequired, - lastUpdated: PropTypes.number.isRequired, - errorMessage: PropTypes.string, - userId: PropTypes.number.isRequired, - selectedSliceIds: PropTypes.arrayOf(PropTypes.number), - editMode: PropTypes.bool, - dashboardId: PropTypes.number, +export type SliceAdderProps = { + fetchSlices: ( + userId?: number, + filter_value?: string, + sortColumn?: string, + ) => Promise; + updateSlices: (slices: { + [id: number]: Slice; + }) => (dispatch: Dispatch) => void; + isLoading: boolean; + slices: Record; + lastUpdated: number; + errorMessage?: string; + userId: number; + selectedSliceIds?: number[]; + editMode?: boolean; + dashboardId: number; }; -const defaultProps = { - selectedSliceIds: [], - editMode: false, - errorMessage: '', +type SliceAdderState = { + filteredSlices: Slice[]; + searchTerm: string; + sortBy: keyof Slice; + selectedSliceIdsSet: Set; + showOnlyMyCharts: boolean; }; const KEYS_TO_FILTERS = ['slice_name', 'viz_type', 'datasource_name']; @@ -92,7 +101,7 @@ const Controls = styled.div` `} `; -const StyledSelect = styled(Select)` +const StyledSelect = styled(Select)<{ id?: string }>` margin-left: ${({ theme }) => theme.gridUnit * 2}px; min-width: 150px; `; @@ -124,22 +133,33 @@ export const ChartList = styled.div` min-height: 0; `; -class SliceAdder extends Component { - static sortByComparator(attr) { +class SliceAdder extends Component { + private slicesRequest?: AbortController | Promise; + + static sortByComparator(attr: keyof Slice) { const desc = attr === 'changed_on' ? -1 : 1; - return (a, b) => { - if (a[attr] < b[attr]) { + return (a: Slice, b: Slice) => { + const aValue = a[attr] ?? Number.MIN_SAFE_INTEGER; + const bValue = b[attr] ?? Number.MIN_SAFE_INTEGER; + + if (aValue < bValue) { return -1 * desc; } - if (a[attr] > b[attr]) { + if (aValue > bValue) { return 1 * desc; } return 0; }; } - constructor(props) { + static defaultProps = { + selectedSliceIds: [], + editMode: false, + errorMessage: '', + }; + + constructor(props: SliceAdderProps) { super(props); this.state = { filteredSlices: [], @@ -163,11 +183,15 @@ class SliceAdder extends Component { } componentDidMount() { - this.slicesRequest = this.props.fetchSlices(this.userIdForFetch()); + this.slicesRequest = this.props.fetchSlices( + this.userIdForFetch(), + '', + this.state.sortBy, + ); } - UNSAFE_componentWillReceiveProps(nextProps) { - const nextState = {}; + UNSAFE_componentWillReceiveProps(nextProps: SliceAdderProps) { + const nextState: SliceAdderState = {} as SliceAdderState; if (nextProps.lastUpdated !== this.props.lastUpdated) { nextState.filteredSlices = this.getFilteredSortedSlices( nextProps.slices, @@ -188,22 +212,27 @@ class SliceAdder extends Component { componentWillUnmount() { // Clears the redux store keeping only selected items - const selectedSlices = pickBy(this.props.slices, value => + const selectedSlices = pickBy(this.props.slices, (value: Slice) => this.state.selectedSliceIdsSet.has(value.slice_id), ); + this.props.updateSlices(selectedSlices); - if (this.slicesRequest && this.slicesRequest.abort) { + if (this.slicesRequest instanceof AbortController) { this.slicesRequest.abort(); } } - getFilteredSortedSlices(slices, searchTerm, sortBy, showOnlyMyCharts) { + getFilteredSortedSlices( + slices: SliceAdderProps['slices'], + searchTerm: string, + sortBy: keyof Slice, + showOnlyMyCharts: boolean, + ) { return Object.values(slices) .filter(slice => showOnlyMyCharts - ? (slice.owners && - slice.owners.find(owner => owner.id === this.props.userId)) || - (slice.created_by && slice.created_by.id === this.props.userId) + ? slice?.owners?.find(owner => owner.id === this.props.userId) || + slice?.created_by?.id === this.props.userId : true, ) .filter(createFilter(searchTerm, KEYS_TO_FILTERS)) @@ -219,7 +248,7 @@ class SliceAdder extends Component { ); }, 300); - searchUpdated(searchTerm) { + searchUpdated(searchTerm: string) { this.setState(prevState => ({ searchTerm, filteredSlices: this.getFilteredSortedSlices( @@ -231,7 +260,7 @@ class SliceAdder extends Component { })); } - handleSelect(sortBy) { + handleSelect(sortBy: keyof Slice) { this.setState(prevState => ({ sortBy, filteredSlices: this.getFilteredSortedSlices( @@ -248,9 +277,10 @@ class SliceAdder extends Component { ); } - rowRenderer({ key, index, style }) { + rowRenderer({ index, style }: { index: number; style: React.CSSProperties }) { const { filteredSlices, selectedSliceIdsSet } = this.state; const cellData = filteredSlices[index]; + const isSelected = selectedSliceIdsSet.has(cellData.slice_id); const type = CHART_TYPE; const id = NEW_CHART_ID; @@ -261,7 +291,7 @@ class SliceAdder extends Component { }; return ( 0 && ( - {({ height, width }) => ( + {({ height, width }: { height: number; width: number }) => ( this.state.filteredSlices[index].slice_id} > {this.rowRenderer} @@ -422,7 +450,4 @@ class SliceAdder extends Component { } } -SliceAdder.propTypes = propTypes; -SliceAdder.defaultProps = defaultProps; - export default SliceAdder; diff --git a/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx b/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx index f67d3076a1022..6dc0023b0cb8e 100644 --- a/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx @@ -444,33 +444,33 @@ test('Correct actions to "SliceHeaderControls"', () => { const props = createProps(); render(, { useRedux: true, useRouter: true }); - expect(props.toggleExpandSlice).toBeCalledTimes(0); + expect(props.toggleExpandSlice).toHaveBeenCalledTimes(0); userEvent.click(screen.getByTestId('toggleExpandSlice')); - expect(props.toggleExpandSlice).toBeCalledTimes(1); + expect(props.toggleExpandSlice).toHaveBeenCalledTimes(1); - expect(props.forceRefresh).toBeCalledTimes(0); + expect(props.forceRefresh).toHaveBeenCalledTimes(0); userEvent.click(screen.getByTestId('forceRefresh')); - expect(props.forceRefresh).toBeCalledTimes(1); + expect(props.forceRefresh).toHaveBeenCalledTimes(1); - expect(props.logExploreChart).toBeCalledTimes(0); + expect(props.logExploreChart).toHaveBeenCalledTimes(0); userEvent.click(screen.getByTestId('exploreChart')); - expect(props.logExploreChart).toBeCalledTimes(1); + expect(props.logExploreChart).toHaveBeenCalledTimes(1); - expect(props.exportCSV).toBeCalledTimes(0); + expect(props.exportCSV).toHaveBeenCalledTimes(0); userEvent.click(screen.getByTestId('exportCSV')); - expect(props.exportCSV).toBeCalledTimes(1); + expect(props.exportCSV).toHaveBeenCalledTimes(1); - expect(props.addSuccessToast).toBeCalledTimes(0); + expect(props.addSuccessToast).toHaveBeenCalledTimes(0); userEvent.click(screen.getByTestId('addSuccessToast')); - expect(props.addSuccessToast).toBeCalledTimes(1); + expect(props.addSuccessToast).toHaveBeenCalledTimes(1); - expect(props.addDangerToast).toBeCalledTimes(0); + expect(props.addDangerToast).toHaveBeenCalledTimes(0); userEvent.click(screen.getByTestId('addDangerToast')); - expect(props.addDangerToast).toBeCalledTimes(1); + expect(props.addDangerToast).toHaveBeenCalledTimes(1); - expect(props.handleToggleFullSize).toBeCalledTimes(0); + expect(props.handleToggleFullSize).toHaveBeenCalledTimes(0); userEvent.click(screen.getByTestId('handleToggleFullSize')); - expect(props.handleToggleFullSize).toBeCalledTimes(1); + expect(props.handleToggleFullSize).toHaveBeenCalledTimes(1); }); test('Add extension to SliceHeader', () => { diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx b/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx index 92a7563fc8dc8..cca28d4e45914 100644 --- a/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx @@ -180,21 +180,21 @@ test('Should render default props', () => { test('Should "export to CSV"', async () => { const props = createProps(); renderWrapper(props); - expect(props.exportCSV).toBeCalledTimes(0); + expect(props.exportCSV).toHaveBeenCalledTimes(0); userEvent.hover(screen.getByText('Download')); userEvent.click(await screen.findByText('Export to .CSV')); - expect(props.exportCSV).toBeCalledTimes(1); - expect(props.exportCSV).toBeCalledWith(371); + expect(props.exportCSV).toHaveBeenCalledTimes(1); + expect(props.exportCSV).toHaveBeenCalledWith(371); }); test('Should "export to Excel"', async () => { const props = createProps(); renderWrapper(props); - expect(props.exportXLSX).toBeCalledTimes(0); + expect(props.exportXLSX).toHaveBeenCalledTimes(0); userEvent.hover(screen.getByText('Download')); userEvent.click(await screen.findByText('Export to Excel')); - expect(props.exportXLSX).toBeCalledTimes(1); - expect(props.exportXLSX).toBeCalledWith(371); + expect(props.exportXLSX).toHaveBeenCalledTimes(1); + expect(props.exportXLSX).toHaveBeenCalledWith(371); }); test('Export full CSV is under featureflag', async () => { @@ -214,11 +214,11 @@ test('Should "export full CSV"', async () => { }; const props = createProps('table'); renderWrapper(props); - expect(props.exportFullCSV).toBeCalledTimes(0); + expect(props.exportFullCSV).toHaveBeenCalledTimes(0); userEvent.hover(screen.getByText('Download')); userEvent.click(await screen.findByText('Export to full .CSV')); - expect(props.exportFullCSV).toBeCalledTimes(1); - expect(props.exportFullCSV).toBeCalledWith(371); + expect(props.exportFullCSV).toHaveBeenCalledTimes(1); + expect(props.exportFullCSV).toHaveBeenCalledWith(371); }); test('Should not show export full CSV if report is not table', async () => { @@ -248,11 +248,11 @@ test('Should "export full Excel"', async () => { }; const props = createProps('table'); renderWrapper(props); - expect(props.exportFullXLSX).toBeCalledTimes(0); + expect(props.exportFullXLSX).toHaveBeenCalledTimes(0); userEvent.hover(screen.getByText('Download')); userEvent.click(await screen.findByText('Export to full Excel')); - expect(props.exportFullXLSX).toBeCalledTimes(1); - expect(props.exportFullXLSX).toBeCalledWith(371); + expect(props.exportFullXLSX).toHaveBeenCalledTimes(1); + expect(props.exportFullXLSX).toHaveBeenCalledWith(371); }); test('Should not show export full Excel if report is not table', async () => { @@ -268,29 +268,29 @@ test('Should not show export full Excel if report is not table', async () => { test('Should "Show chart description"', () => { const props = createProps(); renderWrapper(props); - expect(props.toggleExpandSlice).toBeCalledTimes(0); + expect(props.toggleExpandSlice).toHaveBeenCalledTimes(0); userEvent.click(screen.getByText('Show chart description')); - expect(props.toggleExpandSlice).toBeCalledTimes(1); - expect(props.toggleExpandSlice).toBeCalledWith(371); + expect(props.toggleExpandSlice).toHaveBeenCalledTimes(1); + expect(props.toggleExpandSlice).toHaveBeenCalledWith(371); }); test('Should "Force refresh"', () => { const props = createProps(); renderWrapper(props); - expect(props.forceRefresh).toBeCalledTimes(0); + expect(props.forceRefresh).toHaveBeenCalledTimes(0); userEvent.click(screen.getByText('Force refresh')); - expect(props.forceRefresh).toBeCalledTimes(1); - expect(props.forceRefresh).toBeCalledWith(371, 26); - expect(props.addSuccessToast).toBeCalledTimes(1); + expect(props.forceRefresh).toHaveBeenCalledTimes(1); + expect(props.forceRefresh).toHaveBeenCalledWith(371, 26); + expect(props.addSuccessToast).toHaveBeenCalledTimes(1); }); test('Should "Enter fullscreen"', () => { const props = createProps(); renderWrapper(props); - expect(props.handleToggleFullSize).toBeCalledTimes(0); + expect(props.handleToggleFullSize).toHaveBeenCalledTimes(0); userEvent.click(screen.getByText('Enter fullscreen')); - expect(props.handleToggleFullSize).toBeCalledTimes(1); + expect(props.handleToggleFullSize).toHaveBeenCalledTimes(1); }); test('Drill to detail modal is under featureflag', () => { diff --git a/superset-frontend/src/dashboard/components/UndoRedoKeyListeners/index.jsx b/superset-frontend/src/dashboard/components/UndoRedoKeyListeners/index.tsx similarity index 75% rename from superset-frontend/src/dashboard/components/UndoRedoKeyListeners/index.jsx rename to superset-frontend/src/dashboard/components/UndoRedoKeyListeners/index.tsx index c8bff40366d06..89dd62694ed51 100644 --- a/superset-frontend/src/dashboard/components/UndoRedoKeyListeners/index.jsx +++ b/superset-frontend/src/dashboard/components/UndoRedoKeyListeners/index.tsx @@ -17,15 +17,15 @@ * under the License. */ import { PureComponent } from 'react'; -import PropTypes from 'prop-types'; +import { HeaderProps } from '../Header/types'; -const propTypes = { - onUndo: PropTypes.func.isRequired, - onRedo: PropTypes.func.isRequired, +type UndoRedoKeyListenersProps = { + onUndo: HeaderProps['onUndo']; + onRedo: HeaderProps['onRedo']; }; -class UndoRedoKeyListeners extends PureComponent { - constructor(props) { +class UndoRedoKeyListeners extends PureComponent { + constructor(props: UndoRedoKeyListenersProps) { super(props); this.handleKeydown = this.handleKeydown.bind(this); } @@ -38,15 +38,17 @@ class UndoRedoKeyListeners extends PureComponent { document.removeEventListener('keydown', this.handleKeydown); } - handleKeydown(event) { + handleKeydown(event: KeyboardEvent) { const controlOrCommand = event.ctrlKey || event.metaKey; if (controlOrCommand) { const isZChar = event.key === 'z' || event.keyCode === 90; const isYChar = event.key === 'y' || event.keyCode === 89; - const isEditingMarkdown = - document && document.querySelector('.dashboard-markdown--editing'); - const isEditingTitle = - document && document.querySelector('.editable-title--editing'); + const isEditingMarkdown = document?.querySelector( + '.dashboard-markdown--editing', + ); + const isEditingTitle = document?.querySelector( + '.editable-title--editing', + ); if (!isEditingMarkdown && !isEditingTitle && (isZChar || isYChar)) { event.preventDefault(); @@ -61,6 +63,4 @@ class UndoRedoKeyListeners extends PureComponent { } } -UndoRedoKeyListeners.propTypes = propTypes; - export default UndoRedoKeyListeners; diff --git a/superset-frontend/src/dashboard/components/dnd/AddSliceDragPreview.jsx b/superset-frontend/src/dashboard/components/dnd/AddSliceDragPreview.tsx similarity index 72% rename from superset-frontend/src/dashboard/components/dnd/AddSliceDragPreview.jsx rename to superset-frontend/src/dashboard/components/dnd/AddSliceDragPreview.tsx index 375e2cdc3639a..dfd2d036880cd 100644 --- a/superset-frontend/src/dashboard/components/dnd/AddSliceDragPreview.jsx +++ b/superset-frontend/src/dashboard/components/dnd/AddSliceDragPreview.tsx @@ -16,17 +16,28 @@ * specific language governing permissions and limitations * under the License. */ -import PropTypes from 'prop-types'; -import { DragLayer } from 'react-dnd'; - +import { DragLayer, XYCoord } from 'react-dnd'; +import { Slice } from 'src/dashboard/types'; import AddSliceCard from '../AddSliceCard'; -import { slicePropShape } from '../../util/propShapes'; import { NEW_COMPONENT_SOURCE_TYPE, CHART_TYPE, } from '../../util/componentTypes'; -const staticCardStyles = { +interface DragItem { + index: number; + parentType: string; + type: string; +} + +interface AddSliceDragPreviewProps { + dragItem: DragItem | null; + slices: Slice[] | null; + isDragging: boolean; + currentOffset: XYCoord | null; +} + +const staticCardStyles: React.CSSProperties = { position: 'fixed', pointerEvents: 'none', top: 0, @@ -35,25 +46,12 @@ const staticCardStyles = { width: 376 - 2 * 16, }; -const propTypes = { - dragItem: PropTypes.shape({ - index: PropTypes.number.isRequired, - }), - slices: PropTypes.arrayOf(slicePropShape), - isDragging: PropTypes.bool.isRequired, - currentOffset: PropTypes.shape({ - x: PropTypes.number.isRequired, - y: PropTypes.number.isRequired, - }), -}; - -const defaultProps = { - currentOffset: null, - dragItem: null, - slices: null, -}; - -function AddSliceDragPreview({ dragItem, slices, isDragging, currentOffset }) { +const AddSliceDragPreview: React.FC = ({ + dragItem, + slices, + isDragging, + currentOffset, +}) => { if (!isDragging || !currentOffset || !dragItem || !slices) return null; const slice = slices[dragItem.index]; @@ -77,14 +75,11 @@ function AddSliceDragPreview({ dragItem, slices, isDragging, currentOffset }) { datasourceName={slice.datasource_name} /> ); -} - -AddSliceDragPreview.propTypes = propTypes; -AddSliceDragPreview.defaultProps = defaultProps; +}; // This injects these props into the component export default DragLayer(monitor => ({ - dragItem: monitor.getItem(), + dragItem: monitor.getItem() as DragItem | null, currentOffset: monitor.getSourceClientOffset(), isDragging: monitor.isDragging(), }))(AddSliceDragPreview); diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tab.test.tsx b/superset-frontend/src/dashboard/components/gridComponents/Tab.test.tsx index 28802cc6072a3..5b6d9a7553847 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Tab.test.tsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Tab.test.tsx @@ -116,7 +116,7 @@ test('Render tab (no content)', () => { useDnd: true, }); expect(screen.getByText('🚀 Aspiring Developers')).toBeInTheDocument(); - expect(EditableTitle).toBeCalledTimes(1); + expect(EditableTitle).toHaveBeenCalledTimes(1); expect(getByTestId('dragdroppable-object')).toBeInTheDocument(); }); @@ -129,7 +129,7 @@ test('Render tab (no content) editMode:true', () => { useDnd: true, }); expect(screen.getByText('🚀 Aspiring Developers')).toBeInTheDocument(); - expect(EditableTitle).toBeCalledTimes(1); + expect(EditableTitle).toHaveBeenCalledTimes(1); expect(getByTestId('dragdroppable-object')).toBeInTheDocument(); }); @@ -222,12 +222,12 @@ test('Edit table title', () => { useDnd: true, }); - expect(EditableTitle).toBeCalledTimes(1); + expect(EditableTitle).toHaveBeenCalledTimes(1); expect(getByTestId('dragdroppable-object')).toBeInTheDocument(); - expect(props.updateComponents).not.toBeCalled(); + expect(props.updateComponents).not.toHaveBeenCalled(); userEvent.click(screen.getByText('🚀 Aspiring Developers')); - expect(props.updateComponents).toBeCalled(); + expect(props.updateComponents).toHaveBeenCalled(); }); test('Render tab (with content)', () => { @@ -237,7 +237,7 @@ test('Render tab (with content)', () => { useRedux: true, useDnd: true, }); - expect(DashboardComponent).toBeCalledTimes(2); + expect(DashboardComponent).toHaveBeenCalledTimes(2); expect(DashboardComponent).toHaveBeenNthCalledWith( 1, expect.objectContaining({ @@ -316,7 +316,7 @@ test('Render tab (with content) editMode:true', () => { useRedux: true, useDnd: true, }); - expect(DashboardComponent).toBeCalledTimes(2); + expect(DashboardComponent).toHaveBeenCalledTimes(2); expect(DashboardComponent).toHaveBeenNthCalledWith( 1, expect.objectContaining({ @@ -369,14 +369,14 @@ test('Should call "handleDrop" and "handleTopDropTargetDrop"', () => { }, ); - expect(props.handleComponentDrop).not.toBeCalled(); + expect(props.handleComponentDrop).not.toHaveBeenCalled(); userEvent.click(getAllByTestId('MockDroppable')[0]); - expect(props.handleComponentDrop).toBeCalledTimes(1); - expect(props.onDropOnTab).not.toBeCalled(); + expect(props.handleComponentDrop).toHaveBeenCalledTimes(1); + expect(props.onDropOnTab).not.toHaveBeenCalled(); rerender(); userEvent.click(getAllByTestId('MockDroppable')[1]); - expect(props.onDropOnTab).toBeCalledTimes(1); - expect(props.handleComponentDrop).toBeCalledTimes(2); + expect(props.onDropOnTab).toHaveBeenCalledTimes(1); + expect(props.handleComponentDrop).toHaveBeenCalledTimes(2); }); test('Render tab content with no children, editMode: true, canEdit: true', () => { diff --git a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsImage.test.tsx b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsImage.test.tsx index 0242bd0091571..8401ece73c4c2 100644 --- a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsImage.test.tsx +++ b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsImage.test.tsx @@ -23,13 +23,20 @@ import { Menu } from 'src/components/Menu'; import downloadAsImage from 'src/utils/downloadAsImage'; import DownloadAsImage from './DownloadAsImage'; +const mockAddDangerToast = jest.fn(); + jest.mock('src/utils/downloadAsImage', () => ({ __esModule: true, default: jest.fn(() => (_e: SyntheticEvent) => {}), })); +jest.mock('src/components/MessageToasts/withToasts', () => ({ + useToasts: () => ({ + addDangerToast: mockAddDangerToast, + }), +})); + const createProps = () => ({ - addDangerToast: jest.fn(), text: 'Download as Image', dashboardTitle: 'Test Dashboard', logEvent: jest.fn(), @@ -40,22 +47,24 @@ const renderComponent = () => { , + { + useRedux: true, + }, ); }; test('Should call download image on click', async () => { - const props = createProps(); renderComponent(); await waitFor(() => { - expect(downloadAsImage).toBeCalledTimes(0); - expect(props.addDangerToast).toBeCalledTimes(0); + expect(downloadAsImage).toHaveBeenCalledTimes(0); + expect(mockAddDangerToast).toHaveBeenCalledTimes(0); }); userEvent.click(screen.getByRole('button', { name: 'Download as Image' })); await waitFor(() => { - expect(downloadAsImage).toBeCalledTimes(1); - expect(props.addDangerToast).toBeCalledTimes(0); + expect(downloadAsImage).toHaveBeenCalledTimes(1); + expect(mockAddDangerToast).toHaveBeenCalledTimes(0); }); }); diff --git a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsImage.tsx b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsImage.tsx index 0cb3f1fbb4f41..505a9b8184ae1 100644 --- a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsImage.tsx +++ b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsImage.tsx @@ -21,20 +21,20 @@ import { logging, t } from '@superset-ui/core'; import { Menu } from 'src/components/Menu'; import { LOG_ACTIONS_DASHBOARD_DOWNLOAD_AS_IMAGE } from 'src/logger/LogUtils'; import downloadAsImage from 'src/utils/downloadAsImage'; +import { useToasts } from 'src/components/MessageToasts/withToasts'; export default function DownloadAsImage({ text, logEvent, dashboardTitle, - addDangerToast, ...rest }: { text: string; - addDangerToast: Function; dashboardTitle: string; logEvent?: Function; }) { const SCREENSHOT_NODE_SELECTOR = '.dashboard'; + const { addDangerToast } = useToasts(); const onDownloadImage = async (e: SyntheticEvent) => { try { downloadAsImage(SCREENSHOT_NODE_SELECTOR, dashboardTitle, true)(e); diff --git a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsPdf.test.tsx b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsPdf.test.tsx new file mode 100644 index 0000000000000..56916f4b64763 --- /dev/null +++ b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsPdf.test.tsx @@ -0,0 +1,73 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { SyntheticEvent } from 'react'; +import { render, screen, waitFor } from 'spec/helpers/testing-library'; +import userEvent from '@testing-library/user-event'; +import { Menu } from 'src/components/Menu'; +import downloadAsPdf from 'src/utils/downloadAsPdf'; +import DownloadAsPdf from './DownloadAsPdf'; + +const mockAddDangerToast = jest.fn(); + +jest.mock('src/utils/downloadAsPdf', () => ({ + __esModule: true, + default: jest.fn(() => (_e: SyntheticEvent) => {}), +})); + +jest.mock('src/components/MessageToasts/withToasts', () => ({ + useToasts: () => ({ + addDangerToast: mockAddDangerToast, + }), +})); + +const createProps = () => ({ + text: 'Export as PDF', + dashboardTitle: 'Test Dashboard', + logEvent: jest.fn(), +}); + +const renderComponent = () => { + render( + + + , + { useRedux: true }, + ); +}; + +test('Should call download pdf on click', async () => { + renderComponent(); + await waitFor(() => { + expect(downloadAsPdf).toHaveBeenCalledTimes(0); + expect(mockAddDangerToast).toHaveBeenCalledTimes(0); + }); + + userEvent.click(screen.getByRole('button', { name: 'Export as PDF' })); + + await waitFor(() => { + expect(downloadAsPdf).toHaveBeenCalledTimes(1); + expect(mockAddDangerToast).toHaveBeenCalledTimes(0); + }); +}); + +test('Component is rendered with role="button"', async () => { + renderComponent(); + const button = screen.getByRole('button', { name: 'Export as PDF' }); + expect(button).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsPdf.tsx b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsPdf.tsx new file mode 100644 index 0000000000000..a07a2e232c6dc --- /dev/null +++ b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadAsPdf.tsx @@ -0,0 +1,55 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { SyntheticEvent } from 'react'; +import { logging, t } from '@superset-ui/core'; +import { Menu } from 'src/components/Menu'; +import downloadAsPdf from 'src/utils/downloadAsPdf'; +import { LOG_ACTIONS_DASHBOARD_DOWNLOAD_AS_PDF } from 'src/logger/LogUtils'; +import { useToasts } from 'src/components/MessageToasts/withToasts'; + +export default function DownloadAsPdf({ + text, + logEvent, + dashboardTitle, + ...rest +}: { + text: string; + dashboardTitle: string; + logEvent?: Function; +}) { + const SCREENSHOT_NODE_SELECTOR = '.dashboard'; + const { addDangerToast } = useToasts(); + const onDownloadPdf = async (e: SyntheticEvent) => { + try { + downloadAsPdf(SCREENSHOT_NODE_SELECTOR, dashboardTitle, true)(e); + } catch (error) { + logging.error(error); + addDangerToast(t('Sorry, something went wrong. Try again later.')); + } + logEvent?.(LOG_ACTIONS_DASHBOARD_DOWNLOAD_AS_PDF); + }; + + return ( + +
+ {text} +
+
+ ); +} diff --git a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadMenuItems.test.tsx b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadMenuItems.test.tsx index fe453bb397b38..cbee1765c9ab0 100644 --- a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadMenuItems.test.tsx +++ b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadMenuItems.test.tsx @@ -24,7 +24,7 @@ const createProps = () => ({ imageMenuItemTitle: 'Download as Image', dashboardTitle: 'Test Dashboard', logEvent: jest.fn(), - dashboardId: '123', + dashboardId: 123, }); const renderComponent = () => { diff --git a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.test.tsx b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.test.tsx index 01d756403a463..9c8922f6211f0 100644 --- a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.test.tsx +++ b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.test.tsx @@ -42,7 +42,7 @@ jest.mock('src/components/MessageToasts/withToasts', () => ({ const defaultProps = () => ({ text: 'Download', - dashboardId: '123', + dashboardId: 123, format: DownloadScreenshotFormat.PDF, logEvent: mockLogEvent, }); @@ -130,6 +130,9 @@ describe('DownloadScreenshot component', () => { await waitFor(() => { expect(mockAddInfoToast).toHaveBeenCalledWith( 'The screenshot is being generated. Please, do not leave the page.', + { + noDuplicate: true, + }, ); }); }); @@ -202,7 +205,7 @@ describe('DownloadScreenshot component', () => { // Wait for the successful image retrieval message await waitFor(() => { expect(mockAddSuccessToast).toHaveBeenCalledWith( - 'The screenshot is now being downloaded.', + 'The screenshot has been downloaded.', ); }); }); diff --git a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.tsx b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.tsx index 2d182e31fc754..17ec6ee8d8499 100644 --- a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.tsx +++ b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/DownloadScreenshot.tsx @@ -32,6 +32,8 @@ import { RootState } from 'src/dashboard/types'; import { useSelector } from 'react-redux'; import { useToasts } from 'src/components/MessageToasts/withToasts'; import { last } from 'lodash'; +import { getDashboardUrlParams } from 'src/utils/urlUtils'; +import { useCallback, useEffect, useRef } from 'react'; import { DownloadScreenshotFormat } from './types'; const RETRY_INTERVAL = 3000; @@ -45,28 +47,73 @@ export default function DownloadScreenshot({ ...rest }: { text: string; - dashboardId: string; + dashboardId: number; logEvent?: Function; format: string; }) { const activeTabs = useSelector( (state: RootState) => state.dashboardState.activeTabs || undefined, ); - const anchor = useSelector( (state: RootState) => last(state.dashboardState.directPathToChild) || undefined, ); - const dataMask = useSelector( (state: RootState) => state.dataMask || undefined, ); - const { addDangerToast, addSuccessToast, addInfoToast } = useToasts(); + const currentIntervalIds = useRef([]); + + const printLoadingToast = () => + addInfoToast( + t('The screenshot is being generated. Please, do not leave the page.'), + { + noDuplicate: true, + }, + ); + + const printFailureToast = useCallback( + () => + addDangerToast( + t('The screenshot could not be downloaded. Please, try again later.'), + ), + [addDangerToast], + ); + + const printSuccessToast = useCallback( + () => addSuccessToast(t('The screenshot has been downloaded.')), + [addSuccessToast], + ); + + const stopIntervals = useCallback( + (message?: 'success' | 'failure') => { + currentIntervalIds.current.forEach(clearInterval); + + if (message === 'failure') { + printFailureToast(); + } + if (message === 'success') { + printSuccessToast(); + } + }, + [printFailureToast, printSuccessToast], + ); const onDownloadScreenshot = () => { let retries = 0; + const toastIntervalId = setInterval( + () => printLoadingToast(), + RETRY_INTERVAL, + ); + + currentIntervalIds.current = [ + ...(currentIntervalIds.current || []), + toastIntervalId, + ]; + + printLoadingToast(); + // this function checks if the image is ready const checkImageReady = (cacheKey: string) => SupersetClient.get({ @@ -84,6 +131,7 @@ export default function DownloadScreenshot({ a.click(); document.body.removeChild(a); window.URL.revokeObjectURL(url); + stopIntervals('success'); }) .catch(err => { if ((err as SupersetApiError).status === 404) { @@ -91,34 +139,15 @@ export default function DownloadScreenshot({ } }); - // this is the functions that handles the retries const fetchImageWithRetry = (cacheKey: string) => { - checkImageReady(cacheKey) - .then(() => { - addSuccessToast(t('The screenshot is now being downloaded.')); - }) - .catch(error => { - // we check how many retries have been made - if (retries < MAX_RETRIES) { - retries += 1; - addInfoToast( - t( - 'The screenshot is being generated. Please, do not leave the page.', - ), - { - noDuplicate: true, - }, - ); - setTimeout(() => fetchImageWithRetry(cacheKey), RETRY_INTERVAL); - } else { - addDangerToast( - t( - 'The screenshot could not be downloaded. Please, try again later.', - ), - ); - logging.error(error); - } - }); + if (retries >= MAX_RETRIES) { + stopIntervals('failure'); + logging.error('Max retries reached'); + return; + } + checkImageReady(cacheKey).catch(() => { + retries += 1; + }); }; SupersetClient.post({ @@ -127,6 +156,7 @@ export default function DownloadScreenshot({ anchor, activeTabs, dataMask, + urlParams: getDashboardUrlParams(), }, }) .then(({ json }) => { @@ -134,18 +164,15 @@ export default function DownloadScreenshot({ if (!cacheKey) { throw new Error('No image URL in response'); } - addInfoToast( - t( - 'The screenshot is being generated. Please, do not leave the page.', - ), - ); + const retryIntervalId = setInterval(() => { + fetchImageWithRetry(cacheKey); + }, RETRY_INTERVAL); + currentIntervalIds.current.push(retryIntervalId); fetchImageWithRetry(cacheKey); }) .catch(error => { logging.error(error); - addDangerToast( - t('The screenshot could not be downloaded. Please, try again later.'), - ); + stopIntervals('failure'); }) .finally(() => { logEvent?.( @@ -156,6 +183,16 @@ export default function DownloadScreenshot({ }); }; + useEffect( + () => () => { + if (currentIntervalIds.current.length > 0) { + stopIntervals(); + } + currentIntervalIds.current = []; + }, + [stopIntervals], + ); + return (
diff --git a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/index.tsx b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/index.tsx index c17fc0d0265d7..875537fb8e13b 100644 --- a/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/index.tsx +++ b/superset-frontend/src/dashboard/components/menu/DownloadMenuItems/index.tsx @@ -17,15 +17,18 @@ * under the License. */ import { Menu } from 'src/components/Menu'; +import { FeatureFlag, isFeatureEnabled } from '@superset-ui/core'; import DownloadScreenshot from './DownloadScreenshot'; import { DownloadScreenshotFormat } from './types'; +import DownloadAsPdf from './DownloadAsPdf'; +import DownloadAsImage from './DownloadAsImage'; export interface DownloadMenuItemProps { pdfMenuItemTitle: string; imageMenuItemTitle: string; dashboardTitle: string; logEvent?: Function; - dashboardId: string; + dashboardId: number; } const DownloadMenuItems = (props: DownloadMenuItemProps) => { @@ -34,25 +37,48 @@ const DownloadMenuItems = (props: DownloadMenuItemProps) => { imageMenuItemTitle, logEvent, dashboardId, + dashboardTitle, ...rest } = props; + const isWebDriverScreenshotEnabled = + isFeatureEnabled(FeatureFlag.EnableDashboardScreenshotEndpoints) && + isFeatureEnabled(FeatureFlag.EnableDashboardDownloadWebDriverScreenshot); return ( - - + {isWebDriverScreenshotEnabled ? ( + <> + + + + ) : ( + <> + + + + )} ); }; diff --git a/superset-frontend/src/dashboard/components/menu/HoverMenu.test.tsx b/superset-frontend/src/dashboard/components/menu/HoverMenu.test.tsx index b58afd12e71ed..b3c033e82d602 100644 --- a/superset-frontend/src/dashboard/components/menu/HoverMenu.test.tsx +++ b/superset-frontend/src/dashboard/components/menu/HoverMenu.test.tsx @@ -33,8 +33,8 @@ test('should call onHover when mouse enters and leaves', () => { const hoverMenu = screen.getByTestId('hover-menu'); userEvent.hover(hoverMenu); - expect(onHover).toBeCalledWith({ isHovered: true }); + expect(onHover).toHaveBeenCalledWith({ isHovered: true }); userEvent.unhover(hoverMenu); - expect(onHover).toBeCalledWith({ isHovered: false }); + expect(onHover).toHaveBeenCalledWith({ isHovered: false }); }); diff --git a/superset-frontend/src/dashboard/components/menu/ShareMenuItems/ShareMenuItems.test.tsx b/superset-frontend/src/dashboard/components/menu/ShareMenuItems/ShareMenuItems.test.tsx index 6b8ad4fe2d5c5..8420847acab4d 100644 --- a/superset-frontend/src/dashboard/components/menu/ShareMenuItems/ShareMenuItems.test.tsx +++ b/superset-frontend/src/dashboard/components/menu/ShareMenuItems/ShareMenuItems.test.tsx @@ -96,20 +96,20 @@ test('Click on "Copy dashboard URL" and succeed', async () => { ); await waitFor(() => { - expect(spy).toBeCalledTimes(0); - expect(props.addSuccessToast).toBeCalledTimes(0); - expect(props.addDangerToast).toBeCalledTimes(0); + expect(spy).toHaveBeenCalledTimes(0); + expect(props.addSuccessToast).toHaveBeenCalledTimes(0); + expect(props.addDangerToast).toHaveBeenCalledTimes(0); }); userEvent.click(screen.getByRole('button', { name: 'Copy dashboard URL' })); await waitFor(async () => { - expect(spy).toBeCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(1); const value = await spy.mock.calls[0][0](); expect(value).toBe('http://localhost/superset/dashboard/p/123/'); - expect(props.addSuccessToast).toBeCalledTimes(1); - expect(props.addSuccessToast).toBeCalledWith('Copied to clipboard!'); - expect(props.addDangerToast).toBeCalledTimes(0); + expect(props.addSuccessToast).toHaveBeenCalledTimes(1); + expect(props.addSuccessToast).toHaveBeenCalledWith('Copied to clipboard!'); + expect(props.addDangerToast).toHaveBeenCalledTimes(0); }); }); @@ -124,20 +124,20 @@ test('Click on "Copy dashboard URL" and fail', async () => { ); await waitFor(() => { - expect(spy).toBeCalledTimes(0); - expect(props.addSuccessToast).toBeCalledTimes(0); - expect(props.addDangerToast).toBeCalledTimes(0); + expect(spy).toHaveBeenCalledTimes(0); + expect(props.addSuccessToast).toHaveBeenCalledTimes(0); + expect(props.addDangerToast).toHaveBeenCalledTimes(0); }); userEvent.click(screen.getByRole('button', { name: 'Copy dashboard URL' })); await waitFor(async () => { - expect(spy).toBeCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(1); const value = await spy.mock.calls[0][0](); expect(value).toBe('http://localhost/superset/dashboard/p/123/'); - expect(props.addSuccessToast).toBeCalledTimes(0); - expect(props.addDangerToast).toBeCalledTimes(1); - expect(props.addDangerToast).toBeCalledWith( + expect(props.addSuccessToast).toHaveBeenCalledTimes(0); + expect(props.addDangerToast).toHaveBeenCalledTimes(1); + expect(props.addDangerToast).toHaveBeenCalledWith( 'Sorry, something went wrong. Try again later.', ); }); @@ -153,7 +153,7 @@ test('Click on "Share dashboard by email" and succeed', async () => { ); await waitFor(() => { - expect(props.addDangerToast).toBeCalledTimes(0); + expect(props.addDangerToast).toHaveBeenCalledTimes(0); expect(window.location.href).toBe(''); }); @@ -162,7 +162,7 @@ test('Click on "Share dashboard by email" and succeed', async () => { ); await waitFor(() => { - expect(props.addDangerToast).toBeCalledTimes(0); + expect(props.addDangerToast).toHaveBeenCalledTimes(0); expect(window.location.href).toBe( 'mailto:?Subject=Superset%20dashboard%20COVID%20Vaccine%20Dashboard%20&Body=Check%20out%20this%20dashboard%3A%20http%3A%2F%2Flocalhost%2Fsuperset%2Fdashboard%2Fp%2F123%2F', ); @@ -184,7 +184,7 @@ test('Click on "Share dashboard by email" and fail', async () => { ); await waitFor(() => { - expect(props.addDangerToast).toBeCalledTimes(0); + expect(props.addDangerToast).toHaveBeenCalledTimes(0); expect(window.location.href).toBe(''); }); @@ -194,8 +194,8 @@ test('Click on "Share dashboard by email" and fail', async () => { await waitFor(() => { expect(window.location.href).toBe(''); - expect(props.addDangerToast).toBeCalledTimes(1); - expect(props.addDangerToast).toBeCalledWith( + expect(props.addDangerToast).toHaveBeenCalledTimes(1); + expect(props.addDangerToast).toHaveBeenCalledWith( 'Sorry, something went wrong. Try again later.', ); }); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx index d7e8564eb5105..7be1e7814c085 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx @@ -21,9 +21,10 @@ import { ReactNode, FC, useCallback, useState, memo } from 'react'; import { useDispatch } from 'react-redux'; import { setFilterConfiguration } from 'src/dashboard/actions/nativeFilters'; import Button from 'src/components/Button'; -import { FilterConfiguration, styled } from '@superset-ui/core'; +import { styled } from '@superset-ui/core'; import FiltersConfigModal from 'src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal'; import { getFilterBarTestId } from '../utils'; +import { SaveFilterChangesType } from '../../FiltersConfigModal/types'; export interface FCBProps { createNewOnOpen?: boolean; @@ -46,14 +47,13 @@ export const FilterConfigurationLink: FC = ({ }) => { const dispatch = useDispatch(); const [isOpen, setOpen] = useState(false); - const close = useCallback(() => { setOpen(false); }, [setOpen]); const submit = useCallback( - async (filterConfig: FilterConfiguration) => { - dispatch(await setFilterConfiguration(filterConfig)); + async (filterChanges: SaveFilterChangesType) => { + dispatch(await setFilterConfiguration(filterChanges)); close(); }, [dispatch, close], diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx index f303d5a10aad9..6b06c32f6bdf9 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx @@ -253,7 +253,10 @@ const FilterControl = ({ const label = useMemo( () => ( - + {name} {isRequired && } @@ -315,7 +318,7 @@ const FilterControl = ({
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx index 2d85f413c355a..45ccd4dd4119a 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx @@ -182,7 +182,6 @@ const FilterValue: FC = ({ if (isFeatureEnabled(FeatureFlag.GlobalAsyncQueries)) { // deal with getChartDataRequest transforming the response data const result = 'result' in json ? json.result[0] : json; - if (response.status === 200) { setState([result]); handleFilterLoadFinish(); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.test.tsx index 1a1c6361f8ce9..163a12dc30a76 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.test.tsx @@ -84,12 +84,12 @@ test('Should call "setFields" when "datasetId" changes', () => { const { rerender } = render(, { useRedux: true, }); - expect(props.form.setFields).not.toBeCalled(); + expect(props.form.setFields).not.toHaveBeenCalled(); props.datasetId = 456; rerender(); - expect(props.form.setFields).toBeCalled(); + expect(props.form.setFields).toHaveBeenCalled(); }); test('Should call "getClientErrorObject" when api returns an error', async () => { @@ -98,12 +98,12 @@ test('Should call "getClientErrorObject" when api returns an error', async () => props.datasetId = 789; const spy = jest.spyOn(uiCore, 'getClientErrorObject'); - expect(spy).not.toBeCalled(); + expect(spy).not.toHaveBeenCalled(); render(, { useRedux: true, }); await waitFor(() => { - expect(spy).toBeCalled(); + expect(spy).toHaveBeenCalled(); }); }); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx index 93f3dd6ec1c83..aece899a16078 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx @@ -47,6 +47,7 @@ describe('FilterScope', () => { activeFilterPanelKeys: `DefaultFilterId-${FilterPanels.configuration.key}`, isActive: true, validateDependencies: jest.fn(), + onModifyFilter: jest.fn(), }; const MockModal = ({ scope }: { scope?: object }) => { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx index d5b554a2f5a03..682894acc294c 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx @@ -17,13 +17,8 @@ * under the License. */ -import { FC, useCallback, useRef, useState } from 'react'; -import { - NativeFilterScope, - styled, - t, - useComponentDidUpdate, -} from '@superset-ui/core'; +import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { NativeFilterScope, styled, t } from '@superset-ui/core'; import { Radio } from 'src/components/Radio'; import { AntdForm, Typography } from 'src/components'; import { ScopingType } from './types'; @@ -32,7 +27,7 @@ import { getDefaultScopeValue, isScopingAll } from './utils'; type FilterScopeProps = { pathToFormValue?: string[]; - updateFormValues: (values: any) => void; + updateFormValues: (values: any, triggerFormChange?: boolean) => void; formFilterScope?: NativeFilterScope; forceUpdate: Function; filterScope?: NativeFilterScope; @@ -64,17 +59,19 @@ const FilterScope: FC = ({ chartId, initiallyExcludedCharts, }) => { - const [initialFilterScope] = useState( - filterScope || getDefaultScopeValue(chartId, initiallyExcludedCharts), + const initialFilterScope = useMemo( + () => filterScope || getDefaultScopeValue(chartId, initiallyExcludedCharts), + [chartId, filterScope, initiallyExcludedCharts], ); const lastSpecificScope = useRef(initialFilterScope); - const [initialScopingType] = useState( - isScopingAll(initialFilterScope, chartId) - ? ScopingType.All - : ScopingType.Specific, + const initialScopingType = useMemo( + () => + isScopingAll(initialFilterScope, chartId) + ? ScopingType.All + : ScopingType.Specific, + [chartId, initialFilterScope], ); - const [hasScopeBeenModified, setHasScopeBeenModified] = - useState(!!filterScope); + const [hasScopeBeenModified, setHasScopeBeenModified] = useState(false); const onUpdateFormValues = useCallback( (formValues: any) => { @@ -87,26 +84,24 @@ const FilterScope: FC = ({ [formScopingType, updateFormValues], ); - const updateScopes = useCallback(() => { - if (filterScope || hasScopeBeenModified) { - return; - } + const updateScopes = useCallback( + updatedFormValues => { + if (hasScopeBeenModified) { + return; + } - const newScope = getDefaultScopeValue(chartId, initiallyExcludedCharts); - updateFormValues({ - scope: newScope, - scoping: isScopingAll(newScope, chartId) - ? ScopingType.All - : ScopingType.Specific, - }); - }, [ - chartId, - filterScope, - hasScopeBeenModified, - initiallyExcludedCharts, - updateFormValues, - ]); - useComponentDidUpdate(updateScopes); + updateFormValues(updatedFormValues, false); + }, + [hasScopeBeenModified, updateFormValues], + ); + + useEffect(() => { + const updatedFormValues = { + scope: initialFilterScope, + scoping: initialScopingType, + }; + updateScopes(updatedFormValues); + }, [initialFilterScope, initialScopingType, updateScopes]); return ( diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.test.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.test.ts index 60ae8b8e5f45d..10ab8cf27f848 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.test.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/utils.test.ts @@ -18058,7 +18058,7 @@ describe('Ensure buildTree does not throw runtime errors when encountering an in initiallyExcludedCharts, () => 'Fake title', ); - }).not.toThrowError(); + }).not.toThrow(); }); it('Avoids runtime error with invalid inputs', () => { @@ -18073,7 +18073,7 @@ describe('Ensure buildTree does not throw runtime errors when encountering an in initiallyExcludedCharts, () => 'Fake title', ); - }).not.toThrowError(); + }).not.toThrow(); expect(() => { buildTree( @@ -18086,7 +18086,7 @@ describe('Ensure buildTree does not throw runtime errors when encountering an in initiallyExcludedCharts, () => 'Fake title', ); - }).not.toThrowError(); + }).not.toThrow(); expect(() => { buildTree( @@ -18099,7 +18099,7 @@ describe('Ensure buildTree does not throw runtime errors when encountering an in initiallyExcludedCharts, () => 'Fake title', ); - }).not.toThrowError(); + }).not.toThrow(); expect(() => { buildTree( @@ -18112,7 +18112,7 @@ describe('Ensure buildTree does not throw runtime errors when encountering an in initiallyExcludedCharts, () => 'Fake title', ); - }).not.toThrowError(); + }).not.toThrow(); expect(() => { buildTree( @@ -18125,7 +18125,7 @@ describe('Ensure buildTree does not throw runtime errors when encountering an in initiallyExcludedCharts, () => 'Fake title', ); - }).not.toThrowError(); + }).not.toThrow(); expect(() => { buildTree( @@ -18138,6 +18138,6 @@ describe('Ensure buildTree does not throw runtime errors when encountering an in null, () => 'Fake title', ); - }).not.toThrowError(); + }).not.toThrow(); }); }); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx index 77a423df76954..e498d2cd6a1e5 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx @@ -39,8 +39,9 @@ import { t, ClientErrorObject, getClientErrorObject, + SLOW_DEBOUNCE, } from '@superset-ui/core'; -import { isEqual } from 'lodash'; +import { debounce, isEqual } from 'lodash'; import { forwardRef, useCallback, @@ -306,6 +307,7 @@ export interface FiltersConfigFormProps { filterToEdit?: Filter; removedFilters: Record; restoreFilter: (filterId: string) => void; + onModifyFilter: (filterId: string) => void; form: FormInstance; getAvailableFilters: ( filterId: string, @@ -346,6 +348,7 @@ const FiltersConfigForm = ( restoreFilter, handleActiveFilterPanelChange, setErroredFilters, + onModifyFilter, validateDependencies, getDependencySuggestion, isActive, @@ -372,6 +375,12 @@ const FiltersConfigForm = ( const formValues = filters?.[filterId]; const formFilter = formValues || undoFormValues || defaultFormFilter; + const handleModifyFilter = useCallback(() => { + if (onModifyFilter) { + onModifyFilter(filterId); + } + }, [onModifyFilter, filterId]); + const dependencies: string[] = formFilter?.dependencies || filterToEdit?.cascadeParentIds || []; @@ -412,12 +421,28 @@ const FiltersConfigForm = ( filterToEdit?.targets[0]?.datasetId ?? mostUsedDataset(loadedDatasets, charts); + const formChanged = useCallback(() => { + form.setFields([ + { + name: 'changed', + value: true, + }, + ]); + handleModifyFilter(); + }, [form, handleModifyFilter]); + + const debouncedFormChanged = useCallback( + debounce(formChanged, SLOW_DEBOUNCE), + [], + ); + const { controlItems = {}, mainControlItems = {} } = formFilter ? getControlItemsMap({ expanded, datasetId, disabled: false, forceUpdate, + formChanged, form, filterId, filterType: formFilter?.filterType, @@ -488,7 +513,6 @@ const FiltersConfigForm = ( groupby: formFilter?.column, ...formFilter, }); - formData.extra_form_data = dependenciesDefaultValues; setNativeFilterFieldValuesWrapper({ @@ -549,6 +573,7 @@ const FiltersConfigForm = ( groupby: hasColumn ? formFilter?.column : undefined, ...formFilter, }); + newFormData.extra_form_data = dependenciesDefaultValues; const [hasDefaultValue, isRequired, defaultValueTooltip, setHasDefaultValue] = @@ -557,19 +582,10 @@ const FiltersConfigForm = ( const showDataset = !datasetId || datasetDetails || formFilter?.dataset?.label; - const formChanged = useCallback(() => { - form.setFields([ - { - name: 'changed', - value: true, - }, - ]); - }, [form]); - const updateFormValues = useCallback( - (values: any) => { + (values: any, triggerFormChange = true) => { setNativeFilterFieldValues(form, filterId, values); - formChanged(); + if (triggerFormChange) formChanged(); }, [filterId, form, formChanged], ); @@ -794,6 +810,7 @@ const FiltersConfigForm = ( granularity_sqla: column, }); forceUpdate(); + formChanged(); }} /> @@ -817,7 +834,7 @@ const FiltersConfigForm = ( hidden initialValue={NativeFilterType.NativeFilter} > - + - + @@ -920,6 +941,7 @@ const FiltersConfigForm = ( }); } forceUpdate(); + formChanged(); }} /> @@ -1018,6 +1040,7 @@ const FiltersConfigForm = ( adhoc_filters: filters, }); forceUpdate(); + formChanged(); validatePreFilter(); }} label={ @@ -1050,6 +1073,7 @@ const FiltersConfigForm = ( time_range: timeRange, }); forceUpdate(); + formChanged(); validatePreFilter(); }} /> @@ -1085,6 +1109,7 @@ const FiltersConfigForm = ( { onSortChanged(value.target.value); + formChanged(); }} > {t('Sort ascending')} @@ -1124,6 +1149,7 @@ const FiltersConfigForm = ( }); forceUpdate(); } + formChanged(); }} /> @@ -1156,9 +1182,10 @@ const FiltersConfigForm = ( } > - onEnableSingleValueChanged(value.target.value) - } + onChange={value => { + onEnableSingleValueChanged(value.target.value); + formChanged(); + }} > {t('Minimum')} @@ -1187,7 +1214,7 @@ const FiltersConfigForm = ( initialValue={filterToEdit?.description} label={{t('Description')}} > -