mirror of
https://github.com/apache/superset.git
synced 2026-08-12 11:11:01 +00:00
Compare commits
58
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
482bef1507 | ||
|
|
20c04a4663 | ||
|
|
782f5eab16 | ||
|
|
1234533c67 | ||
|
|
7f0c0aea94 | ||
|
|
d9dcbb68b7 | ||
|
|
98fba1eefe | ||
|
|
bad03b1e76 | ||
|
|
fcfafebb29 | ||
|
|
47e82b02ed | ||
|
|
a463d66c80 | ||
|
|
337da13ba7 | ||
|
|
4a3453999a | ||
|
|
58758de93d | ||
|
|
b4a8acc584 | ||
|
|
08f89690e9 | ||
|
|
f02899d38d | ||
|
|
86583f1121 | ||
|
|
26cbd71099 | ||
|
|
500ce7a02a | ||
|
|
6d8ceed10e | ||
|
|
68d65f727f | ||
|
|
f165785003 | ||
|
|
8e31c93119 | ||
|
|
4974c08f7d | ||
|
|
fa90ba976c | ||
|
|
35c3d8dfbc | ||
|
|
ee23815aff | ||
|
|
7c946ae3db | ||
|
|
3926f5c55c | ||
|
|
fdc03d4bf3 | ||
|
|
24f0aed8a7 | ||
|
|
00d2f577df | ||
|
|
c35fc71bc5 | ||
|
|
1b6d57c3f3 | ||
|
|
d089a96163 | ||
|
|
0b3fe3d60c | ||
|
|
0eeb184b6a | ||
|
|
8e7edce616 | ||
|
|
754201b3d0 | ||
|
|
925401b4e1 | ||
|
|
8368ea4094 | ||
|
|
e8a6fb24ae | ||
|
|
311b7a72dc | ||
|
|
aa496def53 | ||
|
|
aea4375255 | ||
|
|
9ab0a0179d | ||
|
|
3db613dab5 | ||
|
|
de5ca79805 | ||
|
|
aede3bb5ba | ||
|
|
408f84aea6 | ||
|
|
92c07aaf54 | ||
|
|
f405174fcf | ||
|
|
8c125d2553 | ||
|
|
fb8fca4c64 | ||
|
|
dc0c055518 | ||
|
|
09349cb1e7 | ||
|
|
ca29adb0cb |
+7
-7
@@ -25,14 +25,14 @@ little bit helps, and credit will always be given.
|
||||
|
||||
All developer and contribution documentation has moved to the Apache Superset Developer Portal:
|
||||
|
||||
**[📚 View the Developer Portal →](https://superset.apache.org/docs/developer-portal/)**
|
||||
**[📚 View the Developer Portal →](https://superset.apache.org/developer_portal/)**
|
||||
|
||||
The Developer Portal includes comprehensive guides for:
|
||||
- [Contributing Overview](https://superset.apache.org/docs/developer-portal/contributing/overview)
|
||||
- [Development Setup](https://superset.apache.org/docs/developer-portal/contributing/development-setup)
|
||||
- [Submitting Pull Requests](https://superset.apache.org/docs/developer-portal/contributing/submitting-pr)
|
||||
- [Contribution Guidelines](https://superset.apache.org/docs/developer-portal/contributing/guidelines)
|
||||
- [Code Review Process](https://superset.apache.org/docs/developer-portal/contributing/code-review)
|
||||
- [Development How-tos](https://superset.apache.org/docs/developer-portal/contributing/howtos)
|
||||
- [Contributing Overview](https://superset.apache.org/developer_portal/contributing/overview)
|
||||
- [Development Setup](https://superset.apache.org/developer_portal/contributing/development-setup)
|
||||
- [Submitting Pull Requests](https://superset.apache.org/developer_portal/contributing/submitting-pr)
|
||||
- [Contribution Guidelines](https://superset.apache.org/developer_portal/contributing/guidelines)
|
||||
- [Code Review Process](https://superset.apache.org/developer_portal/contributing/code-review)
|
||||
- [Development How-tos](https://superset.apache.org/developer_portal/contributing/howtos)
|
||||
|
||||
Source for the Developer Portal documentation is [located here](https://github.com/apache/superset/tree/master/docs/developer_portal).
|
||||
|
||||
@@ -12,11 +12,13 @@ version: 1
|
||||
SQL Lab and Explore supports [Jinja templating](https://jinja.palletsprojects.com/en/2.11.x/) in queries.
|
||||
To enable templating, the `ENABLE_TEMPLATE_PROCESSING` [feature flag](/docs/configuration/configuring-superset#feature-flags) needs to be enabled in `superset_config.py`.
|
||||
|
||||
> #### ⚠️ Security Warning
|
||||
>
|
||||
> While powerful, this feature executes template code on the server. Within the Superset security model, this is **intended functionality**, as users with permissions to edit charts and virtual datasets are considered **trusted users**.
|
||||
>
|
||||
> If you grant these permissions to untrusted users, this feature can be exploited as a **Server-Side Template Injection (SSTI)** vulnerability. Do not enable `ENABLE_TEMPLATE_PROCESSING` unless you fully understand and accept the associated security risks.
|
||||
:::warning[Security Warning]
|
||||
|
||||
While powerful, this feature executes template code on the server. Within the Superset security model, this is **intended functionality**, as users with permissions to edit charts and virtual datasets are considered **trusted users**.
|
||||
|
||||
If you grant these permissions to untrusted users, this feature can be exploited as a **Server-Side Template Injection (SSTI)** vulnerability. Do not enable `ENABLE_TEMPLATE_PROCESSING` unless you fully understand and accept the associated security risks.
|
||||
|
||||
:::
|
||||
|
||||
When templating is enabled, python code can be embedded in virtual datasets and
|
||||
in Custom SQL in the filter and metric controls in Explore. By default, the following variables are
|
||||
@@ -182,7 +184,7 @@ The available validators and names can be found in
|
||||
|
||||
In this section, we'll walkthrough the pre-defined Jinja macros in Superset.
|
||||
|
||||
**Current Username**
|
||||
### Current Username
|
||||
|
||||
The `{{ current_username() }}` macro returns the `username` of the currently logged in user.
|
||||
|
||||
@@ -197,7 +199,7 @@ cache key by adding the following parameter to your Jinja code:
|
||||
{{ current_username(add_to_cache_keys=False) }}
|
||||
```
|
||||
|
||||
**Current User ID**
|
||||
### Current User ID
|
||||
|
||||
The `{{ current_user_id() }}` macro returns the account ID of the currently logged in user.
|
||||
|
||||
@@ -212,7 +214,7 @@ cache key by adding the following parameter to your Jinja code:
|
||||
{{ current_user_id(add_to_cache_keys=False) }}
|
||||
```
|
||||
|
||||
**Current User Email**
|
||||
### Current User Email
|
||||
|
||||
The `{{ current_user_email() }}` macro returns the email address of the currently logged in user.
|
||||
|
||||
@@ -227,7 +229,7 @@ cache key by adding the following parameter to your Jinja code:
|
||||
{{ current_user_email(add_to_cache_keys=False) }}
|
||||
```
|
||||
|
||||
**Current User Roles**
|
||||
### Current User Roles
|
||||
|
||||
The `{{ current_user_roles() }}` macro returns an array of roles for the logged in user.
|
||||
|
||||
@@ -257,7 +259,7 @@ Will be rendered as:
|
||||
SELECT * FROM users WHERE role IN ('admin', 'viewer')
|
||||
```
|
||||
|
||||
**Current User RLS Rules**
|
||||
### Current User RLS Rules
|
||||
|
||||
The `{{ current_user_rls_rules() }}` macro returns an array of RLS rules applied to the current dataset for the logged in user.
|
||||
|
||||
@@ -265,7 +267,7 @@ If you have caching enabled in your Superset configuration, then the list of RLS
|
||||
by Superset when calculating the cache key. A cache key is a unique identifier that determines if there's a
|
||||
cache hit in the future and Superset can retrieve cached data.
|
||||
|
||||
**Custom URL Parameters**
|
||||
### Custom URL Parameters
|
||||
|
||||
The `{{ url_param('custom_variable') }}` macro lets you define arbitrary URL
|
||||
parameters and reference them in your SQL code.
|
||||
@@ -299,7 +301,7 @@ Here's a concrete example:
|
||||
WHERE country_code = 'US'
|
||||
```
|
||||
|
||||
**Explicitly Including Values in Cache Key**
|
||||
### Explicitly Including Values in Cache Key
|
||||
|
||||
The `{{ cache_key_wrapper() }}` function explicitly instructs Superset to add a value to the
|
||||
accumulated list of values used in the calculation of the cache key.
|
||||
@@ -311,7 +313,7 @@ in the cache key. You can gain more context
|
||||
Note that this function powers the caching of the `user_id` and `username` values
|
||||
in the `current_user_id()` and `current_username()` function calls (if you have caching enabled).
|
||||
|
||||
**Filter Values**
|
||||
### Filter Values
|
||||
|
||||
You can retrieve the value for a specific filter as a list using `{{ filter_values() }}`.
|
||||
|
||||
@@ -332,7 +334,7 @@ GROUP BY action
|
||||
|
||||
There `where_in` filter converts the list of values from `filter_values('action_type')` into a string suitable for an `IN` expression.
|
||||
|
||||
**Filters for a Specific Column**
|
||||
### Filters for a Specific Column
|
||||
|
||||
The `{{ get_filters() }}` macro returns the filters applied to a given column. In addition to
|
||||
returning the values (similar to how `filter_values()` does), the `get_filters()` macro
|
||||
@@ -394,7 +396,7 @@ Here's a concrete example:
|
||||
order by lineage, level
|
||||
```
|
||||
|
||||
**Time Filter**
|
||||
### Time Filter
|
||||
|
||||
The `{{ get_time_filter() }}` macro returns the time filter applied to a specific column. This is useful if you want
|
||||
to handle time filters inside the virtual dataset, as by default the time filter is placed on the outer query. This can
|
||||
@@ -469,7 +471,7 @@ WHERE
|
||||
AND dttm < {{ time_filter.to_expr }}
|
||||
```
|
||||
|
||||
**Datasets**
|
||||
### Datasets
|
||||
|
||||
It's possible to query physical and virtual datasets using the `dataset` macro. This is useful if you've defined computed columns and metrics on your datasets, and want to reuse the definition in adhoc SQL Lab queries.
|
||||
|
||||
@@ -493,7 +495,7 @@ Since metrics are aggregations, the resulting SQL expression will be grouped by
|
||||
SELECT * FROM {{ dataset(42, include_metrics=True, columns=["ds", "category"]) }} LIMIT 10
|
||||
```
|
||||
|
||||
**Metrics**
|
||||
### Metrics
|
||||
|
||||
The `{{ metric('metric_key', dataset_id) }}` macro can be used to retrieve the metric SQL syntax from a dataset. This can be useful for different purposes:
|
||||
|
||||
@@ -511,7 +513,7 @@ The parameter can be used in SQL Lab, or when fetching a metric from another dat
|
||||
|
||||
Superset supports [builtin filters from the Jinja2 templating package](https://jinja.palletsprojects.com/en/stable/templates/#builtin-filters). Custom filters have also been implemented:
|
||||
|
||||
**Where In**
|
||||
### Where In
|
||||
Parses a list into a SQL-compatible statement. This is useful with macros that return an array (for example the `filter_values` macro):
|
||||
|
||||
```
|
||||
@@ -528,7 +530,7 @@ Dashboard filter without any value applied
|
||||
{{ filter_values('column')|where_in(default_to_none=True) }} => None
|
||||
```
|
||||
|
||||
**To Datetime**
|
||||
### To Datetime
|
||||
|
||||
Loads a string as a `datetime` object. This is useful when performing date operations. For example:
|
||||
```
|
||||
|
||||
+11
-11
@@ -28,10 +28,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^6.1.0",
|
||||
"@docusaurus/core": "3.9.1",
|
||||
"@docusaurus/plugin-client-redirects": "3.9.1",
|
||||
"@docusaurus/preset-classic": "3.9.1",
|
||||
"@docusaurus/theme-mermaid": "^3.9.1",
|
||||
"@docusaurus/core": "3.9.2",
|
||||
"@docusaurus/plugin-client-redirects": "3.9.2",
|
||||
"@docusaurus/preset-classic": "3.9.2",
|
||||
"@docusaurus/theme-mermaid": "^3.9.2",
|
||||
"@emotion/core": "^10.0.27",
|
||||
"@emotion/react": "^11.13.3",
|
||||
"@emotion/styled": "^10.0.27",
|
||||
@@ -49,8 +49,8 @@
|
||||
"@storybook/preview-api": "^8.6.11",
|
||||
"@storybook/theming": "^8.6.11",
|
||||
"@superset-ui/core": "^0.20.4",
|
||||
"antd": "^5.27.4",
|
||||
"caniuse-lite": "^1.0.30001750",
|
||||
"antd": "^5.27.6",
|
||||
"caniuse-lite": "^1.0.30001751",
|
||||
"docusaurus-plugin-less": "^2.0.2",
|
||||
"json-bigint": "^1.0.0",
|
||||
"less": "^4.4.2",
|
||||
@@ -63,25 +63,25 @@
|
||||
"remark-import-partial": "^0.0.2",
|
||||
"reselect": "^5.1.1",
|
||||
"storybook": "^8.6.11",
|
||||
"swagger-ui-react": "^5.29.4",
|
||||
"swagger-ui-react": "^5.29.5",
|
||||
"tinycolor2": "^1.4.2",
|
||||
"ts-loader": "^9.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "^3.9.1",
|
||||
"@docusaurus/tsconfig": "^3.9.1",
|
||||
"@eslint/js": "^9.37.0",
|
||||
"@docusaurus/tsconfig": "^3.9.2",
|
||||
"@eslint/js": "^9.38.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"@typescript-eslint/eslint-plugin": "^8.37.0",
|
||||
"@typescript-eslint/parser": "^8.46.0",
|
||||
"eslint": "^9.37.0",
|
||||
"eslint": "^9.38.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.3",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^16.4.0",
|
||||
"prettier": "^3.6.2",
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.46.1",
|
||||
"typescript-eslint": "^8.46.2",
|
||||
"webpack": "^5.102.1"
|
||||
},
|
||||
"browserslist": {
|
||||
|
||||
+355
-357
@@ -1593,10 +1593,10 @@
|
||||
marked "^16.3.0"
|
||||
zod "^4.1.8"
|
||||
|
||||
"@docusaurus/babel@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/babel/-/babel-3.9.1.tgz#5297195ab34df9e184e3e2fe20de1a2e1b2a22e8"
|
||||
integrity sha512-/uoi3oG+wvbVWNBRfPrzrEslOSeLxrQEyWMywK51TLDFTANqIRivzkMusudh5bdDty8fXzCYUT+tg5t697jYqg==
|
||||
"@docusaurus/babel@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/babel/-/babel-3.9.2.tgz#f956c638baeccf2040e482c71a742bc7e35fdb22"
|
||||
integrity sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA==
|
||||
dependencies:
|
||||
"@babel/core" "^7.25.9"
|
||||
"@babel/generator" "^7.25.9"
|
||||
@@ -1608,23 +1608,23 @@
|
||||
"@babel/runtime" "^7.25.9"
|
||||
"@babel/runtime-corejs3" "^7.25.9"
|
||||
"@babel/traverse" "^7.25.9"
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
babel-plugin-dynamic-import-node "^2.3.3"
|
||||
fs-extra "^11.1.1"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/bundler@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/bundler/-/bundler-3.9.1.tgz#6b78c152cf364d706249f6978f8e3fedf576b118"
|
||||
integrity sha512-E1c9DgNmAz4NqbNtiJVp4UgjLtr8O01IgtXD/NDQ4PZaK8895cMiTOgb3k7mN0qX8A3lb8vqyrPJ842+yMpuUg==
|
||||
"@docusaurus/bundler@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/bundler/-/bundler-3.9.2.tgz#0ca82cda4acf13a493e3f66061aea351e9d356cf"
|
||||
integrity sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA==
|
||||
dependencies:
|
||||
"@babel/core" "^7.25.9"
|
||||
"@docusaurus/babel" "3.9.1"
|
||||
"@docusaurus/cssnano-preset" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/babel" "3.9.2"
|
||||
"@docusaurus/cssnano-preset" "3.9.2"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
babel-loader "^9.2.1"
|
||||
clean-css "^5.3.3"
|
||||
copy-webpack-plugin "^11.0.0"
|
||||
@@ -1644,18 +1644,18 @@
|
||||
webpack "^5.95.0"
|
||||
webpackbar "^6.0.1"
|
||||
|
||||
"@docusaurus/core@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.9.1.tgz#be4d859464fee8889794d8527f884e931d591f2e"
|
||||
integrity sha512-FWDk1LIGD5UR5Zmm9rCrXRoxZUgbwuP6FBA7rc50DVfzqDOMkeMe3NyJhOsA2dF0zBE3VbHEIMmTjKwTZJwbaA==
|
||||
"@docusaurus/core@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.9.2.tgz#cc970f29b85a8926d63c84f8cffdcda43ed266ff"
|
||||
integrity sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==
|
||||
dependencies:
|
||||
"@docusaurus/babel" "3.9.1"
|
||||
"@docusaurus/bundler" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/mdx-loader" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-common" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/babel" "3.9.2"
|
||||
"@docusaurus/bundler" "3.9.2"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/mdx-loader" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-common" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
boxen "^6.2.1"
|
||||
chalk "^4.1.2"
|
||||
chokidar "^3.5.3"
|
||||
@@ -1692,32 +1692,32 @@
|
||||
webpack-dev-server "^5.2.2"
|
||||
webpack-merge "^6.0.1"
|
||||
|
||||
"@docusaurus/cssnano-preset@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.1.tgz#fa57c81a3f41e4d118115f86c85a71aed6b90f49"
|
||||
integrity sha512-2y7+s7RWQMqBg+9ejeKwvZs7Bdw/hHIVJIodwMXbs2kr+S48AhcmAfdOh6Cwm0unJb0hJUshN0ROwRoQMwl3xg==
|
||||
"@docusaurus/cssnano-preset@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz#523aab65349db3c51a77f2489048d28527759428"
|
||||
integrity sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==
|
||||
dependencies:
|
||||
cssnano-preset-advanced "^6.1.2"
|
||||
postcss "^8.5.4"
|
||||
postcss-sort-media-queries "^5.2.0"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/logger@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.9.1.tgz#0209c4c1044ee35d89dbf676e3cbb5dc8b59c82b"
|
||||
integrity sha512-C9iFzXwHzwvGlisE4bZx+XQE0JIqlGAYAd5LzpR7fEDgjctu7yL8bE5U4nTNywXKHURDzMt4RJK8V6+stFHVkA==
|
||||
"@docusaurus/logger@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.9.2.tgz#6ec6364b90f5a618a438cc9fd01ac7376869f92a"
|
||||
integrity sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA==
|
||||
dependencies:
|
||||
chalk "^4.1.2"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/mdx-loader@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.9.1.tgz#0ef77bee13450c83c18338f8e5f1753ed2e9ee3f"
|
||||
integrity sha512-/1PY8lqry8jCt0qZddJSpc0U2sH6XC27kVJZfpA7o2TiQ3mdBQyH5AVbj/B2m682B1ounE+XjI0LdpOkAQLPoA==
|
||||
"@docusaurus/mdx-loader@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz#78d238de6c6203fa811cc2a7e90b9b79e111408c"
|
||||
integrity sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ==
|
||||
dependencies:
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
"@mdx-js/mdx" "^3.0.0"
|
||||
"@slorber/remark-comment" "^1.0.0"
|
||||
escape-html "^1.0.3"
|
||||
@@ -1740,12 +1740,12 @@
|
||||
vfile "^6.0.1"
|
||||
webpack "^5.88.1"
|
||||
|
||||
"@docusaurus/module-type-aliases@3.9.1", "@docusaurus/module-type-aliases@^3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.1.tgz#201959a22e7b30881cf879a21d2ae5b26415b705"
|
||||
integrity sha512-YBce3GbJGGcMbJTyHcnEOMvdXqg41pa5HsrMCGA5Rm4z0h0tHS6YtEldj0mlfQRhCG7Y0VD66t2tb87Aom+11g==
|
||||
"@docusaurus/module-type-aliases@3.9.2", "@docusaurus/module-type-aliases@^3.9.1":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.2.tgz#993c7cb0114363dea5ef6855e989b3ad4b843a34"
|
||||
integrity sha512-8qVe2QA9hVLzvnxP46ysuofJUIc/yYQ82tvA/rBTrnpXtCjNSFLxEZfd5U8cYZuJIVlkPxamsIgwd5tGZXfvew==
|
||||
dependencies:
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@types/history" "^4.7.11"
|
||||
"@types/react" "*"
|
||||
"@types/react-router-config" "*"
|
||||
@@ -1753,34 +1753,34 @@
|
||||
react-helmet-async "npm:@slorber/react-helmet-async@1.3.0"
|
||||
react-loadable "npm:@docusaurus/react-loadable@6.0.0"
|
||||
|
||||
"@docusaurus/plugin-client-redirects@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.9.1.tgz#06e07487f1596c62536d50afac81535d5fe60a20"
|
||||
integrity sha512-+1InCGvAnw46H+TnVqxaYlJC0qy9AY5gTMgTx2ZFryjAsImJNs3i1pEYW/iUTVbOdtWRj3E/87E4ehbBIaA1TA==
|
||||
"@docusaurus/plugin-client-redirects@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.9.2.tgz#9c27025c72aeeedeb783a94720163911567da0e8"
|
||||
integrity sha512-lUgMArI9vyOYMzLRBUILcg9vcPTCyyI2aiuXq/4npcMVqOr6GfmwtmBYWSbNMlIUM0147smm4WhpXD0KFboffw==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-common" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-common" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
eta "^2.2.0"
|
||||
fs-extra "^11.1.1"
|
||||
lodash "^4.17.21"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-content-blog@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.1.tgz#bf6619847065360d52abc5bf1da307f5ce2a19f8"
|
||||
integrity sha512-vT6kIimpJLWvW9iuWzH4u7VpTdsGlmn4yfyhq0/Kb1h4kf9uVouGsTmrD7WgtYBUG1P+TSmQzUUQa+ALBSRTig==
|
||||
"@docusaurus/plugin-content-blog@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.2.tgz#d5ce51eb7757bdab0515e2dd26a793ed4e119df9"
|
||||
integrity sha512-3I2HXy3L1QcjLJLGAoTvoBnpOwa6DPUa3Q0dMK19UTY9mhPkKQg/DYhAGTiBUKcTR0f08iw7kLPqOhIgdV3eVQ==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/mdx-loader" "3.9.1"
|
||||
"@docusaurus/theme-common" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-common" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/mdx-loader" "3.9.2"
|
||||
"@docusaurus/theme-common" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-common" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
cheerio "1.0.0-rc.12"
|
||||
feed "^4.2.2"
|
||||
fs-extra "^11.1.1"
|
||||
@@ -1792,20 +1792,20 @@
|
||||
utility-types "^3.10.0"
|
||||
webpack "^5.88.1"
|
||||
|
||||
"@docusaurus/plugin-content-docs@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.1.tgz#e3e75d4aa310689c262c18e10010788e53f101ec"
|
||||
integrity sha512-DyLk9BIA6I9gPIuia8XIL+XIEbNnExam6AHzRsfrEq4zJr7k/DsWW7oi4aJMepDnL7jMRhpVcdsCxdjb0/A9xg==
|
||||
"@docusaurus/plugin-content-docs@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz#cd8f2d1c06e53c3fa3d24bdfcb48d237bf2d6b2e"
|
||||
integrity sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/mdx-loader" "3.9.1"
|
||||
"@docusaurus/module-type-aliases" "3.9.1"
|
||||
"@docusaurus/theme-common" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-common" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/mdx-loader" "3.9.2"
|
||||
"@docusaurus/module-type-aliases" "3.9.2"
|
||||
"@docusaurus/theme-common" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-common" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
"@types/react-router-config" "^5.0.7"
|
||||
combine-promises "^1.1.0"
|
||||
fs-extra "^11.1.1"
|
||||
@@ -1816,142 +1816,142 @@
|
||||
utility-types "^3.10.0"
|
||||
webpack "^5.88.1"
|
||||
|
||||
"@docusaurus/plugin-content-pages@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.1.tgz#044b8adbd2a673ff22630a74b3e0ce482761655d"
|
||||
integrity sha512-/1wFzRnXYASI+Nv9ck9IVPIMw0O5BGQ8ZVhDzEwhkL+tl44ycvSnY6PIe6rW2HLxsw61Z3WFwAiU8+xMMtMZpg==
|
||||
"@docusaurus/plugin-content-pages@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.2.tgz#22db6c88ade91cec0a9e87a00b8089898051b08d"
|
||||
integrity sha512-s4849w/p4noXUrGpPUF0BPqIAfdAe76BLaRGAGKZ1gTDNiGxGcpsLcwJ9OTi1/V8A+AzvsmI9pkjie2zjIQZKA==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/mdx-loader" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/mdx-loader" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
fs-extra "^11.1.1"
|
||||
tslib "^2.6.0"
|
||||
webpack "^5.88.1"
|
||||
|
||||
"@docusaurus/plugin-css-cascade-layers@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.1.tgz#958a04679279e787d14fd3cc423ad35c580dc6fc"
|
||||
integrity sha512-/QyW2gRCk/XE3ttCK/ERIgle8KJ024dBNKMu6U5SmpJvuT2il1n5jR/48Pp/9wEwut8WVml4imNm6X8JsL5A0Q==
|
||||
"@docusaurus/plugin-css-cascade-layers@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.2.tgz#358c85f63f1c6a11f611f1b8889d9435c11b22f8"
|
||||
integrity sha512-w1s3+Ss+eOQbscGM4cfIFBlVg/QKxyYgj26k5AnakuHkKxH6004ZtuLe5awMBotIYF2bbGDoDhpgQ4r/kcj4rQ==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-debug@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.9.1.tgz#5dbe01771176697f427b89a1ff023a3967c3e674"
|
||||
integrity sha512-qPeAuk0LccC251d7jg2MRhNI+o7niyqa924oEM/AxnZJvIpMa596aAxkRImiAqNN6+gtLE1Hkrz/RHUH2HDGsA==
|
||||
"@docusaurus/plugin-debug@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.9.2.tgz#b5df4db115583f5404a252dbf66f379ff933e53c"
|
||||
integrity sha512-j7a5hWuAFxyQAkilZwhsQ/b3T7FfHZ+0dub6j/GxKNFJp2h9qk/P1Bp7vrGASnvA9KNQBBL1ZXTe7jlh4VdPdA==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
fs-extra "^11.1.1"
|
||||
react-json-view-lite "^2.3.0"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-google-analytics@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.1.tgz#226e39ed6d0a5eb3978dc5189bc9676235756446"
|
||||
integrity sha512-k4Qq2HphqOrIU/CevGPdEO1yJnWUI8m0zOJsYt5NfMJwNsIn/gDD6gv/DKD+hxHndQT5pacsfBd4BWHZVNVroQ==
|
||||
"@docusaurus/plugin-google-analytics@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.2.tgz#857fe075fdeccdf6959e62954d9efe39769fa247"
|
||||
integrity sha512-mAwwQJ1Us9jL/lVjXtErXto4p4/iaLlweC54yDUK1a97WfkC6Z2k5/769JsFgwOwOP+n5mUQGACXOEQ0XDuVUw==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-google-gtag@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.1.tgz#971b075898d46d1a59482b2873ccb9aa2e679910"
|
||||
integrity sha512-n9BURBiQyJKI/Ecz35IUjXYwXcgNCSq7/eA07+ZYcDiSyH2p/EjPf8q/QcZG3CyEJPZ/SzGkDHePfcVPahY4Gg==
|
||||
"@docusaurus/plugin-google-gtag@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.2.tgz#df75b1a90ae9266b0471909ba0265f46d5dcae62"
|
||||
integrity sha512-YJ4lDCphabBtw19ooSlc1MnxtYGpjFV9rEdzjLsUnBCeis2djUyCozZaFhCg6NGEwOn7HDDyMh0yzcdRpnuIvA==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
"@types/gtag.js" "^0.0.12"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-google-tag-manager@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.1.tgz#b26770d8bb07cedc1e01305cd9d66c2e4ce6d654"
|
||||
integrity sha512-rZAQZ25ZuXaThBajxzLjXieTDUCMmBzfAA6ThElQ3o7Q+LEpOjCIrwGFau0KLY9HeG6x91+FwwsAM8zeApYDrg==
|
||||
"@docusaurus/plugin-google-tag-manager@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.2.tgz#d1a3cf935acb7d31b84685e92d70a1d342946677"
|
||||
integrity sha512-LJtIrkZN/tuHD8NqDAW1Tnw0ekOwRTfobWPsdO15YxcicBo2ykKF0/D6n0vVBfd3srwr9Z6rzrIWYrMzBGrvNw==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-sitemap@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.1.tgz#e84717c1e52f3a61f9fea414ef98ebe025e7ffd2"
|
||||
integrity sha512-k/bf5cXDxAJUYTzqatgFJwmZsLUbIgl6S8AdZMKGG2Mv2wcOHt+EQNN9qPyWZ5/9cFj+Q8f8DN+KQheBMYLong==
|
||||
"@docusaurus/plugin-sitemap@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.2.tgz#e1d9f7012942562cc0c6543d3cb2cdc4ae713dc4"
|
||||
integrity sha512-WLh7ymgDXjG8oPoM/T4/zUP7KcSuFYRZAUTl8vR6VzYkfc18GBM4xLhcT+AKOwun6kBivYKUJf+vlqYJkm+RHw==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-common" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-common" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
fs-extra "^11.1.1"
|
||||
sitemap "^7.1.1"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-svgr@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.1.tgz#394ad2b8da3af587a0f68167252b4bf99fb72351"
|
||||
integrity sha512-TeZOXT2PSdTNR1OpDJMkYqFyX7MMhbd4t16hQByXksgZQCXNyw3Dio+KaDJ2Nj+LA4WkOvsk45bWgYG5MAaXSQ==
|
||||
"@docusaurus/plugin-svgr@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.2.tgz#62857ed79d97c0150d25f7e7380fdee65671163a"
|
||||
integrity sha512-n+1DE+5b3Lnf27TgVU5jM1d4x5tUh2oW5LTsBxJX4PsAPV0JGcmI6p3yLYtEY0LRVEIJh+8RsdQmRE66wSV8mw==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
"@svgr/core" "8.1.0"
|
||||
"@svgr/webpack" "^8.1.0"
|
||||
tslib "^2.6.0"
|
||||
webpack "^5.88.1"
|
||||
|
||||
"@docusaurus/preset-classic@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.9.1.tgz#58d86664b5c9779578092556a0e6ae5ccebbd6c0"
|
||||
integrity sha512-ZHga2xsxxsyd0dN1BpLj8S889Eu9eMBuj2suqxdw/vaaXu/FjJ8KEGbcaeo6nHPo8VQcBBnPEdkBtSDm2TfMNw==
|
||||
"@docusaurus/preset-classic@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.9.2.tgz#85cc4f91baf177f8146c9ce896dfa1f0fd377050"
|
||||
integrity sha512-IgyYO2Gvaigi21LuDIe+nvmN/dfGXAiMcV/murFqcpjnZc7jxFAxW+9LEjdPt61uZLxG4ByW/oUmX/DDK9t/8w==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/plugin-content-blog" "3.9.1"
|
||||
"@docusaurus/plugin-content-docs" "3.9.1"
|
||||
"@docusaurus/plugin-content-pages" "3.9.1"
|
||||
"@docusaurus/plugin-css-cascade-layers" "3.9.1"
|
||||
"@docusaurus/plugin-debug" "3.9.1"
|
||||
"@docusaurus/plugin-google-analytics" "3.9.1"
|
||||
"@docusaurus/plugin-google-gtag" "3.9.1"
|
||||
"@docusaurus/plugin-google-tag-manager" "3.9.1"
|
||||
"@docusaurus/plugin-sitemap" "3.9.1"
|
||||
"@docusaurus/plugin-svgr" "3.9.1"
|
||||
"@docusaurus/theme-classic" "3.9.1"
|
||||
"@docusaurus/theme-common" "3.9.1"
|
||||
"@docusaurus/theme-search-algolia" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/plugin-content-blog" "3.9.2"
|
||||
"@docusaurus/plugin-content-docs" "3.9.2"
|
||||
"@docusaurus/plugin-content-pages" "3.9.2"
|
||||
"@docusaurus/plugin-css-cascade-layers" "3.9.2"
|
||||
"@docusaurus/plugin-debug" "3.9.2"
|
||||
"@docusaurus/plugin-google-analytics" "3.9.2"
|
||||
"@docusaurus/plugin-google-gtag" "3.9.2"
|
||||
"@docusaurus/plugin-google-tag-manager" "3.9.2"
|
||||
"@docusaurus/plugin-sitemap" "3.9.2"
|
||||
"@docusaurus/plugin-svgr" "3.9.2"
|
||||
"@docusaurus/theme-classic" "3.9.2"
|
||||
"@docusaurus/theme-common" "3.9.2"
|
||||
"@docusaurus/theme-search-algolia" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
|
||||
"@docusaurus/theme-classic@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.9.1.tgz#790fb1b8058d0572632211023ead238c1a6450e0"
|
||||
integrity sha512-LrAIu/mQ04nG6s1cssC0TMmICD8twFIIn/hJ5Pd9uIPQvtKnyAKEn12RefopAul5KfMo9kixPaqogV5jIJr26w==
|
||||
"@docusaurus/theme-classic@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.9.2.tgz#6e514f99a0ff42b80afcf42d5e5d042618311ce0"
|
||||
integrity sha512-IGUsArG5hhekXd7RDb11v94ycpJpFdJPkLnt10fFQWOVxAtq5/D7hT6lzc2fhyQKaaCE62qVajOMKL7OiAFAIA==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/mdx-loader" "3.9.1"
|
||||
"@docusaurus/module-type-aliases" "3.9.1"
|
||||
"@docusaurus/plugin-content-blog" "3.9.1"
|
||||
"@docusaurus/plugin-content-docs" "3.9.1"
|
||||
"@docusaurus/plugin-content-pages" "3.9.1"
|
||||
"@docusaurus/theme-common" "3.9.1"
|
||||
"@docusaurus/theme-translations" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-common" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/mdx-loader" "3.9.2"
|
||||
"@docusaurus/module-type-aliases" "3.9.2"
|
||||
"@docusaurus/plugin-content-blog" "3.9.2"
|
||||
"@docusaurus/plugin-content-docs" "3.9.2"
|
||||
"@docusaurus/plugin-content-pages" "3.9.2"
|
||||
"@docusaurus/theme-common" "3.9.2"
|
||||
"@docusaurus/theme-translations" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-common" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
"@mdx-js/react" "^3.0.0"
|
||||
clsx "^2.0.0"
|
||||
infima "0.2.0-alpha.45"
|
||||
@@ -1965,15 +1965,15 @@
|
||||
tslib "^2.6.0"
|
||||
utility-types "^3.10.0"
|
||||
|
||||
"@docusaurus/theme-common@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.9.1.tgz#095cbeab489d51380143951508571888f4d2928d"
|
||||
integrity sha512-j9adi961F+6Ps9d0jcb5BokMcbjXAAJqKkV43eo8nh4YgmDj7KUNDX4EnOh/MjTQeO06oPY5cxp3yUXdW/8Ggw==
|
||||
"@docusaurus/theme-common@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.9.2.tgz#487172c6fef9815c2746ef62a71e4f5b326f9ba5"
|
||||
integrity sha512-6c4DAbR6n6nPbnZhY2V3tzpnKnGL+6aOsLvFL26VRqhlczli9eWG0VDUNoCQEPnGwDMhPS42UhSAnz5pThm5Ag==
|
||||
dependencies:
|
||||
"@docusaurus/mdx-loader" "3.9.1"
|
||||
"@docusaurus/module-type-aliases" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-common" "3.9.1"
|
||||
"@docusaurus/mdx-loader" "3.9.2"
|
||||
"@docusaurus/module-type-aliases" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-common" "3.9.2"
|
||||
"@types/history" "^4.7.11"
|
||||
"@types/react" "*"
|
||||
"@types/react-router-config" "*"
|
||||
@@ -1983,32 +1983,32 @@
|
||||
tslib "^2.6.0"
|
||||
utility-types "^3.10.0"
|
||||
|
||||
"@docusaurus/theme-mermaid@^3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-mermaid/-/theme-mermaid-3.9.1.tgz#92de20580489e05b3da6716503fda17e5a337a4d"
|
||||
integrity sha512-aKMFlQfxueVBPdCdrNSshG12fOkJXSn1sb6EhI/sGn3UpiTEiazJm4QLP6NoF78mqq8O5Ar2Yll+iHWLvCsuZQ==
|
||||
"@docusaurus/theme-mermaid@^3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-mermaid/-/theme-mermaid-3.9.2.tgz#f065e4b4b319560ddd8c3be65ce9dd19ce1d5cc8"
|
||||
integrity sha512-5vhShRDq/ntLzdInsQkTdoKWSzw8d1jB17sNPYhA/KvYYFXfuVEGHLM6nrf8MFbV8TruAHDG21Fn3W4lO8GaDw==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/module-type-aliases" "3.9.1"
|
||||
"@docusaurus/theme-common" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/module-type-aliases" "3.9.2"
|
||||
"@docusaurus/theme-common" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
mermaid ">=11.6.0"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/theme-search-algolia@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.1.tgz#2f2ad5212201a1bed3acf8527ae6d81a079e654e"
|
||||
integrity sha512-WjM28bzlgfT6nHlEJemkwyGVpvGsZWPireV/w+wZ1Uo64xCZ8lNOb4xwQRukDaLSed3oPBN0gSnu06l5VuCXHg==
|
||||
"@docusaurus/theme-search-algolia@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.2.tgz#420fd5b27fc1673b48151fdc9fe7167ba135ed50"
|
||||
integrity sha512-GBDSFNwjnh5/LdkxCKQHkgO2pIMX1447BxYUBG2wBiajS21uj64a+gH/qlbQjDLxmGrbrllBrtJkUHxIsiwRnw==
|
||||
dependencies:
|
||||
"@docsearch/react" "^3.9.0 || ^4.1.0"
|
||||
"@docusaurus/core" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/plugin-content-docs" "3.9.1"
|
||||
"@docusaurus/theme-common" "3.9.1"
|
||||
"@docusaurus/theme-translations" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-validation" "3.9.1"
|
||||
"@docusaurus/core" "3.9.2"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/plugin-content-docs" "3.9.2"
|
||||
"@docusaurus/theme-common" "3.9.2"
|
||||
"@docusaurus/theme-translations" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-validation" "3.9.2"
|
||||
algoliasearch "^5.37.0"
|
||||
algoliasearch-helper "^3.26.0"
|
||||
clsx "^2.0.0"
|
||||
@@ -2018,23 +2018,23 @@
|
||||
tslib "^2.6.0"
|
||||
utility-types "^3.10.0"
|
||||
|
||||
"@docusaurus/theme-translations@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.9.1.tgz#189f1942d0178bc0da659db88c07682c7d7191ee"
|
||||
integrity sha512-mUQd49BSGKTiM6vP9+JFgRJL28lMIN3PUvXjF3rzuOHMByUZUBNwCt26Z23GkKiSIOrRkjKoaBNTipR/MHdYSQ==
|
||||
"@docusaurus/theme-translations@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.9.2.tgz#238cd69c2da92d612be3d3b4f95944c1d0f1e041"
|
||||
integrity sha512-vIryvpP18ON9T9rjgMRFLr2xJVDpw1rtagEGf8Ccce4CkTrvM/fRB8N2nyWYOW5u3DdjkwKw5fBa+3tbn9P4PA==
|
||||
dependencies:
|
||||
fs-extra "^11.1.1"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/tsconfig@^3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/tsconfig/-/tsconfig-3.9.1.tgz#a39cb74021f16dd4794db9182de812303817528e"
|
||||
integrity sha512-stdzM1dNDgRO0OvxeznXlE3N1igUoeHPNJjiKqyffLizgpVgNXJBAWeG6fuoYiCH4udGUBqy2dyM+1+kG2/UPQ==
|
||||
"@docusaurus/tsconfig@^3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/tsconfig/-/tsconfig-3.9.2.tgz#7f440e0ae665b841e1d487749037f26a0275f9c1"
|
||||
integrity sha512-j6/Fp4Rlpxsc632cnRnl5HpOWeb6ZKssDj6/XzzAzVGXXfm9Eptx3rxCC+fDzySn9fHTS+CWJjPineCR1bB5WQ==
|
||||
|
||||
"@docusaurus/types@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.9.1.tgz#e4fdaf0b91ea014a6aae0d8b62d59f3f020117b6"
|
||||
integrity sha512-ElekJ29sk39s5LTEZMByY1c2oH9FMtw7KbWFU3BtuQ1TytfIK39HhUivDEJvm5KCLyEnnfUZlvSNDXeyk0vzAA==
|
||||
"@docusaurus/types@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.9.2.tgz#e482cf18faea0d1fa5ce0e3f1e28e0f32d2593eb"
|
||||
integrity sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==
|
||||
dependencies:
|
||||
"@mdx-js/mdx" "^3.0.0"
|
||||
"@types/history" "^4.7.11"
|
||||
@@ -2047,36 +2047,36 @@
|
||||
webpack "^5.95.0"
|
||||
webpack-merge "^5.9.0"
|
||||
|
||||
"@docusaurus/utils-common@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.9.1.tgz#202778391caed923c2527a166a3aae3a22b2dcad"
|
||||
integrity sha512-4M1u5Q8Zn2CYL2TJ864M51FV4YlxyGyfC3x+7CLuR6xsyTVNBNU4QMcPgsTHRS9J2+X6Lq7MyH6hiWXyi/sXUQ==
|
||||
"@docusaurus/utils-common@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.9.2.tgz#e89bfcf43d66359f43df45293fcdf22814847460"
|
||||
integrity sha512-I53UC1QctruA6SWLvbjbhCpAw7+X7PePoe5pYcwTOEXD/PxeP8LnECAhTHHwWCblyUX5bMi4QLRkxvyZ+IT8Aw==
|
||||
dependencies:
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/utils-validation@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.9.1.tgz#8f9816b31ffb647539881f3c153d46f54e6399f7"
|
||||
integrity sha512-5bzab5si3E1udrlZuVGR17857Lfwe8iFPoy5AvMP9PXqDfoyIKT7gDQgAmxdRDMurgHaJlyhXEHHdzDKkOxxZQ==
|
||||
"@docusaurus/utils-validation@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.9.2.tgz#04aec285604790806e2fc5aa90aa950dc7ba75ae"
|
||||
integrity sha512-l7yk3X5VnNmATbwijJkexdhulNsQaNDwoagiwujXoxFbWLcxHQqNQ+c/IAlzrfMMOfa/8xSBZ7KEKDesE/2J7A==
|
||||
dependencies:
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/utils" "3.9.1"
|
||||
"@docusaurus/utils-common" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/utils" "3.9.2"
|
||||
"@docusaurus/utils-common" "3.9.2"
|
||||
fs-extra "^11.2.0"
|
||||
joi "^17.9.2"
|
||||
js-yaml "^4.1.0"
|
||||
lodash "^4.17.21"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/utils@3.9.1":
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.9.1.tgz#9b78849a2be5e3023580b800409aae36a0da6dc8"
|
||||
integrity sha512-YAL4yhhWLl9DXuf5MVig260a6INz4MehrBGFU/CZu8yXmRiYEuQvRFWh9ZsjfAOyaG7za1MNmBVZ4VVAi/CiJA==
|
||||
"@docusaurus/utils@3.9.2":
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.9.2.tgz#ffab7922631c7e0febcb54e6d499f648bf8a89eb"
|
||||
integrity sha512-lBSBiRruFurFKXr5Hbsl2thmGweAPmddhF3jb99U4EMDA5L+e5Y1rAkOS07Nvrup7HUMBDrCV45meaxZnt28nQ==
|
||||
dependencies:
|
||||
"@docusaurus/logger" "3.9.1"
|
||||
"@docusaurus/types" "3.9.1"
|
||||
"@docusaurus/utils-common" "3.9.1"
|
||||
"@docusaurus/logger" "3.9.2"
|
||||
"@docusaurus/types" "3.9.2"
|
||||
"@docusaurus/utils-common" "3.9.2"
|
||||
escape-string-regexp "^4.0.0"
|
||||
execa "5.1.1"
|
||||
file-loader "^6.2.0"
|
||||
@@ -2428,19 +2428,19 @@
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
|
||||
integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
|
||||
|
||||
"@eslint/config-array@^0.21.0":
|
||||
version "0.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.0.tgz#abdbcbd16b124c638081766392a4d6b509f72636"
|
||||
integrity sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==
|
||||
"@eslint/config-array@^0.21.1":
|
||||
version "0.21.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.1.tgz#7d1b0060fea407f8301e932492ba8c18aff29713"
|
||||
integrity sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==
|
||||
dependencies:
|
||||
"@eslint/object-schema" "^2.1.6"
|
||||
"@eslint/object-schema" "^2.1.7"
|
||||
debug "^4.3.1"
|
||||
minimatch "^3.1.2"
|
||||
|
||||
"@eslint/config-helpers@^0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.0.tgz#e9f94ba3b5b875e32205cb83fece18e64486e9e6"
|
||||
integrity sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==
|
||||
"@eslint/config-helpers@^0.4.1":
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.1.tgz#7d173a1a35fe256f0989a0fdd8d911ebbbf50037"
|
||||
integrity sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==
|
||||
dependencies:
|
||||
"@eslint/core" "^0.16.0"
|
||||
|
||||
@@ -2466,15 +2466,15 @@
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/js@9.37.0", "@eslint/js@^9.37.0":
|
||||
version "9.37.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.37.0.tgz#0cfd5aa763fe5d1ee60bedf84cd14f54bcf9e21b"
|
||||
integrity sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==
|
||||
"@eslint/js@9.38.0", "@eslint/js@^9.38.0":
|
||||
version "9.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.38.0.tgz#f7aa9c7577577f53302c1d795643589d7709ebd1"
|
||||
integrity sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==
|
||||
|
||||
"@eslint/object-schema@^2.1.6":
|
||||
version "2.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f"
|
||||
integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==
|
||||
"@eslint/object-schema@^2.1.7":
|
||||
version "2.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad"
|
||||
integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==
|
||||
|
||||
"@eslint/plugin-kit@^0.4.0":
|
||||
version "0.4.0"
|
||||
@@ -2796,14 +2796,13 @@
|
||||
classnames "^2.3.2"
|
||||
rc-util "^5.24.4"
|
||||
|
||||
"@rc-component/qrcode@~1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/qrcode/-/qrcode-1.0.0.tgz#48a8de5eb11d0e65926f1377c4b1ef4c888997f5"
|
||||
integrity sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==
|
||||
"@rc-component/qrcode@~1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/qrcode/-/qrcode-1.0.1.tgz#98e0a79dc95f26fe211b59d04ef3312bc70dedbe"
|
||||
integrity sha512-g8eeeaMyFXVlq8cZUeaxCDhfIYjpao0l9cvm5gFwKXy/Vm1yDWV7h2sjH5jHYzdFedlVKBpATFB1VKMrHzwaWQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.24.7"
|
||||
classnames "^2.3.2"
|
||||
rc-util "^5.38.0"
|
||||
|
||||
"@rc-component/tour@~1.15.1":
|
||||
version "1.15.1"
|
||||
@@ -4336,79 +4335,79 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@8.46.1", "@typescript-eslint/eslint-plugin@^8.37.0":
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz#20876354024140aabc8b400bc95735fdcade17d5"
|
||||
integrity sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==
|
||||
"@typescript-eslint/eslint-plugin@8.46.2", "@typescript-eslint/eslint-plugin@^8.37.0":
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz#dc4ab93ee3d7e6c8e38820a0d6c7c93c7183e2dc"
|
||||
integrity sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.10.0"
|
||||
"@typescript-eslint/scope-manager" "8.46.1"
|
||||
"@typescript-eslint/type-utils" "8.46.1"
|
||||
"@typescript-eslint/utils" "8.46.1"
|
||||
"@typescript-eslint/visitor-keys" "8.46.1"
|
||||
"@typescript-eslint/scope-manager" "8.46.2"
|
||||
"@typescript-eslint/type-utils" "8.46.2"
|
||||
"@typescript-eslint/utils" "8.46.2"
|
||||
"@typescript-eslint/visitor-keys" "8.46.2"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^7.0.0"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/parser@8.46.1", "@typescript-eslint/parser@^8.46.0":
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.46.1.tgz#81751f46800fc6b01ce1a72760cd17f06e7f395b"
|
||||
integrity sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==
|
||||
"@typescript-eslint/parser@8.46.2", "@typescript-eslint/parser@^8.46.0":
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.46.2.tgz#dd938d45d581ac8ffa9d8a418a50282b306f7ebf"
|
||||
integrity sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.46.1"
|
||||
"@typescript-eslint/types" "8.46.1"
|
||||
"@typescript-eslint/typescript-estree" "8.46.1"
|
||||
"@typescript-eslint/visitor-keys" "8.46.1"
|
||||
"@typescript-eslint/scope-manager" "8.46.2"
|
||||
"@typescript-eslint/types" "8.46.2"
|
||||
"@typescript-eslint/typescript-estree" "8.46.2"
|
||||
"@typescript-eslint/visitor-keys" "8.46.2"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/project-service@8.46.1":
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.46.1.tgz#07be0e6f27fa90a17d8e5f6996ee02329c9a8c2e"
|
||||
integrity sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==
|
||||
"@typescript-eslint/project-service@8.46.2":
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.46.2.tgz#ab2f02a0de4da6a7eeb885af5e059be57819d608"
|
||||
integrity sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==
|
||||
dependencies:
|
||||
"@typescript-eslint/tsconfig-utils" "^8.46.1"
|
||||
"@typescript-eslint/types" "^8.46.1"
|
||||
"@typescript-eslint/tsconfig-utils" "^8.46.2"
|
||||
"@typescript-eslint/types" "^8.46.2"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.46.1":
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz#590dd2e65e95af646bdaf50adeae9af39e25e8c1"
|
||||
integrity sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==
|
||||
"@typescript-eslint/scope-manager@8.46.2":
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz#7d37df2493c404450589acb3b5d0c69cc0670a88"
|
||||
integrity sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.46.1"
|
||||
"@typescript-eslint/visitor-keys" "8.46.1"
|
||||
"@typescript-eslint/types" "8.46.2"
|
||||
"@typescript-eslint/visitor-keys" "8.46.2"
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@8.46.1", "@typescript-eslint/tsconfig-utils@^8.46.1":
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.1.tgz#24405888560175c6c209c39df11ac06a2efef9d7"
|
||||
integrity sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==
|
||||
"@typescript-eslint/tsconfig-utils@8.46.2", "@typescript-eslint/tsconfig-utils@^8.46.2":
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz#d110451cb93bbd189865206ea37ef677c196828c"
|
||||
integrity sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==
|
||||
|
||||
"@typescript-eslint/type-utils@8.46.1":
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.46.1.tgz#14d4307dd6045f6b48a888cde1513d6ec305537f"
|
||||
integrity sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==
|
||||
"@typescript-eslint/type-utils@8.46.2":
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz#802d027864e6fb752e65425ed09f3e089fb4d384"
|
||||
integrity sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.46.1"
|
||||
"@typescript-eslint/typescript-estree" "8.46.1"
|
||||
"@typescript-eslint/utils" "8.46.1"
|
||||
"@typescript-eslint/types" "8.46.2"
|
||||
"@typescript-eslint/typescript-estree" "8.46.2"
|
||||
"@typescript-eslint/utils" "8.46.2"
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/types@8.46.1", "@typescript-eslint/types@^8.46.1":
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.46.1.tgz#4c5479538ec10b5508b8e982e172911c987446d8"
|
||||
integrity sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==
|
||||
"@typescript-eslint/types@8.46.2", "@typescript-eslint/types@^8.46.2":
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.46.2.tgz#2bad7348511b31e6e42579820e62b73145635763"
|
||||
integrity sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.46.1":
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz#1c146573b942ebe609c156c217ceafdc7a88e6ed"
|
||||
integrity sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==
|
||||
"@typescript-eslint/typescript-estree@8.46.2":
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz#ab547a27e4222bb6a3281cb7e98705272e2c7d08"
|
||||
integrity sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/project-service" "8.46.1"
|
||||
"@typescript-eslint/tsconfig-utils" "8.46.1"
|
||||
"@typescript-eslint/types" "8.46.1"
|
||||
"@typescript-eslint/visitor-keys" "8.46.1"
|
||||
"@typescript-eslint/project-service" "8.46.2"
|
||||
"@typescript-eslint/tsconfig-utils" "8.46.2"
|
||||
"@typescript-eslint/types" "8.46.2"
|
||||
"@typescript-eslint/visitor-keys" "8.46.2"
|
||||
debug "^4.3.4"
|
||||
fast-glob "^3.3.2"
|
||||
is-glob "^4.0.3"
|
||||
@@ -4416,22 +4415,22 @@
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/utils@8.46.1":
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.46.1.tgz#c572184d9227d66b10a954b90249a20c48b22452"
|
||||
integrity sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==
|
||||
"@typescript-eslint/utils@8.46.2":
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.46.2.tgz#b313d33d67f9918583af205bd7bcebf20f231732"
|
||||
integrity sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.7.0"
|
||||
"@typescript-eslint/scope-manager" "8.46.1"
|
||||
"@typescript-eslint/types" "8.46.1"
|
||||
"@typescript-eslint/typescript-estree" "8.46.1"
|
||||
"@typescript-eslint/scope-manager" "8.46.2"
|
||||
"@typescript-eslint/types" "8.46.2"
|
||||
"@typescript-eslint/typescript-estree" "8.46.2"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.46.1":
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz#da35f1d58ec407419d68847cfd358b32746ac315"
|
||||
integrity sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==
|
||||
"@typescript-eslint/visitor-keys@8.46.2":
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz#803fa298948c39acf810af21bdce6f8babfa9738"
|
||||
integrity sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.46.1"
|
||||
"@typescript-eslint/types" "8.46.2"
|
||||
eslint-visitor-keys "^4.2.1"
|
||||
|
||||
"@ungap/structured-clone@^1.0.0":
|
||||
@@ -4746,10 +4745,10 @@ 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.27.4:
|
||||
version "5.27.4"
|
||||
resolved "https://registry.yarnpkg.com/antd/-/antd-5.27.4.tgz#13c97deb12e6aeb43adecd23f3dbe3139a62e579"
|
||||
integrity sha512-rhArohoAUCxhkPjGI/BXthOrrjaElL4Fb7d4vEHnIR3DpxFXfegd4rN21IgGdiF+Iz4EFuUZu8MdS8NuJHLSVQ==
|
||||
antd@^5.27.6:
|
||||
version "5.27.6"
|
||||
resolved "https://registry.yarnpkg.com/antd/-/antd-5.27.6.tgz#6b7c7a87b5c696395d2aab2fdbd8409a342813e1"
|
||||
integrity sha512-70HrjVbzDXvtiUQ5MP1XdNudr/wGAk9Ivaemk6f36yrAeJurJSmZ8KngOIilolLRHdGuNc6/Vk+4T1OZpSjpag==
|
||||
dependencies:
|
||||
"@ant-design/colors" "^7.2.1"
|
||||
"@ant-design/cssinjs" "^1.23.0"
|
||||
@@ -4760,7 +4759,7 @@ antd@^5.27.4:
|
||||
"@babel/runtime" "^7.26.0"
|
||||
"@rc-component/color-picker" "~2.0.1"
|
||||
"@rc-component/mutate-observer" "^1.1.0"
|
||||
"@rc-component/qrcode" "~1.0.0"
|
||||
"@rc-component/qrcode" "~1.0.1"
|
||||
"@rc-component/tour" "~1.15.1"
|
||||
"@rc-component/trigger" "^2.3.0"
|
||||
classnames "^2.5.1"
|
||||
@@ -4790,7 +4789,7 @@ antd@^5.27.4:
|
||||
rc-slider "~11.1.9"
|
||||
rc-steps "~6.0.1"
|
||||
rc-switch "~4.1.0"
|
||||
rc-table "~7.53.0"
|
||||
rc-table "~7.54.0"
|
||||
rc-tabs "~15.7.0"
|
||||
rc-textarea "~1.10.2"
|
||||
rc-tooltip "~6.4.0"
|
||||
@@ -5305,10 +5304,10 @@ caniuse-api@^3.0.0:
|
||||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001746, caniuse-lite@^1.0.30001750:
|
||||
version "1.0.30001750"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001750.tgz#c229f82930033abd1502c6f73035356cf528bfbc"
|
||||
integrity sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ==
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001746, caniuse-lite@^1.0.30001751:
|
||||
version "1.0.30001751"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz#dacd5d9f4baeea841641640139d2b2a4df4226ad"
|
||||
integrity sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==
|
||||
|
||||
ccount@^2.0.0:
|
||||
version "2.0.1"
|
||||
@@ -6997,24 +6996,23 @@ eslint-visitor-keys@^4.2.1:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1"
|
||||
integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==
|
||||
|
||||
eslint@^9.37.0:
|
||||
version "9.37.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.37.0.tgz#ac0222127f76b09c0db63036f4fe289562072d74"
|
||||
integrity sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==
|
||||
eslint@^9.38.0:
|
||||
version "9.38.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.38.0.tgz#3957d2af804e5cf6cc503c618f60acc71acb2e7e"
|
||||
integrity sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.8.0"
|
||||
"@eslint-community/regexpp" "^4.12.1"
|
||||
"@eslint/config-array" "^0.21.0"
|
||||
"@eslint/config-helpers" "^0.4.0"
|
||||
"@eslint/config-array" "^0.21.1"
|
||||
"@eslint/config-helpers" "^0.4.1"
|
||||
"@eslint/core" "^0.16.0"
|
||||
"@eslint/eslintrc" "^3.3.1"
|
||||
"@eslint/js" "9.37.0"
|
||||
"@eslint/js" "9.38.0"
|
||||
"@eslint/plugin-kit" "^0.4.0"
|
||||
"@humanfs/node" "^0.16.6"
|
||||
"@humanwhocodes/module-importer" "^1.0.1"
|
||||
"@humanwhocodes/retry" "^0.4.2"
|
||||
"@types/estree" "^1.0.6"
|
||||
"@types/json-schema" "^7.0.15"
|
||||
ajv "^6.12.4"
|
||||
chalk "^4.0.0"
|
||||
cross-spawn "^7.0.6"
|
||||
@@ -11729,10 +11727,10 @@ rc-switch@~4.1.0:
|
||||
classnames "^2.2.1"
|
||||
rc-util "^5.30.0"
|
||||
|
||||
rc-table@~7.53.0:
|
||||
version "7.53.1"
|
||||
resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.53.1.tgz#b891aa39e9d1d944711f018692d2c52013afc90f"
|
||||
integrity sha512-firAd7Z+liqIDS5TubJ1qqcoBd6YcANLKWQDZhFf3rfoOTt/UNPj4n3O+2vhl+z4QMqwPEUVAil661WHA8H8Aw==
|
||||
rc-table@~7.54.0:
|
||||
version "7.54.0"
|
||||
resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.54.0.tgz#dedd4ea18d1189f2acdf90a80f04d8ca0111e16a"
|
||||
integrity sha512-/wDTkki6wBTjwylwAGjpLKYklKo9YgjZwAU77+7ME5mBoS32Q4nAwoqhA2lSge6fobLW3Tap6uc5xfwaL2p0Sw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.10.1"
|
||||
"@rc-component/context" "^1.4.0"
|
||||
@@ -13259,10 +13257,10 @@ swagger-client@^3.35.7:
|
||||
ramda "^0.30.1"
|
||||
ramda-adjunct "^5.1.0"
|
||||
|
||||
swagger-ui-react@^5.29.4:
|
||||
version "5.29.4"
|
||||
resolved "https://registry.yarnpkg.com/swagger-ui-react/-/swagger-ui-react-5.29.4.tgz#ff061f301b46849a93c53b2490f7cebbea401832"
|
||||
integrity sha512-lBBRq75dHWnuN1uuxGOvJkoYr8F+AuZpOSUdHez9st7GlHKTPiBz5bOFONXPzbLKDWrwsPTQ/zArBSDjfqtVow==
|
||||
swagger-ui-react@^5.29.5:
|
||||
version "5.29.5"
|
||||
resolved "https://registry.yarnpkg.com/swagger-ui-react/-/swagger-ui-react-5.29.5.tgz#8c6eafebb75972c15a9f3e24627caec10cc32cbe"
|
||||
integrity sha512-D0YbsDhi4F38HsY5p1DjzuNduU/fVQxtqm3v0o2dRTF5BbLJYRSgjMZ79jejG4q3nNw4kuouCKKiq5xqCLjWrQ==
|
||||
dependencies:
|
||||
"@babel/runtime-corejs3" "^7.27.1"
|
||||
"@scarf/scarf" "=1.4.0"
|
||||
@@ -13590,15 +13588,15 @@ types-ramda@^0.30.1:
|
||||
dependencies:
|
||||
ts-toolbelt "^9.6.0"
|
||||
|
||||
typescript-eslint@^8.46.1:
|
||||
version "8.46.1"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.46.1.tgz#baeb322ee83ca566a8cf1f6403847694a3acd44a"
|
||||
integrity sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==
|
||||
typescript-eslint@^8.46.2:
|
||||
version "8.46.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.46.2.tgz#da1adec683ba93a1b6c3850a4efb0922ffbc627d"
|
||||
integrity sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "8.46.1"
|
||||
"@typescript-eslint/parser" "8.46.1"
|
||||
"@typescript-eslint/typescript-estree" "8.46.1"
|
||||
"@typescript-eslint/utils" "8.46.1"
|
||||
"@typescript-eslint/eslint-plugin" "8.46.2"
|
||||
"@typescript-eslint/parser" "8.46.2"
|
||||
"@typescript-eslint/typescript-estree" "8.46.2"
|
||||
"@typescript-eslint/utils" "8.46.2"
|
||||
|
||||
typescript@~5.9.3:
|
||||
version "5.9.3"
|
||||
|
||||
Generated
+177
-264
@@ -62,14 +62,14 @@
|
||||
"content-disposition": "^0.5.4",
|
||||
"d3-color": "^3.1.0",
|
||||
"d3-scale": "^2.1.2",
|
||||
"dayjs": "^1.11.13",
|
||||
"dayjs": "^1.11.18",
|
||||
"dom-to-image-more": "^3.6.0",
|
||||
"dom-to-pdf": "^0.3.2",
|
||||
"echarts": "^5.6.0",
|
||||
"eslint-plugin-i18n-strings": "file:eslint-rules/eslint-plugin-i18n-strings",
|
||||
"fast-glob": "^3.3.2",
|
||||
"fs-extra": "^11.2.0",
|
||||
"fuse.js": "^7.0.0",
|
||||
"fuse.js": "^7.1.0",
|
||||
"geolib": "^2.0.24",
|
||||
"geostyler": "^14.1.3",
|
||||
"geostyler-data": "^1.1.0",
|
||||
@@ -112,7 +112,7 @@
|
||||
"react-loadable": "^5.5.0",
|
||||
"react-redux": "^7.2.9",
|
||||
"react-resize-detector": "^7.1.2",
|
||||
"react-reverse-portal": "^2.1.2",
|
||||
"react-reverse-portal": "^2.3.0",
|
||||
"react-router-dom": "^5.3.4",
|
||||
"react-search-input": "^0.11.3",
|
||||
"react-sortable-hoc": "^2.0.0",
|
||||
@@ -139,10 +139,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@applitools/eyes-storybook": "^3.60.0",
|
||||
"@babel/cli": "^7.27.2",
|
||||
"@babel/compat-data": "^7.28.0",
|
||||
"@babel/cli": "^7.28.3",
|
||||
"@babel/compat-data": "^7.28.4",
|
||||
"@babel/core": "^7.28.3",
|
||||
"@babel/eslint-parser": "^7.25.9",
|
||||
"@babel/eslint-parser": "^7.28.4",
|
||||
"@babel/node": "^7.22.6",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
|
||||
@@ -161,7 +161,7 @@
|
||||
"@hot-loader/react-dom": "^17.0.2",
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
||||
"@playwright/test": "^1.49.1",
|
||||
"@playwright/test": "^1.56.0",
|
||||
"@storybook/addon-actions": "8.1.11",
|
||||
"@storybook/addon-controls": "8.1.11",
|
||||
"@storybook/addon-essentials": "8.1.11",
|
||||
@@ -184,7 +184,7 @@
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"@types/math-expression-evaluator": "^1.3.3",
|
||||
"@types/mousetrap": "^1.6.15",
|
||||
"@types/node": "^24.6.2",
|
||||
"@types/node": "^24.8.1",
|
||||
"@types/react": "^17.0.83",
|
||||
"@types/react-dom": "^17.0.26",
|
||||
"@types/react-json-tree": "^0.13.0",
|
||||
@@ -210,7 +210,7 @@
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
"babel-plugin-typescript-to-proptypes": "^2.0.0",
|
||||
"cheerio": "1.1.0",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
"copy-webpack-plugin": "^13.0.1",
|
||||
"cross-env": "^10.0.0",
|
||||
"css-loader": "^7.1.2",
|
||||
"css-minimizer-webpack-plugin": "^7.0.2",
|
||||
@@ -228,7 +228,7 @@
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-lodash": "^7.4.0",
|
||||
"eslint-plugin-no-only-tests": "^3.3.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-prefer-function-component": "^3.3.0",
|
||||
@@ -239,7 +239,7 @@
|
||||
"fetch-mock": "^11.1.5",
|
||||
"fork-ts-checker-webpack-plugin": "^9.1.0",
|
||||
"history": "^5.3.0",
|
||||
"html-webpack-plugin": "^5.6.3",
|
||||
"html-webpack-plugin": "^5.6.4",
|
||||
"imports-loader": "^5.0.0",
|
||||
"jest": "^30.0.2",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
@@ -251,7 +251,7 @@
|
||||
"open-cli": "^8.0.0",
|
||||
"po2json": "^0.4.5",
|
||||
"prettier": "3.6.2",
|
||||
"prettier-plugin-packagejson": "^2.5.3",
|
||||
"prettier-plugin-packagejson": "^2.5.19",
|
||||
"process": "^0.11.10",
|
||||
"react-resizable": "^3.0.5",
|
||||
"redux-mock-store": "^1.5.4",
|
||||
@@ -262,13 +262,13 @@
|
||||
"storybook": "8.1.11",
|
||||
"style-loader": "^4.0.0",
|
||||
"thread-loader": "^4.0.4",
|
||||
"ts-jest": "^29.4.0",
|
||||
"ts-jest": "^29.4.5",
|
||||
"ts-loader": "^9.5.1",
|
||||
"tscw-config": "^1.1.2",
|
||||
"tsx": "^4.20.3",
|
||||
"typescript": "5.4.5",
|
||||
"vm-browserify": "^1.1.2",
|
||||
"webpack": "^5.102.0",
|
||||
"webpack": "^5.102.1",
|
||||
"webpack-bundle-analyzer": "^4.10.1",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"webpack-dev-server": "^5.2.2",
|
||||
@@ -1106,13 +1106,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/cli": {
|
||||
"version": "7.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.27.2.tgz",
|
||||
"integrity": "sha512-cfd7DnGlhH6OIyuPSSj3vcfIdnbXukhAyKY8NaZrFadC7pXyL9mOL5WgjcptiEJLi5k3j8aYvLIVCzezrWTaiA==",
|
||||
"version": "7.28.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.28.3.tgz",
|
||||
"integrity": "sha512-n1RU5vuCX0CsaqaXm9I0KUCNKNQMy5epmzl/xdSSm70bSqhg9GWhgeosypyQLc0bK24+Xpk1WGzZlI9pJtkZdg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.25",
|
||||
"@jridgewell/trace-mapping": "^0.3.28",
|
||||
"commander": "^6.2.0",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"fs-readdir-recursive": "^1.1.0",
|
||||
@@ -1150,9 +1150,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/compat-data": {
|
||||
"version": "7.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
|
||||
"integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==",
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz",
|
||||
"integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -1201,9 +1201,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/eslint-parser": {
|
||||
"version": "7.26.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.26.5.tgz",
|
||||
"integrity": "sha512-Kkm8C8uxI842AwQADxl0GbcG1rupELYLShazYEZO/2DYjhyWXJIOUVOE3tBYm6JXzUCNJOZEzqc4rCW/jsEQYQ==",
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.4.tgz",
|
||||
"integrity": "sha512-Aa+yDiH87980jR6zvRfFuCR1+dLb00vBydhTL+zI992Rz/wQhSvuxjmOOuJOgO3XmakO6RykRGD2S1mq1AtgHA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -4125,6 +4125,12 @@
|
||||
"mjolnir.js": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@deck.gl/core/node_modules/@luma.gl/constants": {
|
||||
"version": "9.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-9.1.10.tgz",
|
||||
"integrity": "sha512-O4Nx8UbWmrHHZ7ihKB8WiscX1cz05l1KvKorYTgq+xeXwz2Beh3MkXBMnA46uuyEtimN945OEdYshZnbh80jyw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@deck.gl/extensions": {
|
||||
"version": "9.1.13",
|
||||
"resolved": "https://registry.npmjs.org/@deck.gl/extensions/-/extensions-9.1.13.tgz",
|
||||
@@ -9000,9 +9006,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@luma.gl/constants": {
|
||||
"version": "9.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-9.1.9.tgz",
|
||||
"integrity": "sha512-yc9fml04OeTTcwK+7gmDMxoLQ67j4ZiAFXjmYvPomYyBVzS0NZxTDuwcCBmnxjLOiroOZW8FRRrVc/yOiFug2w==",
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-9.2.2.tgz",
|
||||
"integrity": "sha512-XURMF0gSh0ImZltYa/PCe9KgmopQJiOA6y1m1PxDxJY8OCLma7ZJyvomLn7TQBvPtWTYZsibTW7blu7RwThsaQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@luma.gl/core": {
|
||||
@@ -9078,6 +9084,12 @@
|
||||
"@luma.gl/core": "^9.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@luma.gl/webgl/node_modules/@luma.gl/constants": {
|
||||
"version": "9.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-9.1.9.tgz",
|
||||
"integrity": "sha512-yc9fml04OeTTcwK+7gmDMxoLQ67j4ZiAFXjmYvPomYyBVzS0NZxTDuwcCBmnxjLOiroOZW8FRRrVc/yOiFug2w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@mapbox/extent": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@mapbox/extent/-/extent-0.4.0.tgz",
|
||||
@@ -10577,26 +10589,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgr/core": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
|
||||
"integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
|
||||
"integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/unts"
|
||||
"url": "https://opencollective.com/pkgr"
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.55.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.0.tgz",
|
||||
"integrity": "sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==",
|
||||
"version": "1.56.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.0.tgz",
|
||||
"integrity": "sha512-Tzh95Twig7hUwwNe381/K3PggZBZblKUe2wv25oIpzWLr6Z0m4KgV1ZVIjnR6GM9ANEqjZD7XsZEa6JL/7YEgg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright": "1.55.0"
|
||||
"playwright": "1.56.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@@ -16371,12 +16383,12 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.6.2.tgz",
|
||||
"integrity": "sha512-d2L25Y4j+W3ZlNAeMKcy7yDsK425ibcAOO2t7aPTz6gNMH0z2GThtwENCDc0d/Pw9wgyRqE5Px1wkV7naz8ang==",
|
||||
"version": "24.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.8.1.tgz",
|
||||
"integrity": "sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.13.0"
|
||||
"undici-types": "~7.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node-forge": {
|
||||
@@ -19140,9 +19152,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ace-builds": {
|
||||
"version": "1.43.1",
|
||||
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.43.1.tgz",
|
||||
"integrity": "sha512-n9/n+zBhbbkEJjU0FJ4wWAZBDl5G8WYzg4+uIjSER/U3wSSSSVo52W4sco4Jryg11JAJvorExxMr3GDINqtjdA==",
|
||||
"version": "1.43.4",
|
||||
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.43.4.tgz",
|
||||
"integrity": "sha512-8hAxVfo2ImICd69BWlZwZlxe9rxDGDjuUhh+WeWgGDvfBCE+r3lkynkQvIovDz4jcMi8O7bsEaFygaDT+h9sBA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"peer": true
|
||||
},
|
||||
@@ -20893,9 +20905,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.26.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz",
|
||||
"integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==",
|
||||
"version": "4.26.3",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz",
|
||||
"integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -20913,9 +20925,9 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.8.3",
|
||||
"caniuse-lite": "^1.0.30001741",
|
||||
"electron-to-chromium": "^1.5.218",
|
||||
"baseline-browser-mapping": "^2.8.9",
|
||||
"caniuse-lite": "^1.0.30001746",
|
||||
"electron-to-chromium": "^1.5.227",
|
||||
"node-releases": "^2.0.21",
|
||||
"update-browserslist-db": "^1.1.3"
|
||||
},
|
||||
@@ -22723,9 +22735,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/copy-webpack-plugin": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-13.0.0.tgz",
|
||||
"integrity": "sha512-FgR/h5a6hzJqATDGd9YG41SeDViH+0bkHn6WNXCi5zKAZkeESeSxLySSsFLHqLEVCh0E+rITmCf0dusXWYukeQ==",
|
||||
"version": "13.0.1",
|
||||
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-13.0.1.tgz",
|
||||
"integrity": "sha512-J+YV3WfhY6W/Xf9h+J1znYuqTye2xkBUIGyTPWuBAT27qajBa5mR4f8WBmfDY3YjRftT2kqZZiLi1qf0H+UOFw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -23925,9 +23937,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.13",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
|
||||
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
|
||||
"version": "1.11.18",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
|
||||
"integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debounce": {
|
||||
@@ -24352,13 +24364,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/detect-indent": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz",
|
||||
"integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==",
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.2.tgz",
|
||||
"integrity": "sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-newline": {
|
||||
@@ -26343,14 +26358,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz",
|
||||
"integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==",
|
||||
"version": "5.5.4",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz",
|
||||
"integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prettier-linter-helpers": "^1.0.0",
|
||||
"synckit": "^0.9.1"
|
||||
"synckit": "^0.11.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
@@ -26361,7 +26376,7 @@
|
||||
"peerDependencies": {
|
||||
"@types/eslint": ">=8.0.0",
|
||||
"eslint": ">=8.0.0",
|
||||
"eslint-config-prettier": "*",
|
||||
"eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0",
|
||||
"prettier": ">=3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
@@ -28414,9 +28429,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/fuse.js": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz",
|
||||
"integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz",
|
||||
"integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
@@ -29526,9 +29541,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/git-hooks-list": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.1.0.tgz",
|
||||
"integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-4.1.1.tgz",
|
||||
"integrity": "sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -30871,9 +30886,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/html-webpack-plugin": {
|
||||
"version": "5.6.3",
|
||||
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz",
|
||||
"integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==",
|
||||
"version": "5.6.4",
|
||||
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.4.tgz",
|
||||
"integrity": "sha512-V/PZeWsqhfpE27nKeX9EO2sbR+D17A+tLf6qU+ht66jdUsN0QLKJN27Z+1+gHrVMKgndBahes0PU6rRihDgHTw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -35729,19 +35744,6 @@
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-snapshot/node_modules/@pkgr/core": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz",
|
||||
"integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/pkgr"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-snapshot/node_modules/@sinclair/typebox": {
|
||||
"version": "0.34.37",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.37.tgz",
|
||||
@@ -35934,22 +35936,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-snapshot/node_modules/synckit": {
|
||||
"version": "0.11.8",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz",
|
||||
"integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/synckit"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-util": {
|
||||
"version": "29.7.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
|
||||
@@ -46079,13 +46065,13 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.55.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.0.tgz",
|
||||
"integrity": "sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==",
|
||||
"version": "1.56.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.0.tgz",
|
||||
"integrity": "sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.55.0"
|
||||
"playwright-core": "1.56.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@@ -46098,9 +46084,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.55.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.0.tgz",
|
||||
"integrity": "sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==",
|
||||
"version": "1.56.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.0.tgz",
|
||||
"integrity": "sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -46863,14 +46849,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-packagejson": {
|
||||
"version": "2.5.8",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.8.tgz",
|
||||
"integrity": "sha512-BaGOF63I0IJZoudxpuQe17naV93BRtK8b3byWktkJReKEMX9CC4qdGUzThPDVO/AUhPzlqDiAXbp18U6X8wLKA==",
|
||||
"version": "2.5.19",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.19.tgz",
|
||||
"integrity": "sha512-Qsqp4+jsZbKMpEGZB1UP1pxeAT8sCzne2IwnKkr+QhUe665EXUo3BAvTf1kAPCqyMv9kg3ZmO0+7eOni/C6Uag==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sort-package-json": "2.14.0",
|
||||
"synckit": "0.9.2"
|
||||
"sort-package-json": "3.4.0",
|
||||
"synckit": "0.11.11"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prettier": ">= 1.16.0"
|
||||
@@ -48969,13 +48955,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-reverse-portal": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-reverse-portal/-/react-reverse-portal-2.1.2.tgz",
|
||||
"integrity": "sha512-li4puNtBmMMJhtI+IVxeSX0RvK1ft8qjPSbCih4OKQ/YUIcROc31Nmo22gv94hTx8EUfR7fzZY47RuZF2YRMdQ==",
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-reverse-portal/-/react-reverse-portal-2.3.0.tgz",
|
||||
"integrity": "sha512-kvbPfLPKg6Y3S6tVq83us2RghvDpOS4GcJxbI7cZ0V0tuzUaSzblRIhVnKLOucfqF4lN/i9oWvEmpEi6bAOYlQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"react": "^16.0.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
|
||||
"react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
@@ -51689,9 +51675,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/schema-utils": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz",
|
||||
"integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
|
||||
"integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -53001,23 +52987,25 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sort-package-json": {
|
||||
"version": "2.14.0",
|
||||
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.14.0.tgz",
|
||||
"integrity": "sha512-xBRdmMjFB/KW3l51mP31dhlaiFmqkHLfWTfZAno8prb/wbDxwBPWFpxB16GZbiPbYr3wL41H8Kx22QIDWRe8WQ==",
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.4.0.tgz",
|
||||
"integrity": "sha512-97oFRRMM2/Js4oEA9LJhjyMlde+2ewpZQf53pgue27UkbEXfHJnDzHlUxQ/DWUkzqmp7DFwJp8D+wi/TYeQhpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"detect-indent": "^7.0.1",
|
||||
"detect-newline": "^4.0.0",
|
||||
"get-stdin": "^9.0.0",
|
||||
"git-hooks-list": "^3.0.0",
|
||||
"detect-newline": "^4.0.1",
|
||||
"git-hooks-list": "^4.0.0",
|
||||
"is-plain-obj": "^4.1.0",
|
||||
"semver": "^7.6.0",
|
||||
"semver": "^7.7.1",
|
||||
"sort-object-keys": "^1.1.3",
|
||||
"tinyglobby": "^0.2.9"
|
||||
"tinyglobby": "^0.2.12"
|
||||
},
|
||||
"bin": {
|
||||
"sort-package-json": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/sort-package-json/node_modules/detect-newline": {
|
||||
@@ -53046,6 +53034,19 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/sort-package-json/node_modules/semver": {
|
||||
"version": "7.7.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/source-list-map": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
|
||||
@@ -54355,26 +54356,25 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/synckit": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
|
||||
"integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
|
||||
"version": "0.11.11",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz",
|
||||
"integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.1.0",
|
||||
"tslib": "^2.6.2"
|
||||
"@pkgr/core": "^0.2.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/unts"
|
||||
"url": "https://opencollective.com/synckit"
|
||||
}
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz",
|
||||
"integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==",
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
|
||||
"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -55359,19 +55359,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ts-jest": {
|
||||
"version": "29.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.0.tgz",
|
||||
"integrity": "sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==",
|
||||
"version": "29.4.5",
|
||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.5.tgz",
|
||||
"integrity": "sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bs-logger": "^0.2.6",
|
||||
"ejs": "^3.1.10",
|
||||
"fast-json-stable-stringify": "^2.1.0",
|
||||
"handlebars": "^4.7.8",
|
||||
"json5": "^2.2.3",
|
||||
"lodash.memoize": "^4.1.2",
|
||||
"make-error": "^1.3.6",
|
||||
"semver": "^7.7.2",
|
||||
"semver": "^7.7.3",
|
||||
"type-fest": "^4.41.0",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
@@ -55412,9 +55412,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ts-jest/node_modules/semver": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"version": "7.7.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
@@ -56413,9 +56413,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.13.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.13.0.tgz",
|
||||
"integrity": "sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==",
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz",
|
||||
"integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unicode-canonical-property-names-ecmascript": {
|
||||
@@ -57554,9 +57554,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.102.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.0.tgz",
|
||||
"integrity": "sha512-hUtqAR3ZLVEYDEABdBioQCIqSoguHbFn1K7WlPPWSuXmx0031BD73PSE35jKyftdSh4YLDoQNgK4pqBt5Q82MA==",
|
||||
"version": "5.102.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.1.tgz",
|
||||
"integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -57568,7 +57568,7 @@
|
||||
"@webassemblyjs/wasm-parser": "^1.14.1",
|
||||
"acorn": "^8.15.0",
|
||||
"acorn-import-phases": "^1.0.3",
|
||||
"browserslist": "^4.24.5",
|
||||
"browserslist": "^4.26.3",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.17.3",
|
||||
"es-module-lexer": "^1.2.1",
|
||||
@@ -57580,8 +57580,8 @@
|
||||
"loader-runner": "^4.2.0",
|
||||
"mime-types": "^2.1.27",
|
||||
"neo-async": "^2.6.2",
|
||||
"schema-utils": "^4.3.2",
|
||||
"tapable": "^2.2.3",
|
||||
"schema-utils": "^4.3.3",
|
||||
"tapable": "^2.3.0",
|
||||
"terser-webpack-plugin": "^5.3.11",
|
||||
"watchpack": "^2.4.4",
|
||||
"webpack-sources": "^3.3.3"
|
||||
@@ -59296,7 +59296,7 @@
|
||||
"version": "0.20.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"chalk": "^5.4.1",
|
||||
"chalk": "^5.6.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"yeoman-generator": "^7.5.1",
|
||||
"yosay": "^3.0.0"
|
||||
@@ -59891,19 +59891,6 @@
|
||||
"@octokit/openapi-types": "^25.1.0"
|
||||
}
|
||||
},
|
||||
"packages/generator-superset/node_modules/@pkgr/core": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
|
||||
"integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/pkgr"
|
||||
}
|
||||
},
|
||||
"packages/generator-superset/node_modules/@sinclair/typebox": {
|
||||
"version": "0.34.38",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz",
|
||||
@@ -59977,9 +59964,9 @@
|
||||
}
|
||||
},
|
||||
"packages/generator-superset/node_modules/chalk": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
|
||||
"integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
|
||||
"integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||
@@ -61279,22 +61266,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"packages/generator-superset/node_modules/synckit": {
|
||||
"version": "0.11.11",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz",
|
||||
"integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.2.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/synckit"
|
||||
}
|
||||
},
|
||||
"packages/generator-superset/node_modules/universal-user-agent": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",
|
||||
@@ -61343,7 +61314,7 @@
|
||||
"version": "0.0.1-rc5",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.26.4",
|
||||
"@babel/cli": "^7.28.3",
|
||||
"@babel/core": "^7.28.3",
|
||||
"@babel/preset-env": "^7.26.9",
|
||||
"@babel/preset-react": "^7.26.3",
|
||||
@@ -64067,11 +64038,11 @@
|
||||
"@ant-design/icons": "^5.2.6",
|
||||
"@apache-superset/core": "*",
|
||||
"@babel/runtime": "^7.28.4",
|
||||
"@fontsource/fira-code": "^5.2.6",
|
||||
"@fontsource/fira-code": "^5.2.7",
|
||||
"@fontsource/inter": "^5.2.6",
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"@visx/responsive": "^3.12.0",
|
||||
"ace-builds": "^1.43.3",
|
||||
"ace-builds": "^1.43.4",
|
||||
"ag-grid-community": "34.2.0",
|
||||
"ag-grid-react": "34.2.0",
|
||||
"brace": "^0.11.1",
|
||||
@@ -64083,7 +64054,7 @@
|
||||
"d3-scale": "^4.0.2",
|
||||
"d3-time": "^3.1.0",
|
||||
"d3-time-format": "^4.1.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dayjs": "^1.11.18",
|
||||
"dompurify": "^3.2.4",
|
||||
"fetch-retry": "^6.0.0",
|
||||
"handlebars": "^4.7.8",
|
||||
@@ -64107,7 +64078,7 @@
|
||||
"reselect": "^5.1.1",
|
||||
"rison": "^0.1.1",
|
||||
"seedrandom": "^3.0.5",
|
||||
"xss": "^1.0.14"
|
||||
"xss": "^1.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@emotion/styled": "^11.14.1",
|
||||
@@ -64119,7 +64090,7 @@
|
||||
"@types/jquery": "^3.5.33",
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/math-expression-evaluator": "^1.3.3",
|
||||
"@types/node": "^24.6.2",
|
||||
"@types/node": "^24.8.1",
|
||||
"@types/prop-types": "^15.7.15",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"@types/react-table": "^7.7.20",
|
||||
@@ -65950,7 +65921,7 @@
|
||||
"@deck.gl/geo-layers": "^9.1.13",
|
||||
"@deck.gl/layers": "^9.1.13",
|
||||
"@deck.gl/react": "^9.1.14",
|
||||
"@luma.gl/constants": "^9.1.9",
|
||||
"@luma.gl/constants": "^9.2.2",
|
||||
"@luma.gl/core": "^9.1.9",
|
||||
"@luma.gl/engine": "^9.1.9",
|
||||
"@luma.gl/shadertools": "^9.1.9",
|
||||
@@ -65964,7 +65935,7 @@
|
||||
"d3-array": "^1.2.4",
|
||||
"d3-color": "^1.4.1",
|
||||
"d3-scale": "^3.0.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dayjs": "^1.11.18",
|
||||
"handlebars": "^4.7.8",
|
||||
"lodash": "^4.17.21",
|
||||
"mousetrap": "^1.6.5",
|
||||
@@ -66008,6 +65979,12 @@
|
||||
"@luma.gl/engine": "~9.1.9"
|
||||
}
|
||||
},
|
||||
"plugins/legacy-preset-chart-deckgl/node_modules/@deck.gl/aggregation-layers/node_modules/@luma.gl/constants": {
|
||||
"version": "9.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-9.1.10.tgz",
|
||||
"integrity": "sha512-O4Nx8UbWmrHHZ7ihKB8WiscX1cz05l1KvKorYTgq+xeXwz2Beh3MkXBMnA46uuyEtimN945OEdYshZnbh80jyw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"plugins/legacy-preset-chart-deckgl/node_modules/@mapbox/tiny-sdf": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.7.tgz",
|
||||
@@ -66098,7 +66075,7 @@
|
||||
"d3": "^3.5.17",
|
||||
"d3-tip": "^0.9.1",
|
||||
"dayjs": "^1.11.18",
|
||||
"dompurify": "^3.2.7",
|
||||
"dompurify": "^3.3.0",
|
||||
"fast-safe-stringify": "^2.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"nvd3-fork": "^2.0.5",
|
||||
@@ -66111,16 +66088,10 @@
|
||||
"react": "^17.0.2"
|
||||
}
|
||||
},
|
||||
"plugins/legacy-preset-chart-nvd3/node_modules/dayjs": {
|
||||
"version": "1.11.18",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
|
||||
"integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"plugins/legacy-preset-chart-nvd3/node_modules/dompurify": {
|
||||
"version": "3.2.7",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz",
|
||||
"integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==",
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.0.tgz",
|
||||
"integrity": "sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
@@ -66192,7 +66163,7 @@
|
||||
"dependencies": {
|
||||
"@types/react-redux": "^7.1.34",
|
||||
"d3-array": "^1.2.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dayjs": "^1.11.18",
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -66538,19 +66509,6 @@
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"plugins/plugin-chart-handlebars/node_modules/@pkgr/core": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
|
||||
"integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/pkgr"
|
||||
}
|
||||
},
|
||||
"plugins/plugin-chart-handlebars/node_modules/@sinclair/typebox": {
|
||||
"version": "0.34.37",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.37.tgz",
|
||||
@@ -67447,22 +67405,6 @@
|
||||
"license": "BSD-3-Clause",
|
||||
"peer": true
|
||||
},
|
||||
"plugins/plugin-chart-handlebars/node_modules/synckit": {
|
||||
"version": "0.11.11",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz",
|
||||
"integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.2.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/synckit"
|
||||
}
|
||||
},
|
||||
"plugins/plugin-chart-pivot-table": {
|
||||
"name": "@superset-ui/plugin-chart-pivot-table",
|
||||
"version": "0.20.3",
|
||||
@@ -67800,19 +67742,6 @@
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"plugins/plugin-chart-pivot-table/node_modules/@pkgr/core": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
|
||||
"integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/pkgr"
|
||||
}
|
||||
},
|
||||
"plugins/plugin-chart-pivot-table/node_modules/@sinclair/typebox": {
|
||||
"version": "0.34.41",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz",
|
||||
@@ -68672,22 +68601,6 @@
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"plugins/plugin-chart-pivot-table/node_modules/synckit": {
|
||||
"version": "0.11.11",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz",
|
||||
"integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.2.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/synckit"
|
||||
}
|
||||
},
|
||||
"plugins/plugin-chart-table": {
|
||||
"name": "@superset-ui/plugin-chart-table",
|
||||
"version": "0.20.3",
|
||||
|
||||
@@ -135,14 +135,14 @@
|
||||
"content-disposition": "^0.5.4",
|
||||
"d3-color": "^3.1.0",
|
||||
"d3-scale": "^2.1.2",
|
||||
"dayjs": "^1.11.13",
|
||||
"dayjs": "^1.11.18",
|
||||
"dom-to-image-more": "^3.6.0",
|
||||
"dom-to-pdf": "^0.3.2",
|
||||
"echarts": "^5.6.0",
|
||||
"eslint-plugin-i18n-strings": "file:eslint-rules/eslint-plugin-i18n-strings",
|
||||
"fast-glob": "^3.3.2",
|
||||
"fs-extra": "^11.2.0",
|
||||
"fuse.js": "^7.0.0",
|
||||
"fuse.js": "^7.1.0",
|
||||
"geolib": "^2.0.24",
|
||||
"geostyler": "^14.1.3",
|
||||
"geostyler-data": "^1.1.0",
|
||||
@@ -185,7 +185,7 @@
|
||||
"react-loadable": "^5.5.0",
|
||||
"react-redux": "^7.2.9",
|
||||
"react-resize-detector": "^7.1.2",
|
||||
"react-reverse-portal": "^2.1.2",
|
||||
"react-reverse-portal": "^2.3.0",
|
||||
"react-router-dom": "^5.3.4",
|
||||
"react-search-input": "^0.11.3",
|
||||
"react-sortable-hoc": "^2.0.0",
|
||||
@@ -212,10 +212,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@applitools/eyes-storybook": "^3.60.0",
|
||||
"@babel/cli": "^7.27.2",
|
||||
"@babel/compat-data": "^7.28.0",
|
||||
"@babel/cli": "^7.28.3",
|
||||
"@babel/compat-data": "^7.28.4",
|
||||
"@babel/core": "^7.28.3",
|
||||
"@babel/eslint-parser": "^7.25.9",
|
||||
"@babel/eslint-parser": "^7.28.4",
|
||||
"@babel/node": "^7.22.6",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
|
||||
@@ -234,7 +234,7 @@
|
||||
"@hot-loader/react-dom": "^17.0.2",
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
||||
"@playwright/test": "^1.49.1",
|
||||
"@playwright/test": "^1.56.0",
|
||||
"@storybook/addon-actions": "8.1.11",
|
||||
"@storybook/addon-controls": "8.1.11",
|
||||
"@storybook/addon-essentials": "8.1.11",
|
||||
@@ -257,7 +257,7 @@
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"@types/math-expression-evaluator": "^1.3.3",
|
||||
"@types/mousetrap": "^1.6.15",
|
||||
"@types/node": "^24.6.2",
|
||||
"@types/node": "^24.8.1",
|
||||
"@types/react": "^17.0.83",
|
||||
"@types/react-dom": "^17.0.26",
|
||||
"@types/react-json-tree": "^0.13.0",
|
||||
@@ -283,7 +283,7 @@
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
"babel-plugin-typescript-to-proptypes": "^2.0.0",
|
||||
"cheerio": "1.1.0",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
"copy-webpack-plugin": "^13.0.1",
|
||||
"cross-env": "^10.0.0",
|
||||
"css-loader": "^7.1.2",
|
||||
"css-minimizer-webpack-plugin": "^7.0.2",
|
||||
@@ -301,7 +301,7 @@
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-lodash": "^7.4.0",
|
||||
"eslint-plugin-no-only-tests": "^3.3.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-prefer-function-component": "^3.3.0",
|
||||
@@ -312,7 +312,7 @@
|
||||
"fetch-mock": "^11.1.5",
|
||||
"fork-ts-checker-webpack-plugin": "^9.1.0",
|
||||
"history": "^5.3.0",
|
||||
"html-webpack-plugin": "^5.6.3",
|
||||
"html-webpack-plugin": "^5.6.4",
|
||||
"imports-loader": "^5.0.0",
|
||||
"jest": "^30.0.2",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
@@ -324,7 +324,7 @@
|
||||
"open-cli": "^8.0.0",
|
||||
"po2json": "^0.4.5",
|
||||
"prettier": "3.6.2",
|
||||
"prettier-plugin-packagejson": "^2.5.3",
|
||||
"prettier-plugin-packagejson": "^2.5.19",
|
||||
"process": "^0.11.10",
|
||||
"react-resizable": "^3.0.5",
|
||||
"redux-mock-store": "^1.5.4",
|
||||
@@ -335,13 +335,13 @@
|
||||
"storybook": "8.1.11",
|
||||
"style-loader": "^4.0.0",
|
||||
"thread-loader": "^4.0.4",
|
||||
"ts-jest": "^29.4.0",
|
||||
"ts-jest": "^29.4.5",
|
||||
"ts-loader": "^9.5.1",
|
||||
"tscw-config": "^1.1.2",
|
||||
"tsx": "^4.20.3",
|
||||
"typescript": "5.4.5",
|
||||
"vm-browserify": "^1.1.2",
|
||||
"webpack": "^5.102.0",
|
||||
"webpack": "^5.102.1",
|
||||
"webpack-bundle-analyzer": "^4.10.1",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"webpack-dev-server": "^5.2.2",
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^5.4.1",
|
||||
"chalk": "^5.6.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"yeoman-generator": "^7.5.1",
|
||||
"yosay": "^3.0.0"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.26.4",
|
||||
"@babel/cli": "^7.28.3",
|
||||
"@babel/core": "^7.28.3",
|
||||
"@babel/preset-env": "^7.26.9",
|
||||
"@babel/preset-react": "^7.26.3",
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
"@apache-superset/core": "*",
|
||||
"@ant-design/icons": "^5.2.6",
|
||||
"@babel/runtime": "^7.28.4",
|
||||
"@fontsource/fira-code": "^5.2.6",
|
||||
"@fontsource/fira-code": "^5.2.7",
|
||||
"@fontsource/inter": "^5.2.6",
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"ace-builds": "^1.43.3",
|
||||
"ace-builds": "^1.43.4",
|
||||
"ag-grid-community": "34.2.0",
|
||||
"ag-grid-react": "34.2.0",
|
||||
"brace": "^0.11.1",
|
||||
@@ -38,7 +38,7 @@
|
||||
"csstype": "^3.1.3",
|
||||
"core-js": "^3.38.1",
|
||||
"d3-format": "^1.3.2",
|
||||
"dayjs": "^1.11.13",
|
||||
"dayjs": "^1.11.18",
|
||||
"d3-interpolate": "^3.0.1",
|
||||
"d3-scale": "^4.0.2",
|
||||
"d3-time": "^3.1.0",
|
||||
@@ -67,7 +67,7 @@
|
||||
"rison": "^0.1.1",
|
||||
"seedrandom": "^3.0.5",
|
||||
"@visx/responsive": "^3.12.0",
|
||||
"xss": "^1.0.14"
|
||||
"xss": "^1.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@emotion/styled": "^11.14.1",
|
||||
@@ -81,7 +81,7 @@
|
||||
"@types/jquery": "^3.5.33",
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/math-expression-evaluator": "^1.3.3",
|
||||
"@types/node": "^24.6.2",
|
||||
"@types/node": "^24.8.1",
|
||||
"@types/prop-types": "^15.7.15",
|
||||
"@types/rison": "0.1.0",
|
||||
"@types/seedrandom": "^3.0.8",
|
||||
|
||||
@@ -28,6 +28,7 @@ export const StyledHeader = styled.span<{ headerPosition: string }>`
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-right: ${headerPosition === 'left' ? theme.sizeUnit * 2 : 0}px;
|
||||
font-size: ${theme.fontSizeSM}px;
|
||||
`}
|
||||
`;
|
||||
|
||||
|
||||
@@ -324,6 +324,7 @@ export type Query = {
|
||||
schema?: string;
|
||||
sql: string;
|
||||
sqlEditorId: string;
|
||||
sqlEditorImmutableId: string;
|
||||
state: QueryState;
|
||||
tab: string | null;
|
||||
tempSchema: string | null;
|
||||
@@ -373,6 +374,7 @@ export const testQuery: Query = {
|
||||
dbId: 1,
|
||||
sql: 'SELECT * FROM something',
|
||||
sqlEditorId: 'dfsadfs',
|
||||
sqlEditorImmutableId: 'immutableId2353',
|
||||
tab: 'unimportant',
|
||||
tempTable: '',
|
||||
ctas: false,
|
||||
|
||||
@@ -402,7 +402,7 @@ export interface ThemeContextType {
|
||||
setTheme: (config: AnyThemeConfig) => void;
|
||||
setThemeMode: (newMode: ThemeMode) => void;
|
||||
resetTheme: () => void;
|
||||
setTemporaryTheme: (config: AnyThemeConfig) => void;
|
||||
setTemporaryTheme: (config: AnyThemeConfig, themeId?: number | null) => void;
|
||||
clearLocalOverrides: () => void;
|
||||
getCurrentCrudThemeId: () => string | null;
|
||||
hasDevOverride: () => boolean;
|
||||
@@ -410,6 +410,7 @@ export interface ThemeContextType {
|
||||
canSetTheme: () => boolean;
|
||||
canDetectOSPreference: () => boolean;
|
||||
createDashboardThemeProvider: (themeId: string) => Promise<Theme | null>;
|
||||
getAppliedThemeId: () => number | null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"@deck.gl/geo-layers": "^9.1.13",
|
||||
"@deck.gl/layers": "^9.1.13",
|
||||
"@deck.gl/react": "^9.1.14",
|
||||
"@luma.gl/constants": "^9.1.9",
|
||||
"@luma.gl/constants": "^9.2.2",
|
||||
"@luma.gl/core": "^9.1.9",
|
||||
"@luma.gl/engine": "^9.1.9",
|
||||
"@luma.gl/shadertools": "^9.1.9",
|
||||
@@ -43,7 +43,7 @@
|
||||
"d3-array": "^1.2.4",
|
||||
"d3-color": "^1.4.1",
|
||||
"d3-scale": "^3.0.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dayjs": "^1.11.18",
|
||||
"handlebars": "^4.7.8",
|
||||
"lodash": "^4.17.21",
|
||||
"mousetrap": "^1.6.5",
|
||||
|
||||
+11
-12
@@ -16,10 +16,9 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { useEffect, useState, memo } from 'react';
|
||||
import { styled, t } from '@superset-ui/core';
|
||||
import { useEffect, useState, memo, useMemo } from 'react';
|
||||
import { styled, t, sanitizeHtml } from '@superset-ui/core';
|
||||
import { extendedDayjs as dayjs } from '@superset-ui/core/utils/dates';
|
||||
import { SafeMarkdown } from '@superset-ui/core/components';
|
||||
import Handlebars from 'handlebars';
|
||||
import { isPlainObject } from 'lodash';
|
||||
|
||||
@@ -45,8 +44,6 @@ export const HandlebarsRenderer: React.FC<HandlebarsRendererProps> = memo(
|
||||
appContainer?.getAttribute('data-bootstrap') || '{}',
|
||||
);
|
||||
const htmlSanitization = common?.conf?.HTML_SANITIZATION ?? true;
|
||||
const htmlSchemaOverrides =
|
||||
common?.conf?.HTML_SANITIZATION_SCHEMA_EXTENSIONS || {};
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
@@ -60,6 +57,12 @@ export const HandlebarsRenderer: React.FC<HandlebarsRendererProps> = memo(
|
||||
}
|
||||
}, [templateSource, data]);
|
||||
|
||||
const htmlContent = useMemo(
|
||||
() =>
|
||||
htmlSanitization ? sanitizeHtml(renderedTemplate) : renderedTemplate,
|
||||
[renderedTemplate, htmlSanitization],
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return <ErrorContainer>{error}</ErrorContainer>;
|
||||
}
|
||||
@@ -73,13 +76,9 @@ export const HandlebarsRenderer: React.FC<HandlebarsRendererProps> = memo(
|
||||
fontSize: '12px',
|
||||
lineHeight: '1.4',
|
||||
}}
|
||||
>
|
||||
<SafeMarkdown
|
||||
source={renderedTemplate || ''}
|
||||
htmlSanitization={htmlSanitization}
|
||||
htmlSchemaOverrides={htmlSchemaOverrides}
|
||||
/>
|
||||
</div>
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{ __html: htmlContent }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"lodash": "^4.17.21",
|
||||
"dayjs": "^1.11.18",
|
||||
"nvd3-fork": "^2.0.5",
|
||||
"dompurify": "^3.2.7",
|
||||
"dompurify": "^3.3.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"urijs": "^1.19.11"
|
||||
},
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"dependencies": {
|
||||
"@types/react-redux": "^7.1.34",
|
||||
"d3-array": "^1.2.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dayjs": "^1.11.18",
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -142,7 +142,7 @@ const config: ControlPanelConfig = {
|
||||
type: 'SelectControl',
|
||||
freeForm: true,
|
||||
clearable: true,
|
||||
label: t('X AXIS TITLE MARGIN'),
|
||||
label: t('X axis title margin'),
|
||||
renderTrigger: true,
|
||||
default: sections.TITLE_MARGIN_OPTIONS[1],
|
||||
choices: formatSelectOptions(sections.TITLE_MARGIN_OPTIONS),
|
||||
@@ -214,7 +214,7 @@ const config: ControlPanelConfig = {
|
||||
type: 'SelectControl',
|
||||
freeForm: true,
|
||||
clearable: true,
|
||||
label: t('Y AXIS TITLE MARGIN'),
|
||||
label: t('Y axis title margin'),
|
||||
renderTrigger: true,
|
||||
default: sections.TITLE_MARGIN_OPTIONS[1],
|
||||
choices: formatSelectOptions(sections.TITLE_MARGIN_OPTIONS),
|
||||
|
||||
+3
-3
@@ -81,7 +81,7 @@ function createAxisTitleControl(axis: 'x' | 'y'): ControlSetRow[] {
|
||||
type: 'SelectControl',
|
||||
freeForm: true,
|
||||
clearable: true,
|
||||
label: t('AXIS TITLE MARGIN'),
|
||||
label: t('Axis title margin'),
|
||||
renderTrigger: true,
|
||||
default: sections.TITLE_MARGIN_OPTIONS[0],
|
||||
choices: formatSelectOptions(sections.TITLE_MARGIN_OPTIONS),
|
||||
@@ -114,7 +114,7 @@ function createAxisTitleControl(axis: 'x' | 'y'): ControlSetRow[] {
|
||||
type: 'SelectControl',
|
||||
freeForm: true,
|
||||
clearable: true,
|
||||
label: t('AXIS TITLE MARGIN'),
|
||||
label: t('Axis title margin'),
|
||||
renderTrigger: true,
|
||||
default: sections.TITLE_MARGIN_OPTIONS[1],
|
||||
choices: formatSelectOptions(sections.TITLE_MARGIN_OPTIONS),
|
||||
@@ -132,7 +132,7 @@ function createAxisTitleControl(axis: 'x' | 'y'): ControlSetRow[] {
|
||||
type: 'SelectControl',
|
||||
freeForm: true,
|
||||
clearable: false,
|
||||
label: t('AXIS TITLE POSITION'),
|
||||
label: t('Axis title position'),
|
||||
renderTrigger: true,
|
||||
default: sections.TITLE_POSITION_OPTIONS[0][0],
|
||||
choices: sections.TITLE_POSITION_OPTIONS,
|
||||
|
||||
@@ -394,7 +394,7 @@ export function runQueryFromSqlEditor(
|
||||
dbId: qe.dbId,
|
||||
sql: qe.selectedText || qe.sql,
|
||||
sqlEditorId: qe.tabViewId ?? qe.id,
|
||||
immutableId: qe.immutableId,
|
||||
sqlEditorImmutableId: qe.immutableId,
|
||||
tab: qe.name,
|
||||
catalog: qe.catalog,
|
||||
schema: qe.schema,
|
||||
|
||||
@@ -602,4 +602,42 @@ describe('ResultSet', () => {
|
||||
);
|
||||
expect(queryByTestId('copy-to-clipboard-button')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should include sqlEditorImmutableId in query object when fetching results', async () => {
|
||||
const queryWithResultsKey = {
|
||||
...queries[0],
|
||||
resultsKey: 'test-results-key',
|
||||
sqlEditorImmutableId: 'test-immutable-id-123',
|
||||
};
|
||||
|
||||
const store = mockStore({
|
||||
...initialState,
|
||||
user,
|
||||
sqlLab: {
|
||||
...initialState.sqlLab,
|
||||
queries: {
|
||||
[queryWithResultsKey.id]: queryWithResultsKey,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
setup({ ...mockedProps, queryId: queryWithResultsKey.id }, store);
|
||||
|
||||
await waitFor(() => {
|
||||
// Check that REQUEST_QUERY_RESULTS action was dispatched
|
||||
const actions = store.getActions();
|
||||
const requestAction = actions.find(
|
||||
action => action.type === 'REQUEST_QUERY_RESULTS',
|
||||
);
|
||||
expect(requestAction).toBeDefined();
|
||||
// Verify sqlEditorImmutableId is present in the query object
|
||||
expect(requestAction?.query?.sqlEditorImmutableId).toBe(
|
||||
'test-immutable-id-123',
|
||||
);
|
||||
});
|
||||
|
||||
// Verify the API was called
|
||||
const resultsCalls = fetchMock.calls('glob:*/api/v1/sqllab/results/*');
|
||||
expect(resultsCalls).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -198,6 +198,7 @@ const ResultSet = ({
|
||||
'sql',
|
||||
'executedSql',
|
||||
'sqlEditorId',
|
||||
'sqlEditorImmutableId',
|
||||
'templateParams',
|
||||
'schema',
|
||||
'rows',
|
||||
|
||||
@@ -238,6 +238,7 @@ export const queries = [
|
||||
ctas: false,
|
||||
cached: false,
|
||||
id: 'BkA1CLrJg',
|
||||
sqlEditorImmutableId: 'BkA1CLrJg_immutable',
|
||||
progress: 100,
|
||||
startDttm: 1476910566092.96,
|
||||
state: QueryState.Success,
|
||||
@@ -297,6 +298,7 @@ export const queries = [
|
||||
ctas: false,
|
||||
cached: false,
|
||||
id: 'S1zeAISkx',
|
||||
sqlEditorImmutableId: 'S1zeAISkx_immutable',
|
||||
progress: 100,
|
||||
startDttm: 1476910570802.2,
|
||||
state: QueryState.Success,
|
||||
@@ -331,6 +333,7 @@ export const queryWithNoQueryLimit = {
|
||||
ctas: false,
|
||||
cached: false,
|
||||
id: 'BkA1CLrJg',
|
||||
sqlEditorImmutableId: 'BkA1CLrJg_immutable',
|
||||
progress: 100,
|
||||
startDttm: 1476910566092.96,
|
||||
state: QueryState.Success,
|
||||
@@ -589,6 +592,7 @@ const baseQuery: QueryResponse = {
|
||||
ctas: false,
|
||||
cached: false,
|
||||
id: 'BkA1CLrJg',
|
||||
sqlEditorImmutableId: 'BkA1CLrJg_immutable',
|
||||
progress: 100,
|
||||
startDttm: 1476910566092.96,
|
||||
state: QueryState.Success,
|
||||
@@ -672,6 +676,7 @@ export const runningQuery: QueryResponse = {
|
||||
cached: false,
|
||||
ctas: false,
|
||||
id: 'ryhMUZCGb',
|
||||
sqlEditorImmutableId: 'ryhMUZCGb_immutable',
|
||||
progress: 90,
|
||||
state: QueryState.Running,
|
||||
startDttm: Date.now() - 500,
|
||||
@@ -683,6 +688,7 @@ export const successfulQuery: QueryResponse = {
|
||||
cached: false,
|
||||
ctas: false,
|
||||
id: 'ryhMUZCGb',
|
||||
sqlEditorImmutableId: 'ryhMUZCGb_immutable',
|
||||
progress: 100,
|
||||
state: QueryState.Success,
|
||||
startDttm: Date.now() - 500,
|
||||
|
||||
+10
-4
@@ -1019,10 +1019,16 @@ class DatasourceEditor extends PureComponent {
|
||||
<Field
|
||||
fieldKey="default_endpoint"
|
||||
label={t('Default URL')}
|
||||
description={t(
|
||||
`Default URL to redirect to when accessing from the dataset list page.
|
||||
Accepts relative URLs such as <span style=„white-space: nowrap;”>/superset/dashboard/{id}/</span>`,
|
||||
)}
|
||||
description={
|
||||
<>
|
||||
{t(
|
||||
'Default URL to redirect to when accessing from the dataset list page. Accepts relative URLs such as',
|
||||
)}{' '}
|
||||
<Typography.Text code>
|
||||
/superset/dashboard/{'{id}'}/
|
||||
</Typography.Text>
|
||||
</>
|
||||
}
|
||||
control={<TextControl controlId="default_endpoint" />}
|
||||
/>
|
||||
<Field
|
||||
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
} from 'src/SqlLab/actions/sqlLab';
|
||||
import { RootState, store } from 'src/views/store';
|
||||
import { AnyListenerPredicate } from '@reduxjs/toolkit';
|
||||
import memoizeOne from 'memoize-one';
|
||||
import type { SqlLabRootState } from 'src/SqlLab/types';
|
||||
import { Disposable } from '../models';
|
||||
import { createActionListener } from '../utils';
|
||||
@@ -198,13 +197,10 @@ const getActiveEditorImmutableId = () => {
|
||||
return activeEditor?.immutableId;
|
||||
};
|
||||
|
||||
// Memoized version to avoid repeated store lookups when active editor hasn't changed
|
||||
const getActiveEditorId = memoizeOne(getActiveEditorImmutableId);
|
||||
|
||||
const predicate = (actionType: string): AnyListenerPredicate<RootState> => {
|
||||
// Capture the immutable ID of the active editor at the time the listener is created
|
||||
// This ID never changes for a tab, ensuring stable event routing
|
||||
const registrationImmutableId = getActiveEditorId();
|
||||
const registrationImmutableId = getActiveEditorImmutableId();
|
||||
|
||||
return action => {
|
||||
if (action.type !== actionType) return false;
|
||||
@@ -212,14 +208,15 @@ const predicate = (actionType: string): AnyListenerPredicate<RootState> => {
|
||||
// If we don't have a registration ID, don't filter events
|
||||
if (!registrationImmutableId) return true;
|
||||
|
||||
// For query events, use the immutableId directly from the action payload
|
||||
if (action.query?.immutableId) {
|
||||
return action.query.immutableId === registrationImmutableId;
|
||||
// For query events, use the sqlEditorImmutableId directly from the action payload
|
||||
if (action.query?.sqlEditorImmutableId) {
|
||||
return action.query.sqlEditorImmutableId === registrationImmutableId;
|
||||
}
|
||||
|
||||
// For tab events, we need to find the immutable ID of the affected tab
|
||||
if (action.queryEditor?.id) {
|
||||
const queryEditor = findQueryEditor(action.queryEditor.id);
|
||||
const queryEditorId = action.queryEditor?.id || action.query?.sqlEditorId;
|
||||
if (queryEditorId) {
|
||||
const queryEditor = findQueryEditor(queryEditorId);
|
||||
return queryEditor?.immutableId === registrationImmutableId;
|
||||
}
|
||||
|
||||
|
||||
@@ -208,8 +208,7 @@ class TextAreaControl extends Component {
|
||||
buttonSize="small"
|
||||
style={{ marginTop: this.props.theme.sizeUnit }}
|
||||
>
|
||||
{t('Edit')} <strong>{this.props.language}</strong>{' '}
|
||||
{t('in modal')}
|
||||
{t('Edit %s in modal', this.props.language)}
|
||||
</Button>
|
||||
}
|
||||
modalBody={this.renderModalBody(true)}
|
||||
|
||||
@@ -66,6 +66,7 @@ export const mapQueryResponse = (
|
||||
): Omit<
|
||||
Query,
|
||||
| 'tempSchema'
|
||||
| 'sqlEditorImmutableId'
|
||||
| 'started'
|
||||
| 'time'
|
||||
| 'duration'
|
||||
|
||||
@@ -103,6 +103,9 @@ const Actions = styled.div`
|
||||
}
|
||||
}
|
||||
color: ${theme.colorTextDisabled};
|
||||
&:hover {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.ant-menu-item:hover {
|
||||
cursor: default;
|
||||
}
|
||||
@@ -479,7 +482,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={allowEdit ? 'action-button' : 'disabled'}
|
||||
className={`action-button ${allowEdit ? '' : 'disabled'}`}
|
||||
onClick={allowEdit ? handleEdit : undefined}
|
||||
>
|
||||
<Icons.EditOutlined iconSize="l" />
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
Typography,
|
||||
Icons,
|
||||
} from '@superset-ui/core/components';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useState, useEffect, useMemo } from 'react';
|
||||
import { capitalize } from 'lodash/fp';
|
||||
import { addDangerToast } from 'src/components/MessageToasts/actions';
|
||||
import { useDispatch } from 'react-redux';
|
||||
@@ -82,6 +82,26 @@ export default function Login() {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const bootstrapData = getBootstrapData();
|
||||
const nextUrl = useMemo(() => {
|
||||
try {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
return params.get('next') || '';
|
||||
} catch (_error) {
|
||||
return '';
|
||||
}
|
||||
}, []);
|
||||
|
||||
const loginEndpoint = useMemo(
|
||||
() => (nextUrl ? `/login/?next=${encodeURIComponent(nextUrl)}` : '/login/'),
|
||||
[nextUrl],
|
||||
);
|
||||
|
||||
const buildProviderLoginUrl = (providerName: string) => {
|
||||
const base = `/login/${providerName}`;
|
||||
return nextUrl
|
||||
? `${base}${base.includes('?') ? '&' : '?'}next=${encodeURIComponent(nextUrl)}`
|
||||
: base;
|
||||
};
|
||||
|
||||
const authType: AuthType = bootstrapData.common.conf.AUTH_TYPE;
|
||||
const providers: Provider[] = bootstrapData.common.conf.AUTH_PROVIDERS;
|
||||
@@ -109,7 +129,7 @@ export default function Login() {
|
||||
sessionStorage.setItem('login_attempted', 'true');
|
||||
|
||||
// Use standard form submission for Flask-AppBuilder compatibility
|
||||
SupersetClient.postForm('/login/', values, '');
|
||||
SupersetClient.postForm(loginEndpoint, values, '');
|
||||
};
|
||||
|
||||
const getAuthIconElement = (
|
||||
@@ -146,7 +166,7 @@ export default function Login() {
|
||||
{providers.map((provider: OIDProvider) => (
|
||||
<Form.Item<LoginForm>>
|
||||
<Button
|
||||
href={`/login/${provider.name}`}
|
||||
href={buildProviderLoginUrl(provider.name)}
|
||||
block
|
||||
iconPosition="start"
|
||||
icon={getAuthIconElement(provider.name)}
|
||||
@@ -164,7 +184,7 @@ export default function Login() {
|
||||
{providers.map((provider: OAuthProvider) => (
|
||||
<Form.Item<LoginForm>>
|
||||
<Button
|
||||
href={`/login/${provider.name}`}
|
||||
href={buildProviderLoginUrl(provider.name)}
|
||||
block
|
||||
iconPosition="start"
|
||||
icon={getAuthIconElement(provider.name)}
|
||||
|
||||
@@ -62,6 +62,7 @@ jest.mock('src/views/CRUD/hooks', () => ({
|
||||
|
||||
// Mock the useThemeContext hook
|
||||
const mockSetTemporaryTheme = jest.fn();
|
||||
const mockGetAppliedThemeId = jest.fn();
|
||||
jest.mock('src/theme/ThemeProvider', () => ({
|
||||
...jest.requireActual('src/theme/ThemeProvider'),
|
||||
useThemeContext: jest.fn(),
|
||||
@@ -141,10 +142,13 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
// Mock useThemeContext
|
||||
mockGetAppliedThemeId.mockReturnValue(null);
|
||||
(useThemeContext as jest.Mock).mockReturnValue({
|
||||
getCurrentCrudThemeId: jest.fn().mockReturnValue('1'),
|
||||
appliedTheme: { theme_name: 'Light Theme', id: 1 },
|
||||
setTemporaryTheme: mockSetTemporaryTheme,
|
||||
hasDevOverride: jest.fn().mockReturnValue(false),
|
||||
getAppliedThemeId: mockGetAppliedThemeId,
|
||||
});
|
||||
|
||||
fetchMock.reset();
|
||||
@@ -460,7 +464,7 @@ test('shows create theme button when user has permissions', async () => {
|
||||
expect(addButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('clicking apply button calls setTemporaryTheme with parsed theme data', async () => {
|
||||
test('clicking apply button calls setTemporaryTheme with parsed theme data and ID', async () => {
|
||||
render(
|
||||
<ThemesList
|
||||
user={mockUser}
|
||||
@@ -483,8 +487,106 @@ test('clicking apply button calls setTemporaryTheme with parsed theme data', asy
|
||||
await userEvent.click(applyButtons[0]);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockSetTemporaryTheme).toHaveBeenCalledWith({
|
||||
colors: { primary: '#ffffff' },
|
||||
});
|
||||
expect(mockSetTemporaryTheme).toHaveBeenCalledWith(
|
||||
{
|
||||
colors: { primary: '#ffffff' },
|
||||
},
|
||||
1, // theme ID
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('applying a local theme calls setTemporaryTheme with theme ID', async () => {
|
||||
render(
|
||||
<ThemesList
|
||||
user={mockUser}
|
||||
addDangerToast={jest.fn()}
|
||||
addSuccessToast={jest.fn()}
|
||||
/>,
|
||||
{
|
||||
useRedux: true,
|
||||
useRouter: true,
|
||||
useQueryParams: true,
|
||||
useTheme: true,
|
||||
},
|
||||
);
|
||||
|
||||
await screen.findByText('Custom Theme');
|
||||
|
||||
// Find and click the apply button for the first theme
|
||||
const applyButtons = await screen.findAllByTestId('apply-action');
|
||||
await userEvent.click(applyButtons[0]);
|
||||
|
||||
// Check that setTemporaryTheme was called with both theme config and ID
|
||||
await waitFor(() => {
|
||||
expect(mockSetTemporaryTheme).toHaveBeenCalledWith(
|
||||
{ colors: { primary: '#ffffff' } },
|
||||
1, // theme ID
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('component loads successfully with applied theme ID set', async () => {
|
||||
// This test verifies that having a stored theme ID doesn't break the component
|
||||
// Mock hasDevOverride to return true since we have a dev override set
|
||||
mockGetAppliedThemeId.mockReturnValue(1);
|
||||
(useThemeContext as jest.Mock).mockReturnValue({
|
||||
getCurrentCrudThemeId: jest.fn().mockReturnValue('1'),
|
||||
appliedTheme: { theme_name: 'Light Theme', id: 1 },
|
||||
setTemporaryTheme: mockSetTemporaryTheme,
|
||||
hasDevOverride: jest.fn().mockReturnValue(true),
|
||||
getAppliedThemeId: mockGetAppliedThemeId,
|
||||
});
|
||||
|
||||
render(
|
||||
<ThemesList
|
||||
user={mockUser}
|
||||
addDangerToast={jest.fn()}
|
||||
addSuccessToast={jest.fn()}
|
||||
/>,
|
||||
{
|
||||
useRedux: true,
|
||||
useRouter: true,
|
||||
useQueryParams: true,
|
||||
useTheme: true,
|
||||
},
|
||||
);
|
||||
|
||||
// Wait for list to load and verify it renders successfully
|
||||
await screen.findByText('Custom Theme');
|
||||
|
||||
// Verify the component called getAppliedThemeId
|
||||
expect(mockGetAppliedThemeId).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('component loads successfully and preserves applied theme state', async () => {
|
||||
// Mock hasDevOverride to return true and getAppliedThemeId to return a theme
|
||||
mockGetAppliedThemeId.mockReturnValue(1);
|
||||
(useThemeContext as jest.Mock).mockReturnValue({
|
||||
getCurrentCrudThemeId: jest.fn().mockReturnValue('1'),
|
||||
appliedTheme: { theme_name: 'Light Theme', id: 1 },
|
||||
setTemporaryTheme: mockSetTemporaryTheme,
|
||||
hasDevOverride: jest.fn().mockReturnValue(true),
|
||||
getAppliedThemeId: mockGetAppliedThemeId,
|
||||
});
|
||||
|
||||
render(
|
||||
<ThemesList
|
||||
user={mockUser}
|
||||
addDangerToast={jest.fn()}
|
||||
addSuccessToast={jest.fn()}
|
||||
/>,
|
||||
{
|
||||
useRedux: true,
|
||||
useRouter: true,
|
||||
useQueryParams: true,
|
||||
useTheme: true,
|
||||
},
|
||||
);
|
||||
|
||||
// Wait for list to load
|
||||
await screen.findByText('Custom Theme');
|
||||
|
||||
// Verify getAppliedThemeId is called during component mount
|
||||
expect(mockGetAppliedThemeId).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { t, SupersetClient, styled } from '@superset-ui/core';
|
||||
import {
|
||||
Tag,
|
||||
@@ -110,15 +110,27 @@ function ThemesList({
|
||||
refreshData,
|
||||
toggleBulkSelect,
|
||||
} = useListViewResource<ThemeObject>('theme', t('Themes'), addDangerToast);
|
||||
const { setTemporaryTheme, getCurrentCrudThemeId } = useThemeContext();
|
||||
const { setTemporaryTheme, hasDevOverride, getAppliedThemeId } =
|
||||
useThemeContext();
|
||||
const [themeModalOpen, setThemeModalOpen] = useState<boolean>(false);
|
||||
const [currentTheme, setCurrentTheme] = useState<ThemeObject | null>(null);
|
||||
const [preparingExport, setPreparingExport] = useState<boolean>(false);
|
||||
const [importingTheme, showImportModal] = useState<boolean>(false);
|
||||
const [appliedThemeId, setAppliedThemeId] = useState<number | null>(null);
|
||||
const [appliedThemeId, setLocalAppliedThemeId] = useState<number | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
const { showConfirm, ConfirmModal } = useConfirmModal();
|
||||
|
||||
useEffect(() => {
|
||||
if (hasDevOverride()) {
|
||||
const storedThemeId = getAppliedThemeId();
|
||||
setLocalAppliedThemeId(storedThemeId);
|
||||
} else {
|
||||
setLocalAppliedThemeId(null);
|
||||
}
|
||||
}, [hasDevOverride, getAppliedThemeId]);
|
||||
|
||||
const canCreate = hasPerm('can_write');
|
||||
const canEdit = hasPerm('can_write');
|
||||
const canDelete = hasPerm('can_write');
|
||||
@@ -201,8 +213,11 @@ function ThemesList({
|
||||
if (themeObj.json_data) {
|
||||
try {
|
||||
const themeConfig = JSON.parse(themeObj.json_data);
|
||||
setTemporaryTheme(themeConfig);
|
||||
setAppliedThemeId(themeObj.id || null);
|
||||
const themeId = themeObj.id || null;
|
||||
|
||||
setTemporaryTheme(themeConfig, themeId);
|
||||
setLocalAppliedThemeId(themeId);
|
||||
|
||||
addSuccessToast(t('Local theme set to "%s"', themeObj.theme_name));
|
||||
} catch (error) {
|
||||
addDangerToast(
|
||||
@@ -217,23 +232,26 @@ function ThemesList({
|
||||
function handleThemeModalApply() {
|
||||
// Clear any previously applied theme ID when applying from modal
|
||||
// since the modal theme might not have an ID yet (unsaved theme)
|
||||
setAppliedThemeId(null);
|
||||
setLocalAppliedThemeId(null);
|
||||
}
|
||||
|
||||
const handleBulkThemeExport = async (themesToExport: ThemeObject[]) => {
|
||||
const ids = themesToExport
|
||||
.map(({ id }) => id)
|
||||
.filter((id): id is number => id !== undefined);
|
||||
setPreparingExport(true);
|
||||
try {
|
||||
await handleResourceExport('theme', ids, () => {
|
||||
const handleBulkThemeExport = useCallback(
|
||||
async (themesToExport: ThemeObject[]) => {
|
||||
const ids = themesToExport
|
||||
.map(({ id }) => id)
|
||||
.filter((id): id is number => id !== undefined);
|
||||
setPreparingExport(true);
|
||||
try {
|
||||
await handleResourceExport('theme', ids, () => {
|
||||
setPreparingExport(false);
|
||||
});
|
||||
} catch (error) {
|
||||
setPreparingExport(false);
|
||||
});
|
||||
} catch (error) {
|
||||
setPreparingExport(false);
|
||||
addDangerToast(t('There was an issue exporting the selected themes'));
|
||||
}
|
||||
};
|
||||
addDangerToast(t('There was an issue exporting the selected themes'));
|
||||
}
|
||||
},
|
||||
[addDangerToast],
|
||||
);
|
||||
|
||||
const openThemeImportModal = () => {
|
||||
showImportModal(true);
|
||||
@@ -346,11 +364,10 @@ function ThemesList({
|
||||
() => [
|
||||
{
|
||||
Cell: ({ row: { original } }: any) => {
|
||||
const currentCrudThemeId = getCurrentCrudThemeId();
|
||||
const isCurrentTheme =
|
||||
(currentCrudThemeId &&
|
||||
original.id?.toString() === currentCrudThemeId) ||
|
||||
(appliedThemeId && original.id === appliedThemeId);
|
||||
hasDevOverride() &&
|
||||
appliedThemeId &&
|
||||
original.id === appliedThemeId;
|
||||
|
||||
return (
|
||||
<FlexRowContainer>
|
||||
@@ -520,11 +537,12 @@ function ThemesList({
|
||||
canDelete,
|
||||
canApply,
|
||||
canExport,
|
||||
getCurrentCrudThemeId,
|
||||
hasDevOverride,
|
||||
appliedThemeId,
|
||||
canSetSystemThemes,
|
||||
addDangerToast,
|
||||
handleThemeApply,
|
||||
handleBulkThemeExport,
|
||||
handleSetSystemDefault,
|
||||
handleUnsetSystemDefault,
|
||||
handleSetSystemDark,
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
type ThemeControllerOptions,
|
||||
type ThemeStorage,
|
||||
isThemeConfigDark,
|
||||
makeApi,
|
||||
Theme,
|
||||
ThemeMode,
|
||||
themeObject as supersetThemeObject,
|
||||
@@ -37,6 +38,7 @@ const STORAGE_KEYS = {
|
||||
THEME_MODE: 'superset-theme-mode',
|
||||
CRUD_THEME_ID: 'superset-crud-theme-id',
|
||||
DEV_THEME_OVERRIDE: 'superset-dev-theme-override',
|
||||
APPLIED_THEME_ID: 'superset-applied-theme-id',
|
||||
} as const;
|
||||
|
||||
const MEDIA_QUERY_DARK_SCHEME = '(prefers-color-scheme: dark)';
|
||||
@@ -224,14 +226,14 @@ export class ThemeController {
|
||||
return this.dashboardThemes.get(themeId)!;
|
||||
}
|
||||
|
||||
// Fetch theme config from API
|
||||
const response = await fetch(`/api/v1/theme/${themeId}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
// Fetch theme config from API using SupersetClient for proper auth
|
||||
const getTheme = makeApi<void, { result: { json_data: string } }>({
|
||||
method: 'GET',
|
||||
endpoint: `/api/v1/theme/${themeId}`,
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
const themeConfig = JSON.parse(data.result.json_data);
|
||||
const { result } = await getTheme();
|
||||
const themeConfig = JSON.parse(result.json_data);
|
||||
|
||||
if (themeConfig) {
|
||||
// Controller creates and owns the dashboard theme
|
||||
@@ -303,7 +305,12 @@ export class ThemeController {
|
||||
public setThemeMode(mode: ThemeMode): void {
|
||||
this.validateModeUpdatePermission(mode);
|
||||
|
||||
if (this.currentMode === mode) return;
|
||||
if (
|
||||
this.currentMode === mode &&
|
||||
!this.devThemeOverride &&
|
||||
!this.crudThemeId
|
||||
)
|
||||
return;
|
||||
|
||||
// Clear any local overrides when explicitly selecting a theme mode
|
||||
// This ensures the selected mode takes effect and provides clear UX
|
||||
@@ -367,8 +374,12 @@ export class ThemeController {
|
||||
* Sets a temporary theme override for development purposes.
|
||||
* This does not persist the theme but allows live preview.
|
||||
* @param theme - The theme configuration to apply temporarily
|
||||
* @param themeId - Optional theme ID to track which theme was applied (for UI display)
|
||||
*/
|
||||
public setTemporaryTheme(theme: AnyThemeConfig): void {
|
||||
public setTemporaryTheme(
|
||||
theme: AnyThemeConfig,
|
||||
themeId?: number | null,
|
||||
): void {
|
||||
this.validateThemeUpdatePermission();
|
||||
|
||||
this.devThemeOverride = theme;
|
||||
@@ -377,6 +388,11 @@ export class ThemeController {
|
||||
JSON.stringify(theme),
|
||||
);
|
||||
|
||||
// Store the theme ID if provided
|
||||
if (themeId !== undefined) {
|
||||
this.setAppliedThemeId(themeId);
|
||||
}
|
||||
|
||||
const mergedTheme = this.getThemeForMode(this.currentMode);
|
||||
if (mergedTheme) this.updateTheme(mergedTheme);
|
||||
}
|
||||
@@ -392,6 +408,7 @@ export class ThemeController {
|
||||
|
||||
this.storage.removeItem(STORAGE_KEYS.DEV_THEME_OVERRIDE);
|
||||
this.storage.removeItem(STORAGE_KEYS.CRUD_THEME_ID);
|
||||
this.storage.removeItem(STORAGE_KEYS.APPLIED_THEME_ID);
|
||||
|
||||
// Clear dashboard themes cache
|
||||
this.dashboardThemes.clear();
|
||||
@@ -413,6 +430,34 @@ export class ThemeController {
|
||||
return this.devThemeOverride !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the applied theme ID (for UI display purposes).
|
||||
*/
|
||||
public getAppliedThemeId(): number | null {
|
||||
try {
|
||||
const storedId = this.storage.getItem(STORAGE_KEYS.APPLIED_THEME_ID);
|
||||
return storedId ? parseInt(storedId, 10) : null;
|
||||
} catch (error) {
|
||||
console.warn('Failed to get applied theme ID:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the applied theme ID (for UI display purposes).
|
||||
*/
|
||||
public setAppliedThemeId(themeId: number | null): void {
|
||||
try {
|
||||
if (themeId !== null) {
|
||||
this.storage.setItem(STORAGE_KEYS.APPLIED_THEME_ID, themeId.toString());
|
||||
} else {
|
||||
this.storage.removeItem(STORAGE_KEYS.APPLIED_THEME_ID);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to set applied theme ID:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if OS preference detection is allowed.
|
||||
* Allowed when dark theme is available (including base dark theme)
|
||||
@@ -817,13 +862,14 @@ export class ThemeController {
|
||||
themeId: string,
|
||||
): Promise<AnyThemeConfig | null> {
|
||||
try {
|
||||
const response = await fetch(`/api/v1/theme/${themeId}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
// Use SupersetClient for proper authentication handling
|
||||
const getTheme = makeApi<void, { result: { json_data: string } }>({
|
||||
method: 'GET',
|
||||
endpoint: `/api/v1/theme/${themeId}`,
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
const themeConfig = JSON.parse(data.result.json_data);
|
||||
const { result } = await getTheme();
|
||||
const themeConfig = JSON.parse(result.json_data);
|
||||
|
||||
return themeConfig;
|
||||
} catch (error) {
|
||||
|
||||
@@ -117,6 +117,11 @@ export function SupersetThemeProvider({
|
||||
[themeController],
|
||||
);
|
||||
|
||||
const getAppliedThemeId = useCallback(
|
||||
() => themeController.getAppliedThemeId(),
|
||||
[themeController],
|
||||
);
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
theme: currentTheme,
|
||||
@@ -132,6 +137,7 @@ export function SupersetThemeProvider({
|
||||
canSetTheme,
|
||||
canDetectOSPreference,
|
||||
createDashboardThemeProvider,
|
||||
getAppliedThemeId,
|
||||
}),
|
||||
[
|
||||
currentTheme,
|
||||
@@ -147,6 +153,7 @@ export function SupersetThemeProvider({
|
||||
canSetTheme,
|
||||
canDetectOSPreference,
|
||||
createDashboardThemeProvider,
|
||||
getAppliedThemeId,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -1137,4 +1137,236 @@ describe('ThemeController', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('setThemeMode clears dev override and crud theme from storage', () => {
|
||||
mockGetBootstrapData.mockReturnValue(
|
||||
createMockBootstrapData({
|
||||
default: DEFAULT_THEME,
|
||||
dark: DARK_THEME,
|
||||
}),
|
||||
);
|
||||
|
||||
mockLocalStorage.getItem.mockReturnValue(null);
|
||||
|
||||
const controller = new ThemeController({
|
||||
storage: mockLocalStorage,
|
||||
themeObject: mockThemeObject,
|
||||
});
|
||||
|
||||
// Simulate having overrides after initialization using Reflect to access private properties
|
||||
Reflect.set(controller, 'devThemeOverride', {
|
||||
token: { colorPrimary: '#ff0000' },
|
||||
});
|
||||
Reflect.set(controller, 'crudThemeId', '123');
|
||||
|
||||
jest.clearAllMocks();
|
||||
|
||||
// Change theme mode - should clear the overrides
|
||||
controller.setThemeMode(ThemeMode.DARK);
|
||||
|
||||
// Verify both storage keys were removed
|
||||
expect(mockLocalStorage.removeItem).toHaveBeenCalledWith(
|
||||
'superset-dev-theme-override',
|
||||
);
|
||||
expect(mockLocalStorage.removeItem).toHaveBeenCalledWith(
|
||||
'superset-crud-theme-id',
|
||||
);
|
||||
});
|
||||
|
||||
test('setThemeMode can be called with same mode when overrides exist', () => {
|
||||
mockGetBootstrapData.mockReturnValue(
|
||||
createMockBootstrapData({
|
||||
default: DEFAULT_THEME,
|
||||
dark: DARK_THEME,
|
||||
}),
|
||||
);
|
||||
|
||||
mockLocalStorage.getItem.mockReturnValue(null);
|
||||
|
||||
const controller = new ThemeController({
|
||||
storage: mockLocalStorage,
|
||||
themeObject: mockThemeObject,
|
||||
});
|
||||
|
||||
jest.clearAllMocks();
|
||||
|
||||
// Simulate having dev override after initialization using Reflect
|
||||
Reflect.set(controller, 'devThemeOverride', {
|
||||
token: { colorPrimary: '#ff0000' },
|
||||
});
|
||||
|
||||
// Call setThemeMode with DEFAULT mode - should clear override
|
||||
controller.setThemeMode(ThemeMode.DEFAULT);
|
||||
|
||||
// Verify override was removed even though mode is the same
|
||||
expect(mockLocalStorage.removeItem).toHaveBeenCalledWith(
|
||||
'superset-dev-theme-override',
|
||||
);
|
||||
expect(mockLocalStorage.removeItem).toHaveBeenCalledWith(
|
||||
'superset-crud-theme-id',
|
||||
);
|
||||
|
||||
// Theme should still be updated to clear the override
|
||||
expect(mockSetConfig).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('setThemeMode with no override and same mode does not trigger update', () => {
|
||||
mockGetBootstrapData.mockReturnValue(
|
||||
createMockBootstrapData({
|
||||
default: DEFAULT_THEME,
|
||||
dark: DARK_THEME,
|
||||
}),
|
||||
);
|
||||
|
||||
const controller = new ThemeController({
|
||||
storage: mockLocalStorage,
|
||||
themeObject: mockThemeObject,
|
||||
});
|
||||
|
||||
// Set mode to DEFAULT
|
||||
controller.setThemeMode(ThemeMode.DEFAULT);
|
||||
|
||||
jest.clearAllMocks();
|
||||
|
||||
// Call again with same mode and no override - should skip
|
||||
controller.setThemeMode(ThemeMode.DEFAULT);
|
||||
|
||||
// Should not trigger any updates
|
||||
expect(mockSetConfig).not.toHaveBeenCalled();
|
||||
expect(mockLocalStorage.removeItem).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('hasDevOverride returns true when dev override is set', () => {
|
||||
mockGetBootstrapData.mockReturnValue(
|
||||
createMockBootstrapData({
|
||||
default: DEFAULT_THEME,
|
||||
dark: DARK_THEME,
|
||||
}),
|
||||
);
|
||||
|
||||
mockLocalStorage.getItem.mockReturnValue(null);
|
||||
|
||||
const controller = new ThemeController({
|
||||
storage: mockLocalStorage,
|
||||
themeObject: mockThemeObject,
|
||||
});
|
||||
|
||||
// Simulate dev override after initialization using Reflect
|
||||
Reflect.set(controller, 'devThemeOverride', {
|
||||
token: { colorPrimary: '#ff0000' },
|
||||
});
|
||||
|
||||
expect(controller.hasDevOverride()).toBe(true);
|
||||
});
|
||||
|
||||
test('hasDevOverride returns false when no dev override in storage', () => {
|
||||
mockGetBootstrapData.mockReturnValue(
|
||||
createMockBootstrapData({
|
||||
default: DEFAULT_THEME,
|
||||
dark: DARK_THEME,
|
||||
}),
|
||||
);
|
||||
|
||||
mockLocalStorage.getItem.mockReturnValue(null);
|
||||
|
||||
const controller = new ThemeController({
|
||||
storage: mockLocalStorage,
|
||||
themeObject: mockThemeObject,
|
||||
});
|
||||
|
||||
expect(controller.hasDevOverride()).toBe(false);
|
||||
});
|
||||
|
||||
test('clearLocalOverrides removes dev override, crud theme, and applied theme ID', () => {
|
||||
mockGetBootstrapData.mockReturnValue(
|
||||
createMockBootstrapData({
|
||||
default: DEFAULT_THEME,
|
||||
dark: DARK_THEME,
|
||||
}),
|
||||
);
|
||||
|
||||
mockLocalStorage.getItem.mockReturnValue(null);
|
||||
|
||||
const controller = new ThemeController({
|
||||
storage: mockLocalStorage,
|
||||
themeObject: mockThemeObject,
|
||||
});
|
||||
|
||||
jest.clearAllMocks();
|
||||
|
||||
// Clear overrides
|
||||
controller.clearLocalOverrides();
|
||||
|
||||
// Verify all storage keys are removed
|
||||
expect(mockLocalStorage.removeItem).toHaveBeenCalledWith(
|
||||
'superset-dev-theme-override',
|
||||
);
|
||||
expect(mockLocalStorage.removeItem).toHaveBeenCalledWith(
|
||||
'superset-crud-theme-id',
|
||||
);
|
||||
expect(mockLocalStorage.removeItem).toHaveBeenCalledWith(
|
||||
'superset-applied-theme-id',
|
||||
);
|
||||
|
||||
// Should reset to default theme
|
||||
expect(mockSetConfig).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('getAppliedThemeId returns stored theme ID', () => {
|
||||
mockLocalStorage.getItem.mockImplementation((key: string) => {
|
||||
if (key === 'superset-applied-theme-id') {
|
||||
return '42';
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
const controller = new ThemeController({
|
||||
storage: mockLocalStorage,
|
||||
themeObject: mockThemeObject,
|
||||
});
|
||||
|
||||
expect(controller.getAppliedThemeId()).toBe(42);
|
||||
});
|
||||
|
||||
test('getAppliedThemeId returns null when no theme ID is stored', () => {
|
||||
mockLocalStorage.getItem.mockReturnValue(null);
|
||||
|
||||
const controller = new ThemeController({
|
||||
storage: mockLocalStorage,
|
||||
themeObject: mockThemeObject,
|
||||
});
|
||||
|
||||
expect(controller.getAppliedThemeId()).toBeNull();
|
||||
});
|
||||
|
||||
test('setAppliedThemeId stores theme ID in storage', () => {
|
||||
const controller = new ThemeController({
|
||||
storage: mockLocalStorage,
|
||||
themeObject: mockThemeObject,
|
||||
});
|
||||
|
||||
jest.clearAllMocks();
|
||||
|
||||
controller.setAppliedThemeId(123);
|
||||
|
||||
expect(mockLocalStorage.setItem).toHaveBeenCalledWith(
|
||||
'superset-applied-theme-id',
|
||||
'123',
|
||||
);
|
||||
});
|
||||
|
||||
test('setAppliedThemeId removes theme ID when null is passed', () => {
|
||||
const controller = new ThemeController({
|
||||
storage: mockLocalStorage,
|
||||
themeObject: mockThemeObject,
|
||||
});
|
||||
|
||||
jest.clearAllMocks();
|
||||
|
||||
controller.setAppliedThemeId(null);
|
||||
|
||||
expect(mockLocalStorage.removeItem).toHaveBeenCalledWith(
|
||||
'superset-applied-theme-id',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -276,3 +276,123 @@ test('handles various resource types', async () => {
|
||||
|
||||
expect(doneMock).toHaveBeenCalledTimes(5);
|
||||
});
|
||||
|
||||
test('handles network errors and logs them', async () => {
|
||||
const networkError = new Error('Network request failed');
|
||||
(SupersetClient.get as jest.Mock).mockRejectedValue(networkError);
|
||||
|
||||
const doneMock = jest.fn();
|
||||
|
||||
await expect(
|
||||
handleResourceExport('dashboard', [1], doneMock),
|
||||
).rejects.toThrow('Network request failed');
|
||||
|
||||
expect(logging.error).toHaveBeenCalledWith(
|
||||
'Resource export failed:',
|
||||
networkError,
|
||||
);
|
||||
expect(doneMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('handles 404 errors when resource not found', async () => {
|
||||
const notFoundError = new Error('Not found');
|
||||
(SupersetClient.get as jest.Mock).mockRejectedValue(notFoundError);
|
||||
|
||||
const doneMock = jest.fn();
|
||||
|
||||
await expect(
|
||||
handleResourceExport('dashboard', [999], doneMock),
|
||||
).rejects.toThrow('Not found');
|
||||
|
||||
expect(doneMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('handles empty response from server', async () => {
|
||||
const emptyBlob = new Blob([], { type: 'application/zip' });
|
||||
mockResponse = {
|
||||
headers: new Headers({
|
||||
'Content-Disposition': 'attachment; filename="empty.zip"',
|
||||
}),
|
||||
blob: jest.fn().mockResolvedValue(emptyBlob),
|
||||
} as unknown as Response;
|
||||
(SupersetClient.get as jest.Mock).mockResolvedValue(mockResponse);
|
||||
|
||||
const doneMock = jest.fn();
|
||||
await handleResourceExport('dashboard', [1], doneMock);
|
||||
|
||||
expect(window.URL.createObjectURL).toHaveBeenCalledWith(emptyBlob);
|
||||
expect(doneMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('cleans up blob URL even when download fails', async () => {
|
||||
const mockAnchor = document.createElement('a');
|
||||
mockAnchor.click = jest.fn().mockImplementation(() => {
|
||||
throw new Error('Click failed');
|
||||
});
|
||||
|
||||
createElementSpy.mockRestore();
|
||||
createElementSpy = jest
|
||||
.spyOn(document, 'createElement')
|
||||
.mockReturnValue(mockAnchor);
|
||||
|
||||
const doneMock = jest.fn();
|
||||
|
||||
await expect(
|
||||
handleResourceExport('dashboard', [1], doneMock),
|
||||
).rejects.toThrow('Click failed');
|
||||
|
||||
// Verify cleanup still happens
|
||||
expect(window.URL.revokeObjectURL).toHaveBeenCalledWith('blob:mock-url');
|
||||
expect(doneMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('handles malformed Content-Disposition header', async () => {
|
||||
mockResponse = {
|
||||
headers: new Headers({
|
||||
'Content-Disposition': 'not-a-valid-header',
|
||||
}),
|
||||
blob: jest.fn().mockResolvedValue(mockBlob),
|
||||
} as unknown as Response;
|
||||
(SupersetClient.get as jest.Mock).mockResolvedValue(mockResponse);
|
||||
|
||||
(contentDisposition.parse as jest.Mock).mockImplementationOnce(() => {
|
||||
throw new Error('Parse error');
|
||||
});
|
||||
|
||||
const doneMock = jest.fn();
|
||||
await handleResourceExport('dataset', [5], doneMock);
|
||||
|
||||
// Should fall back to default filename
|
||||
const anchor = document.createElement('a');
|
||||
expect(anchor.download).toBe('dataset_export.zip');
|
||||
expect(logging.warn).toHaveBeenCalledWith(
|
||||
'Failed to parse Content-Disposition header:',
|
||||
expect.any(Error),
|
||||
);
|
||||
});
|
||||
|
||||
test('handles missing headers object', async () => {
|
||||
mockResponse = {
|
||||
headers: new Headers(),
|
||||
blob: jest.fn().mockResolvedValue(mockBlob),
|
||||
} as unknown as Response;
|
||||
(SupersetClient.get as jest.Mock).mockResolvedValue(mockResponse);
|
||||
|
||||
const doneMock = jest.fn();
|
||||
await handleResourceExport('chart', [7], doneMock);
|
||||
|
||||
const anchor = document.createElement('a');
|
||||
expect(anchor.download).toBe('chart_export.zip');
|
||||
expect(doneMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('handles export with empty IDs array', async () => {
|
||||
const doneMock = jest.fn();
|
||||
await handleResourceExport('dashboard', [], doneMock);
|
||||
|
||||
expect(SupersetClient.get).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
endpoint: '/api/v1/dashboard/export/?q=!()',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
Generated
+179
-179
@@ -25,12 +25,12 @@
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/jsonwebtoken": "^9.0.10",
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/node": "^24.7.2",
|
||||
"@types/node": "^24.9.1",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@types/ws": "^8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.26.0",
|
||||
"@typescript-eslint/parser": "^8.46.1",
|
||||
"eslint": "^9.37.0",
|
||||
"@typescript-eslint/parser": "^8.46.2",
|
||||
"eslint": "^9.38.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-lodash": "^8.0.0",
|
||||
"globals": "^16.4.0",
|
||||
@@ -40,7 +40,7 @@
|
||||
"ts-node": "^10.9.2",
|
||||
"tscw-config": "^1.1.2",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.46.1"
|
||||
"typescript-eslint": "^8.46.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.4",
|
||||
@@ -750,12 +750,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-array": {
|
||||
"version": "0.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
|
||||
"integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
|
||||
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/object-schema": "^2.1.6",
|
||||
"@eslint/object-schema": "^2.1.7",
|
||||
"debug": "^4.3.1",
|
||||
"minimatch": "^3.1.2"
|
||||
},
|
||||
@@ -764,9 +765,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-helpers": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz",
|
||||
"integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==",
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.1.tgz",
|
||||
"integrity": "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -847,9 +848,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz",
|
||||
"integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==",
|
||||
"version": "9.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz",
|
||||
"integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -860,10 +861,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/object-schema": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
|
||||
"integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
|
||||
"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
@@ -1857,13 +1859,13 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.7.2.tgz",
|
||||
"integrity": "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==",
|
||||
"version": "24.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz",
|
||||
"integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.14.0"
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/stack-utils": {
|
||||
@@ -1909,17 +1911,17 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz",
|
||||
"integrity": "sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz",
|
||||
"integrity": "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.46.1",
|
||||
"@typescript-eslint/type-utils": "8.46.1",
|
||||
"@typescript-eslint/utils": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1",
|
||||
"@typescript-eslint/scope-manager": "8.46.2",
|
||||
"@typescript-eslint/type-utils": "8.46.2",
|
||||
"@typescript-eslint/utils": "8.46.2",
|
||||
"@typescript-eslint/visitor-keys": "8.46.2",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^7.0.0",
|
||||
"natural-compare": "^1.4.0",
|
||||
@@ -1933,7 +1935,7 @@
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/parser": "^8.46.1",
|
||||
"@typescript-eslint/parser": "^8.46.2",
|
||||
"eslint": "^8.57.0 || ^9.0.0",
|
||||
"typescript": ">=4.8.4 <6.0.0"
|
||||
}
|
||||
@@ -1949,16 +1951,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.1.tgz",
|
||||
"integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.2.tgz",
|
||||
"integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1",
|
||||
"@typescript-eslint/scope-manager": "8.46.2",
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"@typescript-eslint/typescript-estree": "8.46.2",
|
||||
"@typescript-eslint/visitor-keys": "8.46.2",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1974,14 +1976,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/project-service": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.1.tgz",
|
||||
"integrity": "sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.2.tgz",
|
||||
"integrity": "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/tsconfig-utils": "^8.46.1",
|
||||
"@typescript-eslint/types": "^8.46.1",
|
||||
"@typescript-eslint/tsconfig-utils": "^8.46.2",
|
||||
"@typescript-eslint/types": "^8.46.2",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1996,14 +1998,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz",
|
||||
"integrity": "sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz",
|
||||
"integrity": "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1"
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"@typescript-eslint/visitor-keys": "8.46.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -2014,9 +2016,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.1.tgz",
|
||||
"integrity": "sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz",
|
||||
"integrity": "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -2031,15 +2033,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.1.tgz",
|
||||
"integrity": "sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz",
|
||||
"integrity": "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1",
|
||||
"@typescript-eslint/utils": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"@typescript-eslint/typescript-estree": "8.46.2",
|
||||
"@typescript-eslint/utils": "8.46.2",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^2.1.0"
|
||||
},
|
||||
@@ -2056,9 +2058,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.1.tgz",
|
||||
"integrity": "sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.2.tgz",
|
||||
"integrity": "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -2070,16 +2072,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz",
|
||||
"integrity": "sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz",
|
||||
"integrity": "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/project-service": "8.46.1",
|
||||
"@typescript-eslint/tsconfig-utils": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1",
|
||||
"@typescript-eslint/project-service": "8.46.2",
|
||||
"@typescript-eslint/tsconfig-utils": "8.46.2",
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"@typescript-eslint/visitor-keys": "8.46.2",
|
||||
"debug": "^4.3.4",
|
||||
"fast-glob": "^3.3.2",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -2125,16 +2127,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.1.tgz",
|
||||
"integrity": "sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.2.tgz",
|
||||
"integrity": "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.7.0",
|
||||
"@typescript-eslint/scope-manager": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1"
|
||||
"@typescript-eslint/scope-manager": "8.46.2",
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"@typescript-eslint/typescript-estree": "8.46.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -2149,13 +2151,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz",
|
||||
"integrity": "sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz",
|
||||
"integrity": "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"eslint-visitor-keys": "^4.2.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -2839,25 +2841,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.37.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz",
|
||||
"integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==",
|
||||
"version": "9.38.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.38.0.tgz",
|
||||
"integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
"@eslint/config-array": "^0.21.0",
|
||||
"@eslint/config-helpers": "^0.4.0",
|
||||
"@eslint/config-array": "^0.21.1",
|
||||
"@eslint/config-helpers": "^0.4.1",
|
||||
"@eslint/core": "^0.16.0",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "9.37.0",
|
||||
"@eslint/js": "9.38.0",
|
||||
"@eslint/plugin-kit": "^0.4.0",
|
||||
"@humanfs/node": "^0.16.6",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@humanwhocodes/retry": "^0.4.2",
|
||||
"@types/estree": "^1.0.6",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"ajv": "^6.12.4",
|
||||
"chalk": "^4.0.0",
|
||||
"cross-spawn": "^7.0.6",
|
||||
@@ -6305,16 +6306,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript-eslint": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.1.tgz",
|
||||
"integrity": "sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.2.tgz",
|
||||
"integrity": "sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "8.46.1",
|
||||
"@typescript-eslint/parser": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1",
|
||||
"@typescript-eslint/utils": "8.46.1"
|
||||
"@typescript-eslint/eslint-plugin": "8.46.2",
|
||||
"@typescript-eslint/parser": "8.46.2",
|
||||
"@typescript-eslint/typescript-estree": "8.46.2",
|
||||
"@typescript-eslint/utils": "8.46.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -6343,9 +6344,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz",
|
||||
"integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==",
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -7163,20 +7164,20 @@
|
||||
"dev": true
|
||||
},
|
||||
"@eslint/config-array": {
|
||||
"version": "0.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
|
||||
"integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
|
||||
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint/object-schema": "^2.1.6",
|
||||
"@eslint/object-schema": "^2.1.7",
|
||||
"debug": "^4.3.1",
|
||||
"minimatch": "^3.1.2"
|
||||
}
|
||||
},
|
||||
"@eslint/config-helpers": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz",
|
||||
"integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==",
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.1.tgz",
|
||||
"integrity": "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint/core": "^0.16.0"
|
||||
@@ -7232,15 +7233,15 @@
|
||||
}
|
||||
},
|
||||
"@eslint/js": {
|
||||
"version": "9.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz",
|
||||
"integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==",
|
||||
"version": "9.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz",
|
||||
"integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==",
|
||||
"dev": true
|
||||
},
|
||||
"@eslint/object-schema": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
|
||||
"integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
|
||||
"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
|
||||
"dev": true
|
||||
},
|
||||
"@eslint/plugin-kit": {
|
||||
@@ -8056,12 +8057,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "24.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.7.2.tgz",
|
||||
"integrity": "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==",
|
||||
"version": "24.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz",
|
||||
"integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"undici-types": "~7.14.0"
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
},
|
||||
"@types/stack-utils": {
|
||||
@@ -8106,16 +8107,16 @@
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz",
|
||||
"integrity": "sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz",
|
||||
"integrity": "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.46.1",
|
||||
"@typescript-eslint/type-utils": "8.46.1",
|
||||
"@typescript-eslint/utils": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1",
|
||||
"@typescript-eslint/scope-manager": "8.46.2",
|
||||
"@typescript-eslint/type-utils": "8.46.2",
|
||||
"@typescript-eslint/utils": "8.46.2",
|
||||
"@typescript-eslint/visitor-keys": "8.46.2",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^7.0.0",
|
||||
"natural-compare": "^1.4.0",
|
||||
@@ -8131,75 +8132,75 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.1.tgz",
|
||||
"integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.2.tgz",
|
||||
"integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1",
|
||||
"@typescript-eslint/scope-manager": "8.46.2",
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"@typescript-eslint/typescript-estree": "8.46.2",
|
||||
"@typescript-eslint/visitor-keys": "8.46.2",
|
||||
"debug": "^4.3.4"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/project-service": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.1.tgz",
|
||||
"integrity": "sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.2.tgz",
|
||||
"integrity": "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/tsconfig-utils": "^8.46.1",
|
||||
"@typescript-eslint/types": "^8.46.1",
|
||||
"@typescript-eslint/tsconfig-utils": "^8.46.2",
|
||||
"@typescript-eslint/types": "^8.46.2",
|
||||
"debug": "^4.3.4"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz",
|
||||
"integrity": "sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz",
|
||||
"integrity": "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1"
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"@typescript-eslint/visitor-keys": "8.46.2"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/tsconfig-utils": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.1.tgz",
|
||||
"integrity": "sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz",
|
||||
"integrity": "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@typescript-eslint/type-utils": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.1.tgz",
|
||||
"integrity": "sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz",
|
||||
"integrity": "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1",
|
||||
"@typescript-eslint/utils": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"@typescript-eslint/typescript-estree": "8.46.2",
|
||||
"@typescript-eslint/utils": "8.46.2",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.1.tgz",
|
||||
"integrity": "sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.2.tgz",
|
||||
"integrity": "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz",
|
||||
"integrity": "sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz",
|
||||
"integrity": "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/project-service": "8.46.1",
|
||||
"@typescript-eslint/tsconfig-utils": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1",
|
||||
"@typescript-eslint/project-service": "8.46.2",
|
||||
"@typescript-eslint/tsconfig-utils": "8.46.2",
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"@typescript-eslint/visitor-keys": "8.46.2",
|
||||
"debug": "^4.3.4",
|
||||
"fast-glob": "^3.3.2",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -8229,24 +8230,24 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/utils": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.1.tgz",
|
||||
"integrity": "sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.2.tgz",
|
||||
"integrity": "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/eslint-utils": "^4.7.0",
|
||||
"@typescript-eslint/scope-manager": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1"
|
||||
"@typescript-eslint/scope-manager": "8.46.2",
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"@typescript-eslint/typescript-estree": "8.46.2"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz",
|
||||
"integrity": "sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz",
|
||||
"integrity": "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.2",
|
||||
"eslint-visitor-keys": "^4.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -8742,24 +8743,23 @@
|
||||
"dev": true
|
||||
},
|
||||
"eslint": {
|
||||
"version": "9.37.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz",
|
||||
"integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==",
|
||||
"version": "9.38.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.38.0.tgz",
|
||||
"integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
"@eslint/config-array": "^0.21.0",
|
||||
"@eslint/config-helpers": "^0.4.0",
|
||||
"@eslint/config-array": "^0.21.1",
|
||||
"@eslint/config-helpers": "^0.4.1",
|
||||
"@eslint/core": "^0.16.0",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "9.37.0",
|
||||
"@eslint/js": "9.38.0",
|
||||
"@eslint/plugin-kit": "^0.4.0",
|
||||
"@humanfs/node": "^0.16.6",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@humanwhocodes/retry": "^0.4.2",
|
||||
"@types/estree": "^1.0.6",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"ajv": "^6.12.4",
|
||||
"chalk": "^4.0.0",
|
||||
"cross-spawn": "^7.0.6",
|
||||
@@ -11259,15 +11259,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"typescript-eslint": {
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.1.tgz",
|
||||
"integrity": "sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==",
|
||||
"version": "8.46.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.2.tgz",
|
||||
"integrity": "sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/eslint-plugin": "8.46.1",
|
||||
"@typescript-eslint/parser": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1",
|
||||
"@typescript-eslint/utils": "8.46.1"
|
||||
"@typescript-eslint/eslint-plugin": "8.46.2",
|
||||
"@typescript-eslint/parser": "8.46.2",
|
||||
"@typescript-eslint/typescript-estree": "8.46.2",
|
||||
"@typescript-eslint/utils": "8.46.2"
|
||||
}
|
||||
},
|
||||
"uglify-js": {
|
||||
@@ -11278,9 +11278,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"undici-types": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz",
|
||||
"integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==",
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||
"dev": true
|
||||
},
|
||||
"unix-dgram": {
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/jsonwebtoken": "^9.0.10",
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/node": "^24.7.2",
|
||||
"@types/node": "^24.9.1",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@types/ws": "^8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.26.0",
|
||||
"@typescript-eslint/parser": "^8.46.1",
|
||||
"eslint": "^9.37.0",
|
||||
"@typescript-eslint/parser": "^8.46.2",
|
||||
"eslint": "^9.38.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-lodash": "^8.0.0",
|
||||
"globals": "^16.4.0",
|
||||
@@ -48,7 +48,7 @@
|
||||
"ts-node": "^10.9.2",
|
||||
"tscw-config": "^1.1.2",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.46.1"
|
||||
"typescript-eslint": "^8.46.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.4",
|
||||
|
||||
@@ -30,6 +30,7 @@ from typing import Any, Optional, TYPE_CHECKING, Union
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from flask import current_app
|
||||
from flask_babel import gettext as __
|
||||
|
||||
from superset.common.chart_data import ChartDataResultFormat
|
||||
@@ -340,7 +341,15 @@ def apply_client_processing( # noqa: C901
|
||||
if query["result_format"] == ChartDataResultFormat.JSON:
|
||||
df = pd.DataFrame.from_dict(data)
|
||||
elif query["result_format"] == ChartDataResultFormat.CSV:
|
||||
df = pd.read_csv(StringIO(data))
|
||||
# Use custom NA values configuration for
|
||||
# reports to avoid unwanted conversions
|
||||
# This allows users to control which values should be treated as null/NA
|
||||
na_values = current_app.config["REPORTS_CSV_NA_NAMES"]
|
||||
df = pd.read_csv(
|
||||
StringIO(data),
|
||||
keep_default_na=na_values is None,
|
||||
na_values=na_values,
|
||||
)
|
||||
|
||||
# convert all columns to verbose (label) name
|
||||
if datasource:
|
||||
|
||||
@@ -1354,6 +1354,15 @@ ALLOWED_USER_CSV_SCHEMA_FUNC = allowed_schemas_for_csv_upload
|
||||
# Values that should be treated as nulls for the csv uploads.
|
||||
CSV_DEFAULT_NA_NAMES = list(STR_NA_VALUES)
|
||||
|
||||
# Values that should be treated as nulls for scheduled reports CSV processing.
|
||||
# If not set or None, defaults to standard pandas NA handling behavior.
|
||||
# Set to a custom list to control which values should be treated as null.
|
||||
# Examples:
|
||||
# REPORTS_CSV_NA_NAMES = None # Use default pandas NA handling (backwards compatible)
|
||||
# REPORTS_CSV_NA_NAMES = [] # Disable all automatic NA conversion
|
||||
# REPORTS_CSV_NA_NAMES = ["", "NULL", "null"] # Only treat these specific values as NA
|
||||
REPORTS_CSV_NA_NAMES: list[str] | None = None
|
||||
|
||||
# Chunk size for reading CSV files during uploads
|
||||
# Smaller values use less memory but may be slower for large files
|
||||
READ_CSV_CHUNK_SIZE = 1000
|
||||
|
||||
@@ -59,6 +59,7 @@ class GuestUser(AnonymousUserMixin):
|
||||
"""
|
||||
|
||||
is_guest_user = True
|
||||
active = True
|
||||
|
||||
@property
|
||||
def is_authenticated(self) -> bool:
|
||||
|
||||
@@ -751,10 +751,10 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "اغسطس"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "هامش عنوان المحور"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "موضع عنوان المحور"
|
||||
|
||||
msgid "About"
|
||||
@@ -13452,7 +13452,7 @@ msgstr "اكتب وصفًا لاستعلامك"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "اكتب قالب المقاود لعرض البيانات"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "هامش عنوان المحور X"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13501,7 +13501,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "حدود Y 2"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "هامش عنوان المحور Y"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -780,10 +780,10 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "AGO"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "MARGE DEL TÍTOL DE L'EIX"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "POSICIÓ DEL TÍTOL DE L'EIX"
|
||||
|
||||
msgid "About"
|
||||
@@ -13231,7 +13231,7 @@ msgstr "Escriu una descripció per la teva consulta"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "Escriu una plantilla handlebars per renderitzar les dades"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "MARGE DEL TÍTOL DE L'EIX X"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13279,7 +13279,7 @@ msgstr "XYZ"
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Límits Y 2"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "MARGE DEL TÍTOL DE L'EIX Y"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -794,10 +794,10 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "AUG"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "ABSTAND DES ACHSENTITELS"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "Y-ACHSE TITEL POSITION"
|
||||
|
||||
msgid "About"
|
||||
@@ -13868,7 +13868,7 @@ msgstr "Beschreibung Ihrer Anfrage"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "Handlebars-Template zur Darstellung der Daten verfassen"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "X AXIS TITLE MARGIN"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13917,7 +13917,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Y 2 Grenzen"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "Y-ACHSE TITEL RAND"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -689,10 +689,10 @@ msgstr ""
|
||||
msgid "AUG"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr ""
|
||||
|
||||
msgid "About"
|
||||
@@ -12368,7 +12368,7 @@ msgstr ""
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr ""
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -12416,7 +12416,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -689,10 +689,10 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "AGO"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "MARGEN DEL TÍTULO DEL EJE"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "POSICIÓN DEL TÍTULO DEL EJE"
|
||||
|
||||
msgid "About"
|
||||
@@ -12368,7 +12368,7 @@ msgstr "Escribe una descripción para tu consulta"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "Elabora una plantilla de Handlebars para renderizar los datos"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "MARGEN DEL TÍTULO DEL EJE X"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -12416,7 +12416,7 @@ msgstr "XYZ"
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Límites de Y 2"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "MARGEN DEL TÍTULO DEL EJE Y"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -767,10 +767,10 @@ msgstr ""
|
||||
msgid "AUG"
|
||||
msgstr "آگوست"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "حاشیه عنوان محور"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "محل عنوان محور"
|
||||
|
||||
msgid "About"
|
||||
@@ -13425,7 +13425,7 @@ msgstr "توضیحی برای کوئری خود بنویسید."
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "یک الگوی هندلبارز برای نمایش دادهها بنویسید."
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "حاشیه عنوان محور ایکس"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13474,7 +13474,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "بازههای Y ۲"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "حاشیه عنوان محور Y"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -852,10 +852,10 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "AUG"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "MARGE DU TITRE DE L'AXE"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "POSITION DU TITRE DE L'AXE"
|
||||
|
||||
msgid "About"
|
||||
@@ -16095,7 +16095,7 @@ msgstr "Écrire une description pour votre requête"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "Écrire un modèle handlebar pour afficher les données"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "MARGE DU TITRE DE L'AXE DES ABCISSES"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -16148,7 +16148,7 @@ msgstr "XYZ"
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Limites ordonnées 2"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "MARGE DU TITRE DE L'AXE DES ORDONNÉES"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -718,11 +718,11 @@ msgstr ""
|
||||
msgid "AUG"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "Testa la Connessione"
|
||||
|
||||
msgid "About"
|
||||
@@ -13284,7 +13284,7 @@ msgstr ""
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr ""
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13336,7 +13336,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -725,10 +725,10 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "8月"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "軸のタイトルの余白"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "軸タイトルの位置"
|
||||
|
||||
msgid "About"
|
||||
@@ -12622,7 +12622,7 @@ msgstr "クエリの説明を書いてください"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "データをレンダリングするハンドルバー テンプレートを作成する"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "X 軸のタイトルマージン"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -12670,7 +12670,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Y 2 バウンド"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "Y 軸のタイトルマージン"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -715,10 +715,10 @@ msgstr ""
|
||||
msgid "AUG"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr ""
|
||||
|
||||
msgid "About"
|
||||
@@ -13159,7 +13159,7 @@ msgstr ""
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr ""
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13209,7 +13209,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -695,10 +695,10 @@ msgstr ""
|
||||
msgid "AUG"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr ""
|
||||
|
||||
msgid "About"
|
||||
@@ -12353,7 +12353,7 @@ msgstr ""
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr ""
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -12401,7 +12401,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -757,10 +757,10 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "AUG"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "AXIS TITEL MARGIN"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "AXIS TITEL POSITIE"
|
||||
|
||||
msgid "About"
|
||||
@@ -13691,7 +13691,7 @@ msgstr "Schrijf een omschrijving voor uw query"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "Schrijf een handlebars sjabloon om de gegevens weer te geven"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "X AXIS TITEL MARGE"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13740,7 +13740,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Y 2 grenzen"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "Y AXIS TITEL MARGE"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -796,11 +796,11 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "SIE"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "MARGINES TYTUŁU OSI"
|
||||
|
||||
#, fuzzy
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "POZYCJA TYTUŁU OSI"
|
||||
|
||||
msgid "About"
|
||||
@@ -14280,7 +14280,7 @@ msgstr "Napisz opis swojego zapytania"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "Napisz szablon handlebars do renderowania danych"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "MARGINES TYTUŁU OSI X"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -14335,7 +14335,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Granice osi Y 2"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "MARGINES TYTUŁU OSI Y"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -726,10 +726,10 @@ msgstr ""
|
||||
msgid "AUG"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr ""
|
||||
|
||||
msgid "About"
|
||||
@@ -13486,7 +13486,7 @@ msgstr "Escreva uma descrição para sua consulta"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr ""
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13537,7 +13537,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -769,10 +769,10 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "AGO"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "MARGEM DO EIXO DO TÍTULO "
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "POSIÇÃO DO EIXO DO TÍTULO"
|
||||
|
||||
msgid "About"
|
||||
@@ -13862,7 +13862,7 @@ msgstr "Escreva uma descrição para sua consulta"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "Escreva um modelo de guidão para renderizar os dados"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "MARGEM DO TÍTULO DO EIXO X"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13912,7 +13912,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Y 2 limites"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "MARGEM DO TÍTULO DO EIXO Y"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -799,10 +799,10 @@ msgstr "Асинхронные запросы"
|
||||
msgid "AUG"
|
||||
msgstr "АВГ"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "Отступ заголовка оси"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "Положение заголовка оси"
|
||||
|
||||
msgid "About"
|
||||
@@ -14035,7 +14035,7 @@ msgstr "Заполните описание к вашему запросу"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "Напишите шаблон Handlebars для отображения данных"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "Отступ заголовка оси X"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -14089,7 +14089,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Границы оси Y 2"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "Отступ заголовка оси Y"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -693,10 +693,10 @@ msgstr ""
|
||||
msgid "AUG"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr ""
|
||||
|
||||
msgid "About"
|
||||
@@ -12502,7 +12502,7 @@ msgstr ""
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr ""
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -12550,7 +12550,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -787,10 +787,10 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "AVG"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "OBROBA OZNAKE OSI"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "POLOŽAJ OZNAKE OSI"
|
||||
|
||||
msgid "About"
|
||||
@@ -13457,7 +13457,7 @@ msgstr "Dodajte opis vaše poizvedbe"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "Napišite Handlebars-predlogo za prikaz podatkov"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "OBROBA NASLOVA X-OSI"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13506,7 +13506,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Meje Y-osi 2"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "OBROBA NASLOVA Y-OSI"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -691,10 +691,10 @@ msgstr ""
|
||||
msgid "AUG"
|
||||
msgstr "AĞU"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr ""
|
||||
|
||||
msgid "About"
|
||||
@@ -12543,7 +12543,7 @@ msgstr ""
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr ""
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -12591,7 +12591,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -759,10 +759,10 @@ msgstr "AQE"
|
||||
msgid "AUG"
|
||||
msgstr "Серпень"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "ЗАВДАННЯ ВІСІВ"
|
||||
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "Позиція заголовка вісь"
|
||||
|
||||
msgid "About"
|
||||
@@ -13662,7 +13662,7 @@ msgstr "Напишіть опис свого запиту"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr "Напишіть шаблон ручки для надання даних"
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr ""
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13712,7 +13712,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Y 2 межі"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "Y Exis title Margin"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -730,11 +730,11 @@ msgstr "异步执行查询"
|
||||
msgid "AUG"
|
||||
msgstr "八月"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "轴标题边距"
|
||||
|
||||
#, fuzzy
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "轴标题的位置"
|
||||
|
||||
msgid "About"
|
||||
@@ -13364,7 +13364,7 @@ msgstr "为您的查询写一段描述"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr ""
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "X 轴标题边距"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13416,7 +13416,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Y 界限"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "Y 轴标题边距"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -729,11 +729,11 @@ msgstr "異步執行查詢"
|
||||
msgid "AUG"
|
||||
msgstr "八月"
|
||||
|
||||
msgid "AXIS TITLE MARGIN"
|
||||
msgid "Axis title margin"
|
||||
msgstr "軸標題邊距"
|
||||
|
||||
#, fuzzy
|
||||
msgid "AXIS TITLE POSITION"
|
||||
msgid "Axis title position"
|
||||
msgstr "軸標題的位置"
|
||||
|
||||
msgid "About"
|
||||
@@ -13378,7 +13378,7 @@ msgstr "為您的查詢寫一段描述"
|
||||
msgid "Write a handlebars template to render the data"
|
||||
msgstr ""
|
||||
|
||||
msgid "X AXIS TITLE MARGIN"
|
||||
msgid "X axis title margin"
|
||||
msgstr "X 軸標題邊距"
|
||||
|
||||
msgid "X Axis"
|
||||
@@ -13430,7 +13430,7 @@ msgstr ""
|
||||
msgid "Y 2 bounds"
|
||||
msgstr "Y 界限"
|
||||
|
||||
msgid "Y AXIS TITLE MARGIN"
|
||||
msgid "Y axis title margin"
|
||||
msgstr "Y 軸標題邊距"
|
||||
|
||||
msgid "Y Axis"
|
||||
|
||||
@@ -120,15 +120,26 @@ def take_tiled_screenshot(
|
||||
dashboard_top,
|
||||
)
|
||||
|
||||
# Calculate number of tiles needed
|
||||
num_tiles = max(1, (dashboard_height + viewport_height - 1) // viewport_height)
|
||||
# Get actual viewport height to ensure we don't skip content
|
||||
actual_viewport_height = page.viewport_size["height"]
|
||||
tile_height = min(viewport_height, actual_viewport_height)
|
||||
|
||||
logger.info(
|
||||
"Viewport: configured=%s, actual=%s, using tile_height=%s",
|
||||
viewport_height,
|
||||
actual_viewport_height,
|
||||
tile_height,
|
||||
)
|
||||
|
||||
# Calculate number of tiles needed based on actual tile height
|
||||
num_tiles = max(1, (dashboard_height + tile_height - 1) // tile_height)
|
||||
logger.info("Taking %s screenshot tiles", num_tiles)
|
||||
|
||||
screenshot_tiles = []
|
||||
|
||||
for i in range(num_tiles):
|
||||
# Calculate scroll position to show this tile's content
|
||||
scroll_y = dashboard_top + (i * viewport_height)
|
||||
scroll_y = dashboard_top + (i * tile_height)
|
||||
|
||||
# Scroll the window to the desired position
|
||||
page.evaluate(f"window.scrollTo(0, {scroll_y})")
|
||||
@@ -139,29 +150,65 @@ def take_tiled_screenshot(
|
||||
# Wait for scroll to settle and content to load
|
||||
page.wait_for_timeout(2000) # 2 second wait per tile
|
||||
|
||||
# Get the current element position after scroll
|
||||
current_element_box = page.evaluate(f"""() => {{
|
||||
# Get the current element position after scroll and viewport size
|
||||
viewport_info = page.evaluate(f"""() => {{
|
||||
const el = document.querySelector(".{element_name}");
|
||||
const rect = el.getBoundingClientRect();
|
||||
return {{
|
||||
x: rect.left,
|
||||
y: rect.top,
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
elementX: rect.left,
|
||||
elementY: rect.top,
|
||||
elementWidth: rect.width,
|
||||
elementHeight: rect.height,
|
||||
viewportWidth: window.innerWidth,
|
||||
viewportHeight: window.innerHeight
|
||||
}};
|
||||
}}""")
|
||||
|
||||
# Calculate what portion of the element we want to capture for this tile
|
||||
tile_start_in_element = i * viewport_height
|
||||
remaining_content = dashboard_height - tile_start_in_element
|
||||
tile_content_height = min(viewport_height, remaining_content)
|
||||
# Ensure clip coordinates are within viewport bounds
|
||||
# If element.top is negative, it's scrolled above viewport - start from y=0
|
||||
clip_y = max(0, viewport_info["elementY"])
|
||||
# If element.left is negative, start from x=0
|
||||
clip_x = max(0, viewport_info["elementX"])
|
||||
|
||||
# Calculate clip dimensions - capture what's visible of the element
|
||||
# Handle elements scrolled above viewport: if elementY is negative,
|
||||
# only the portion from (elementY + elementHeight) is visible
|
||||
if viewport_info["elementY"] < 0:
|
||||
# Element extends from above viewport - calculate visible portion
|
||||
visible_height = (
|
||||
viewport_info["elementY"] + viewport_info["elementHeight"]
|
||||
)
|
||||
clip_height = min(visible_height, viewport_info["viewportHeight"])
|
||||
else:
|
||||
# Element is within viewport
|
||||
clip_height = min(
|
||||
viewport_info["elementHeight"],
|
||||
viewport_info["viewportHeight"] - clip_y,
|
||||
)
|
||||
|
||||
clip_width = min(
|
||||
viewport_info["elementWidth"], viewport_info["viewportWidth"] - clip_x
|
||||
)
|
||||
|
||||
# Validate clip region before taking screenshot
|
||||
if clip_width <= 0 or clip_height <= 0:
|
||||
logger.warning(
|
||||
"Skipping tile %s/%s - invalid clip dimensions: %sx%s at (%s, %s)",
|
||||
i + 1,
|
||||
num_tiles,
|
||||
clip_width,
|
||||
clip_height,
|
||||
clip_x,
|
||||
clip_y,
|
||||
)
|
||||
continue
|
||||
|
||||
# Clip to capture only the current tile portion of the element
|
||||
clip = {
|
||||
"x": current_element_box["x"],
|
||||
"y": current_element_box["y"],
|
||||
"width": current_element_box["width"],
|
||||
"height": min(tile_content_height, current_element_box["height"]),
|
||||
"x": clip_x,
|
||||
"y": clip_y,
|
||||
"width": clip_width,
|
||||
"height": clip_height,
|
||||
}
|
||||
|
||||
# Take screenshot with clipping to capture only this tile's content
|
||||
|
||||
@@ -216,6 +216,13 @@ class WebDriverPlaywright(WebDriverProxy):
|
||||
|
||||
return error_messages
|
||||
|
||||
@staticmethod
|
||||
def _get_screenshot(page: Page, element: Locator, element_name: str) -> bytes:
|
||||
if element_name == "standalone":
|
||||
return page.screenshot(full_page=True)
|
||||
else:
|
||||
return element.screenshot()
|
||||
|
||||
def get_screenshot( # pylint: disable=too-many-locals, too-many-statements # noqa: C901
|
||||
self, url: str, element_name: str, user: User
|
||||
) -> bytes | None:
|
||||
@@ -363,11 +370,18 @@ class WebDriverPlaywright(WebDriverProxy):
|
||||
"falling back to standard screenshot"
|
||||
)
|
||||
)
|
||||
img = element.screenshot()
|
||||
img = WebDriverPlaywright._get_screenshot(
|
||||
page, element, element_name
|
||||
)
|
||||
else:
|
||||
img = element.screenshot()
|
||||
img = WebDriverPlaywright._get_screenshot(
|
||||
page, element, element_name
|
||||
)
|
||||
else:
|
||||
img = element.screenshot()
|
||||
img = WebDriverPlaywright._get_screenshot(
|
||||
page, element, element_name
|
||||
)
|
||||
|
||||
except PlaywrightTimeout:
|
||||
# raise again for the finally block, but handled above
|
||||
pass
|
||||
|
||||
+13
-4
@@ -46,7 +46,6 @@ from sqlalchemy.exc import SQLAlchemyError
|
||||
from werkzeug.utils import safe_join
|
||||
|
||||
from superset import (
|
||||
appbuilder,
|
||||
db,
|
||||
event_logger,
|
||||
is_feature_enabled,
|
||||
@@ -80,6 +79,7 @@ from superset.models.slice import Slice
|
||||
from superset.models.sql_lab import Query
|
||||
from superset.models.user_attributes import UserAttribute
|
||||
from superset.superset_typing import FlaskResponse
|
||||
from superset.tasks.utils import get_current_user
|
||||
from superset.utils import core as utils, json
|
||||
from superset.utils.cache import etag_cache
|
||||
from superset.utils.core import (
|
||||
@@ -108,6 +108,7 @@ from superset.views.utils import (
|
||||
get_form_data,
|
||||
get_viz,
|
||||
loads_request_json,
|
||||
redirect_to_login,
|
||||
sanitize_datasource_data,
|
||||
)
|
||||
from superset.viz import BaseViz
|
||||
@@ -765,13 +766,21 @@ class Superset(BaseSupersetView):
|
||||
dashboard = Dashboard.get(dashboard_id_or_slug)
|
||||
|
||||
if not dashboard:
|
||||
if not get_current_user():
|
||||
return redirect_to_login()
|
||||
abort(404)
|
||||
|
||||
# Redirect anonymous users to login for unpublished dashboards,
|
||||
# in the edge case where a dataset has been shared with public
|
||||
if not get_current_user() and not dashboard.published:
|
||||
return redirect_to_login()
|
||||
|
||||
try:
|
||||
dashboard.raise_for_access()
|
||||
except SupersetSecurityException:
|
||||
# Return 404 to avoid revealing dashboard existence
|
||||
return Response(status=404)
|
||||
if not get_current_user():
|
||||
return redirect_to_login()
|
||||
abort(404)
|
||||
add_extra_log_payload(
|
||||
dashboard_id=dashboard.id,
|
||||
dashboard_version="v2",
|
||||
@@ -882,7 +891,7 @@ class Superset(BaseSupersetView):
|
||||
def welcome(self) -> FlaskResponse:
|
||||
"""Personalized welcome page"""
|
||||
if not g.user or not get_user_id():
|
||||
return redirect(appbuilder.get_url_for_login)
|
||||
return redirect_to_login()
|
||||
|
||||
if welcome_dashboard_id := (
|
||||
db.session.query(UserAttribute.welcome_dashboard_id)
|
||||
|
||||
@@ -25,7 +25,6 @@ from typing import Any, Callable, cast
|
||||
|
||||
from flask import (
|
||||
Flask,
|
||||
redirect,
|
||||
request,
|
||||
Response,
|
||||
send_file,
|
||||
@@ -34,7 +33,6 @@ from flask_wtf.csrf import CSRFError
|
||||
from sqlalchemy import exc
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
from superset import appbuilder
|
||||
from superset.commands.exceptions import CommandException, CommandInvalidError
|
||||
from superset.errors import ErrorLevel, SupersetError, SupersetErrorType
|
||||
from superset.exceptions import (
|
||||
@@ -46,6 +44,7 @@ from superset.exceptions import (
|
||||
from superset.superset_typing import FlaskResponse
|
||||
from superset.utils import core as utils, json
|
||||
from superset.utils.log import get_logger_from_status
|
||||
from superset.views.utils import redirect_to_login
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from superset.views.base import BaseSupersetView
|
||||
@@ -153,7 +152,7 @@ def set_app_error_handlers(app: Flask) -> None: # noqa: C901
|
||||
if request.is_json:
|
||||
return show_http_exception(ex)
|
||||
|
||||
return redirect(appbuilder.get_url_for_login)
|
||||
return redirect_to_login()
|
||||
|
||||
@app.errorhandler(HTTPException)
|
||||
def show_http_exception(ex: HTTPException) -> FlaskResponse:
|
||||
@@ -165,7 +164,11 @@ def set_app_error_handlers(app: Flask) -> None: # noqa: C901
|
||||
and ex.code in {404, 500}
|
||||
):
|
||||
path = files("superset") / f"static/assets/{ex.code}.html"
|
||||
return send_file(path, max_age=0), ex.code
|
||||
# Try to serve HTML file; fall back to JSON if not built
|
||||
try:
|
||||
return send_file(path, max_age=0), ex.code
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
return json_error_response(
|
||||
[
|
||||
@@ -189,7 +192,11 @@ def set_app_error_handlers(app: Flask) -> None: # noqa: C901
|
||||
|
||||
if "text/html" in request.accept_mimetypes and not app.config["DEBUG"]:
|
||||
path = files("superset") / "static/assets/500.html"
|
||||
return send_file(path, max_age=0), 500
|
||||
# Try to serve HTML file; fall back to JSON if not built
|
||||
try:
|
||||
return send_file(path, max_age=0), 500
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
extra = ex.normalized_messages() if isinstance(ex, CommandInvalidError) else {}
|
||||
return json_error_response(
|
||||
|
||||
+31
-3
@@ -19,16 +19,17 @@ import logging
|
||||
from collections import defaultdict
|
||||
from functools import wraps
|
||||
from typing import Any, Callable, DefaultDict, Optional, Union
|
||||
from urllib import parse
|
||||
|
||||
import msgpack
|
||||
import pyarrow as pa
|
||||
from flask import current_app as app, g, has_request_context, request
|
||||
from flask import current_app as app, g, has_request_context, redirect, request
|
||||
from flask_appbuilder.security.sqla import models as ab_models
|
||||
from flask_appbuilder.security.sqla.models import User
|
||||
from flask_babel import _
|
||||
from sqlalchemy.exc import NoResultFound
|
||||
|
||||
from superset import dataframe, db, result_set, viz
|
||||
from superset import appbuilder, dataframe, db, result_set, viz
|
||||
from superset.common.db_query_status import QueryStatus
|
||||
from superset.daos.datasource import DatasourceDAO
|
||||
from superset.errors import ErrorLevel, SupersetError, SupersetErrorType
|
||||
@@ -44,7 +45,7 @@ from superset.models.core import Database
|
||||
from superset.models.dashboard import Dashboard
|
||||
from superset.models.slice import Slice
|
||||
from superset.models.sql_lab import Query
|
||||
from superset.superset_typing import FormData
|
||||
from superset.superset_typing import FlaskResponse, FormData
|
||||
from superset.utils import json
|
||||
from superset.utils.core import DatasourceType
|
||||
from superset.utils.decorators import stats_timing
|
||||
@@ -58,6 +59,33 @@ if not feature_flag_manager.is_feature_enabled("ENABLE_JAVASCRIPT_CONTROLS"):
|
||||
REJECTED_FORM_DATA_KEYS = ["js_tooltip", "js_onclick_href", "js_data_mutator"]
|
||||
|
||||
|
||||
def redirect_to_login(next_target: str | None = None) -> FlaskResponse:
|
||||
"""Return a redirect response to the login view, preserving target URL.
|
||||
|
||||
When ``next_target`` is ``None`` the current request path (including query
|
||||
string) is used, provided a request context is available. The resulting URL
|
||||
always remains relative, mirroring Flask-AppBuilder expectations.
|
||||
"""
|
||||
|
||||
login_url = appbuilder.get_url_for_login
|
||||
parsed = parse.urlparse(login_url)
|
||||
query = parse.parse_qs(parsed.query, keep_blank_values=True)
|
||||
|
||||
target = next_target
|
||||
if target is None and has_request_context():
|
||||
if request.query_string:
|
||||
target = request.full_path.rstrip("?")
|
||||
else:
|
||||
target = request.path
|
||||
|
||||
if target:
|
||||
query["next"] = [target]
|
||||
|
||||
encoded_query = parse.urlencode(query, doseq=True)
|
||||
redirect_url = parse.urlunparse(parsed._replace(query=encoded_query))
|
||||
return redirect(redirect_url)
|
||||
|
||||
|
||||
def sanitize_datasource_data(datasource_data: dict[str, Any]) -> dict[str, Any]:
|
||||
if datasource_data:
|
||||
datasource_database = datasource_data.get("database")
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
"""Unit tests for Superset"""
|
||||
|
||||
import re
|
||||
import unittest
|
||||
from random import random
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
||||
import pytest
|
||||
from flask import Response, escape, url_for
|
||||
@@ -52,7 +52,7 @@ from tests.integration_tests.fixtures.world_bank_dashboard import (
|
||||
load_world_bank_data, # noqa: F401
|
||||
)
|
||||
|
||||
from .base_tests import SupersetTestCase
|
||||
from .base_tests import DEFAULT_PASSWORD, SupersetTestCase
|
||||
|
||||
|
||||
class TestDashboard(SupersetTestCase):
|
||||
@@ -186,6 +186,72 @@ class TestDashboard(SupersetTestCase):
|
||||
# Cleanup
|
||||
self.revoke_public_access_to_table(table)
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"load_energy_table_with_slice",
|
||||
"load_dashboard",
|
||||
)
|
||||
def test_anonymous_user_redirects_to_login_with_next(self):
|
||||
self.logout()
|
||||
target_path = f"/superset/dashboard/{pytest.hidden_dash_slug}/"
|
||||
|
||||
response = self.client.get(target_path, follow_redirects=False)
|
||||
|
||||
assert response.status_code == 302
|
||||
|
||||
redirect_location = response.headers["Location"]
|
||||
parsed = urlparse(redirect_location)
|
||||
assert parsed.path.rstrip("/") == "/login"
|
||||
|
||||
next_values = parse_qs(parsed.query).get("next")
|
||||
assert next_values is not None
|
||||
assert next_values[0].endswith(target_path)
|
||||
|
||||
login_target = (
|
||||
f"{parsed.path}{'?' + parsed.query if parsed.query else ''}"
|
||||
if parsed.scheme or parsed.netloc
|
||||
else redirect_location
|
||||
)
|
||||
|
||||
login_response = self.client.post(
|
||||
login_target,
|
||||
data={"username": ADMIN_USERNAME, "password": DEFAULT_PASSWORD},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert login_response.status_code == 302
|
||||
assert login_response.headers["Location"].endswith(target_path)
|
||||
|
||||
target_response: Response = self.client.get(target_path, follow_redirects=False)
|
||||
assert target_response.status_code == 200
|
||||
|
||||
def test_anonymous_user_redirects_to_login_for_missing_dashboard(self):
|
||||
self.logout()
|
||||
target_path = "/superset/dashboard/nonexistent-dashboard/"
|
||||
|
||||
response = self.client.get(target_path, follow_redirects=False)
|
||||
|
||||
assert response.status_code == 302
|
||||
parsed = urlparse(response.headers["Location"])
|
||||
assert parsed.path.rstrip("/") == "/login"
|
||||
next_values = parse_qs(parsed.query).get("next")
|
||||
assert next_values is not None
|
||||
assert next_values[0].endswith(target_path)
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"public_role_like_gamma",
|
||||
"load_energy_table_with_slice",
|
||||
"load_dashboard",
|
||||
)
|
||||
def test_authenticated_user_without_access_gets_404(self):
|
||||
self.login(GAMMA_USERNAME)
|
||||
target_path = f"/superset/dashboard/{pytest.hidden_dash_slug}/"
|
||||
|
||||
response = self.client.get(
|
||||
target_path,
|
||||
follow_redirects=False,
|
||||
headers={"Accept": "text/html"},
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"public_role_like_gamma",
|
||||
"load_energy_table_with_slice",
|
||||
@@ -248,7 +314,3 @@ class TestDashboard(SupersetTestCase):
|
||||
db.session.commit()
|
||||
|
||||
assert f"/superset/dashboard/{slug}/" not in resp
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -108,7 +108,7 @@ class TestDashboardRoleBasedSecurity(BaseTestDashboardSecurity):
|
||||
|
||||
# act
|
||||
response = self.get_dashboard_view_response(dashboard_to_access)
|
||||
assert response.status_code == 404
|
||||
assert response.status_code == 404 # Authenticated users without access get 404
|
||||
|
||||
request_payload = get_query_context("birth_names")
|
||||
rv = self.post_assert_metric(CHART_DATA_URI, request_payload, "data")
|
||||
@@ -221,7 +221,8 @@ class TestDashboardRoleBasedSecurity(BaseTestDashboardSecurity):
|
||||
response = self.get_dashboard_view_response(dashboard_to_access)
|
||||
|
||||
# assert
|
||||
assert response.status_code == 404
|
||||
# Anonymous users are redirected to login instead of getting 404
|
||||
assert response.status_code == 302
|
||||
|
||||
@pytest.mark.usefixtures("public_role_like_gamma")
|
||||
def test_get_dashboard_view__public_user_with_dashboard_permission_can_not_access_draft( # noqa: E501
|
||||
@@ -234,7 +235,8 @@ class TestDashboardRoleBasedSecurity(BaseTestDashboardSecurity):
|
||||
response = self.get_dashboard_view_response(dashboard_to_access)
|
||||
|
||||
# assert
|
||||
assert response.status_code == 404
|
||||
# Anonymous users are redirected to login for unpublished dashboards
|
||||
assert response.status_code == 302
|
||||
|
||||
# post
|
||||
revoke_access_to_dashboard(dashboard_to_access, "Public") # noqa: F405
|
||||
|
||||
@@ -190,6 +190,8 @@ def delete_all_inserted_objects() -> None:
|
||||
|
||||
def delete_all_inserted_dashboards():
|
||||
try:
|
||||
# Expire all objects to ensure fresh state after potential rollbacks
|
||||
db.session.expire_all()
|
||||
dashboards_to_delete: list[Dashboard] = (
|
||||
db.session.query(Dashboard)
|
||||
.filter(Dashboard.id.in_(inserted_dashboards_ids))
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# under the License.
|
||||
|
||||
from random import randint
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from flask_appbuilder.security.sqla.models import User
|
||||
@@ -25,7 +25,7 @@ from freezegun.api import FakeDatetime
|
||||
|
||||
from superset.extensions import db
|
||||
from superset.reports.models import ReportScheduleType
|
||||
from superset.tasks.scheduler import execute, scheduler
|
||||
from superset.tasks.scheduler import execute, log_task_failure, scheduler
|
||||
from tests.integration_tests.reports.utils import insert_report_schedule
|
||||
from tests.integration_tests.test_app import app
|
||||
|
||||
@@ -201,3 +201,48 @@ def test_execute_task_with_command_exception(
|
||||
|
||||
db.session.delete(report_schedule)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
@patch("superset.tasks.scheduler.logger")
|
||||
def test_log_task_failure_with_sender(logger_mock):
|
||||
"""
|
||||
Test that log_task_failure logs correctly when sender is provided
|
||||
"""
|
||||
mock_task = MagicMock()
|
||||
mock_task.name = "test.task.name"
|
||||
mock_exception = Exception("Test error")
|
||||
mock_einfo = MagicMock()
|
||||
|
||||
log_task_failure(
|
||||
sender=mock_task,
|
||||
task_id="test-task-id",
|
||||
exception=mock_exception,
|
||||
einfo=mock_einfo,
|
||||
)
|
||||
|
||||
logger_mock.exception.assert_called_once_with(
|
||||
"Celery task %s failed: %s",
|
||||
"test.task.name",
|
||||
mock_exception,
|
||||
exc_info=mock_einfo,
|
||||
)
|
||||
|
||||
|
||||
@patch("superset.tasks.scheduler.logger")
|
||||
def test_log_task_failure_without_sender(logger_mock):
|
||||
"""
|
||||
Test that log_task_failure logs correctly when sender is None
|
||||
"""
|
||||
mock_exception = Exception("Test error")
|
||||
mock_einfo = MagicMock()
|
||||
|
||||
log_task_failure(
|
||||
sender=None,
|
||||
task_id="test-task-id",
|
||||
exception=mock_exception,
|
||||
einfo=mock_einfo,
|
||||
)
|
||||
|
||||
logger_mock.exception.assert_called_once_with(
|
||||
"Celery task %s failed: %s", "Unknown", mock_exception, exc_info=mock_einfo
|
||||
)
|
||||
|
||||
@@ -24,6 +24,7 @@ from sqlalchemy.orm.session import Session
|
||||
from superset.charts.client_processing import apply_client_processing, pivot_df, table
|
||||
from superset.common.chart_data import ChartDataResultFormat
|
||||
from superset.utils.core import GenericDataType
|
||||
from tests.conftest import with_config
|
||||
|
||||
|
||||
def test_pivot_df_no_cols_no_rows_single_metric():
|
||||
@@ -2653,3 +2654,137 @@ def test_pivot_multi_level_index():
|
||||
| ('Total (Sum)', '', '') | 210 | 105 | 0 |
|
||||
""".strip()
|
||||
)
|
||||
|
||||
|
||||
@with_config({"REPORTS_CSV_NA_NAMES": []})
|
||||
def test_apply_client_processing_csv_format_preserves_na_strings():
|
||||
"""
|
||||
Test that apply_client_processing preserves "NA" when REPORTS_CSV_NA_NAMES is [].
|
||||
|
||||
This ensures that scheduled reports can be configured to
|
||||
preserve strings like "NA" as literal values.
|
||||
"""
|
||||
|
||||
# CSV data with "NA" string that should be preserved
|
||||
csv_data = "first_name,last_name\nJeff,Smith\nAlice,NA"
|
||||
|
||||
result = {
|
||||
"queries": [
|
||||
{
|
||||
"result_format": ChartDataResultFormat.CSV,
|
||||
"data": csv_data,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
form_data = {
|
||||
"datasource": "1__table",
|
||||
"viz_type": "table",
|
||||
"slice_id": 1,
|
||||
"url_params": {},
|
||||
"metrics": [],
|
||||
"groupby": [],
|
||||
"columns": ["first_name", "last_name"],
|
||||
"extra_form_data": {},
|
||||
"force": False,
|
||||
"result_format": "csv",
|
||||
"result_type": "results",
|
||||
}
|
||||
|
||||
# Test with REPORTS_CSV_NA_NAMES set to empty list (disable NA conversion)
|
||||
|
||||
processed_result = apply_client_processing(result, form_data)
|
||||
|
||||
# Verify the CSV data still contains "NA" as string, not converted to null
|
||||
output_data = processed_result["queries"][0]["data"]
|
||||
assert "NA" in output_data
|
||||
# The "NA" should be preserved in the output CSV
|
||||
lines = output_data.strip().split("\n")
|
||||
assert "Alice,NA" in lines[2] # Second data row should preserve "NA"
|
||||
|
||||
|
||||
@with_config({"REPORTS_CSV_NA_NAMES": ["MISSING"]})
|
||||
def test_apply_client_processing_csv_format_custom_na_values():
|
||||
"""
|
||||
Test that apply_client_processing respects custom NA values configuration.
|
||||
"""
|
||||
|
||||
csv_data = "name,status\nJeff,MISSING\nAlice,OK"
|
||||
|
||||
result = {
|
||||
"queries": [
|
||||
{
|
||||
"result_format": ChartDataResultFormat.CSV,
|
||||
"data": csv_data,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
form_data = {
|
||||
"datasource": "1__table",
|
||||
"viz_type": "table",
|
||||
"slice_id": 1,
|
||||
"url_params": {},
|
||||
"metrics": [],
|
||||
"groupby": [],
|
||||
"columns": ["name", "status"],
|
||||
"extra_form_data": {},
|
||||
"force": False,
|
||||
"result_format": "csv",
|
||||
"result_type": "results",
|
||||
}
|
||||
|
||||
# Test with custom NA values - only "MISSING" should be treated as NA
|
||||
processed_result = apply_client_processing(result, form_data)
|
||||
|
||||
output_data = processed_result["queries"][0]["data"]
|
||||
lines = output_data.strip().split("\n")
|
||||
assert len(lines) >= 3 # header + 2 data rows
|
||||
assert "Jeff," in lines[1] # First data row should have empty status after "Jeff,"
|
||||
assert "Alice,OK" in lines[2] # Second data row should preserve "OK"
|
||||
|
||||
|
||||
@with_config({"REPORTS_CSV_NA_NAMES": []})
|
||||
def test_apply_client_processing_csv_format_default_na_behavior():
|
||||
"""
|
||||
Test that apply_client_processing uses default pandas NA behavior
|
||||
when REPORTS_CSV_NA_NAMES is not configured.
|
||||
This ensures backwards compatibility.
|
||||
"""
|
||||
|
||||
# CSV data with "NA" string that should be converted to null in default behavior
|
||||
csv_data = "first_name,last_name\nJeff,Smith\nAlice,NA"
|
||||
|
||||
result = {
|
||||
"queries": [
|
||||
{
|
||||
"result_format": ChartDataResultFormat.CSV,
|
||||
"data": csv_data,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
form_data = {
|
||||
"datasource": "1__table",
|
||||
"viz_type": "table",
|
||||
"slice_id": 1,
|
||||
"url_params": {},
|
||||
"metrics": [],
|
||||
"groupby": [],
|
||||
"columns": ["first_name", "last_name"],
|
||||
"extra_form_data": {},
|
||||
"force": False,
|
||||
"result_format": "csv",
|
||||
"result_type": "results",
|
||||
}
|
||||
|
||||
processed_result = apply_client_processing(result, form_data)
|
||||
|
||||
# Verify the CSV data has "NA" converted to empty (default pandas behavior)
|
||||
output_data = processed_result["queries"][0]["data"]
|
||||
lines = output_data.strip().split("\n")
|
||||
assert len(lines) >= 3 # header + 2 data rows
|
||||
# The "NA" should be converted to empty by default pandas behavior
|
||||
assert (
|
||||
"Alice," in lines[2]
|
||||
) # Second data row should have empty last_name (NA converted to null)
|
||||
|
||||
@@ -127,6 +127,21 @@ def fake_get_chart_csv_data_hierarchical(chart_url, auth_cookies=None):
|
||||
return json.dumps(fake_result).encode("utf-8")
|
||||
|
||||
|
||||
def fake_get_chart_csv_data_with_na_values(chart_url, auth_cookies=None):
|
||||
# Return JSON with data containing "NA" string value that will be treated as null
|
||||
fake_result = {
|
||||
"result": [
|
||||
{
|
||||
"data": {"first_name": ["Jeff", "Alice"], "last_name": ["Smith", "NA"]},
|
||||
"coltypes": [GenericDataType.STRING, GenericDataType.STRING],
|
||||
"colnames": ["first_name", "last_name"],
|
||||
"indexnames": ["idx1", "idx2"],
|
||||
}
|
||||
]
|
||||
}
|
||||
return json.dumps(fake_result).encode("utf-8")
|
||||
|
||||
|
||||
def test_df_to_escaped_csv():
|
||||
df = pd.DataFrame(
|
||||
data={
|
||||
@@ -263,3 +278,42 @@ def test_get_chart_dataframe_with_hierarchical_columns(monkeypatch: pytest.Monke
|
||||
| ('idx',) | 2 |
|
||||
"""
|
||||
assert markdown_str.strip() == expected_markdown_str.strip()
|
||||
|
||||
|
||||
def test_get_chart_dataframe_preserves_na_string_values(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
):
|
||||
"""
|
||||
Test that get_chart_dataframe currently preserves rows containing "NA"
|
||||
string values.
|
||||
This test verifies the existing behavior before implementing custom NA handling.
|
||||
"""
|
||||
monkeypatch.setattr(
|
||||
csv, "get_chart_csv_data", fake_get_chart_csv_data_with_na_values
|
||||
)
|
||||
df = get_chart_dataframe("http://dummy-url")
|
||||
assert df is not None
|
||||
|
||||
# Verify the DataFrame structure
|
||||
expected_columns = pd.MultiIndex.from_tuples([("first_name",), ("last_name",)])
|
||||
pd.testing.assert_index_equal(df.columns, expected_columns)
|
||||
|
||||
expected_index = pd.MultiIndex.from_tuples([("idx1",), ("idx2",)])
|
||||
pd.testing.assert_index_equal(df.index, expected_index)
|
||||
|
||||
# Check that we have both rows initially
|
||||
assert len(df) == 2
|
||||
|
||||
# Verify the data contains the "NA" string value (not converted to NaN)
|
||||
pd.testing.assert_series_equal(
|
||||
df[("first_name",)],
|
||||
pd.Series(["Jeff", "Alice"], name=("first_name",), index=df.index),
|
||||
)
|
||||
pd.testing.assert_series_equal(
|
||||
df[("last_name",)],
|
||||
pd.Series(["Smith", "NA"], name=("last_name",), index=df.index),
|
||||
)
|
||||
|
||||
last_name_values = df[("last_name",)].values
|
||||
assert last_name_values[0] == "Smith"
|
||||
assert last_name_values[1] == "NA"
|
||||
|
||||
@@ -110,24 +110,42 @@ class TestTakeTiledScreenshot:
|
||||
"""Create a mock Playwright page object."""
|
||||
page = MagicMock()
|
||||
|
||||
# Mock viewport size
|
||||
page.viewport_size = {"width": 1024, "height": 768}
|
||||
|
||||
# Mock element locator
|
||||
element = MagicMock()
|
||||
page.locator.return_value = element
|
||||
|
||||
# Mock element info - simulating a 5000px tall dashboard
|
||||
element_info = {"height": 5000, "top": 100, "left": 50, "width": 800}
|
||||
element_box = {"x": 50, "y": 200, "width": 800, "height": 600}
|
||||
viewport_info = {
|
||||
"elementX": 50,
|
||||
"elementY": 200,
|
||||
"elementWidth": 800,
|
||||
"elementHeight": 600,
|
||||
"viewportWidth": 1024,
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
# For 3 tiles (5000px / 2000px = 2.5, rounded up to 3):
|
||||
# 1 initial call + 3 scroll + 3 element box + 1 reset scroll = 8 calls
|
||||
# For 7 tiles (5000px / 768px actual viewport = 6.5, rounded up to 7):
|
||||
# 1 initial call + 7 scroll + 7 viewport info + 1 reset scroll = 16 calls
|
||||
page.evaluate.side_effect = [
|
||||
element_info, # Initial call for dashboard dimensions
|
||||
None, # First scroll call
|
||||
element_box, # First element box call
|
||||
None, # Second scroll call
|
||||
element_box, # Second element box call
|
||||
None, # Third scroll call
|
||||
element_box, # Third element box call
|
||||
None,
|
||||
viewport_info, # Tile 1
|
||||
None,
|
||||
viewport_info, # Tile 2
|
||||
None,
|
||||
viewport_info, # Tile 3
|
||||
None,
|
||||
viewport_info, # Tile 4
|
||||
None,
|
||||
viewport_info, # Tile 5
|
||||
None,
|
||||
viewport_info, # Tile 6
|
||||
None,
|
||||
viewport_info, # Tile 7
|
||||
None, # Final reset scroll call
|
||||
]
|
||||
|
||||
@@ -150,8 +168,8 @@ class TestTakeTiledScreenshot:
|
||||
assert result == b"combined_screenshot"
|
||||
|
||||
# Should have called screenshot method multiple times
|
||||
# (3 tiles for 5000px height)
|
||||
assert mock_page.screenshot.call_count == 3
|
||||
# (7 tiles for 5000px height with 768px actual viewport)
|
||||
assert mock_page.screenshot.call_count == 7
|
||||
|
||||
# Should have called combine function
|
||||
mock_combine.assert_called_once()
|
||||
@@ -171,16 +189,23 @@ class TestTakeTiledScreenshot:
|
||||
"""Test that tiles are calculated correctly."""
|
||||
# Mock dashboard height of 3500px with viewport of 2000px
|
||||
element_info = {"height": 3500, "top": 100, "left": 50, "width": 800}
|
||||
element_box = {"x": 50, "y": 200, "width": 800, "height": 600}
|
||||
viewport_info = {
|
||||
"elementX": 50,
|
||||
"elementY": 200,
|
||||
"elementWidth": 800,
|
||||
"elementHeight": 600,
|
||||
"viewportWidth": 1024,
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
# For 2 tiles (3500px / 2000px = 1.75, rounded up to 2):
|
||||
# 1 initial call + 2 scroll + 2 element box + 1 reset scroll = 6 calls
|
||||
# 1 initial call + 2 scroll + 2 viewport info + 1 reset scroll = 6 calls
|
||||
mock_page.evaluate.side_effect = [
|
||||
element_info,
|
||||
None, # First scroll call
|
||||
element_box, # First element box call
|
||||
viewport_info, # First viewport info call
|
||||
None, # Second scroll call
|
||||
element_box, # Second element box call
|
||||
viewport_info, # Second viewport info call
|
||||
None, # Reset scroll call
|
||||
]
|
||||
|
||||
@@ -198,38 +223,57 @@ class TestTakeTiledScreenshot:
|
||||
"""Test that scroll positions are calculated correctly."""
|
||||
# Override the fixture's side_effect for this specific test
|
||||
element_info = {"height": 5000, "top": 100, "left": 50, "width": 800}
|
||||
element_box = {"x": 50, "y": 200, "width": 800, "height": 600}
|
||||
viewport_info = {
|
||||
"elementX": 50,
|
||||
"elementY": 200,
|
||||
"elementWidth": 800,
|
||||
"elementHeight": 600,
|
||||
"viewportWidth": 1024,
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
mock_page.evaluate.side_effect = [
|
||||
element_info, # Initial call for dashboard dimensions
|
||||
None, # First scroll call
|
||||
element_box, # First element box call
|
||||
None, # Second scroll call
|
||||
element_box, # Second element box call
|
||||
None, # Third scroll call
|
||||
element_box, # Third element box call
|
||||
None,
|
||||
viewport_info, # Tile 1
|
||||
None,
|
||||
viewport_info, # Tile 2
|
||||
None,
|
||||
viewport_info, # Tile 3
|
||||
None,
|
||||
viewport_info, # Tile 4
|
||||
None,
|
||||
viewport_info, # Tile 5
|
||||
None,
|
||||
viewport_info, # Tile 6
|
||||
None,
|
||||
viewport_info, # Tile 7
|
||||
None, # Reset scroll call
|
||||
]
|
||||
|
||||
with patch("superset.utils.screenshot_utils.combine_screenshot_tiles"):
|
||||
take_tiled_screenshot(mock_page, "dashboard", viewport_height=2000)
|
||||
|
||||
# Check scroll positions (dashboard_top = 100)
|
||||
# Check scroll positions (dashboard_top = 100, tile_height = 768)
|
||||
scroll_calls = [
|
||||
call
|
||||
for call in mock_page.evaluate.call_args_list
|
||||
if "scrollTo" in str(call)
|
||||
]
|
||||
|
||||
# Should have scrolled to positions: 100, 2100, 4100
|
||||
# Should have scrolled to positions: 100, 868, 1636, 2404, 3172, 3940, 4708
|
||||
expected_scrolls = [
|
||||
"window.scrollTo(0, 100)",
|
||||
"window.scrollTo(0, 2100)",
|
||||
"window.scrollTo(0, 4100)",
|
||||
"window.scrollTo(0, 868)",
|
||||
"window.scrollTo(0, 1636)",
|
||||
"window.scrollTo(0, 2404)",
|
||||
"window.scrollTo(0, 3172)",
|
||||
"window.scrollTo(0, 3940)",
|
||||
"window.scrollTo(0, 4708)",
|
||||
]
|
||||
actual_scrolls = [call[0][0] for call in scroll_calls]
|
||||
|
||||
assert len(actual_scrolls) == 4 # 3 tile scrolls + 1 reset
|
||||
assert len(actual_scrolls) == 8 # 7 tile scrolls + 1 reset
|
||||
for expected in expected_scrolls:
|
||||
assert expected in actual_scrolls
|
||||
|
||||
@@ -237,16 +281,31 @@ class TestTakeTiledScreenshot:
|
||||
"""Test that scroll position is reset after screenshot."""
|
||||
# Override the fixture's side_effect for this specific test
|
||||
element_info = {"height": 5000, "top": 100, "left": 50, "width": 800}
|
||||
element_box = {"x": 50, "y": 200, "width": 800, "height": 600}
|
||||
viewport_info = {
|
||||
"elementX": 50,
|
||||
"elementY": 200,
|
||||
"elementWidth": 800,
|
||||
"elementHeight": 600,
|
||||
"viewportWidth": 1024,
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
mock_page.evaluate.side_effect = [
|
||||
element_info, # Initial call for dashboard dimensions
|
||||
None, # First scroll call
|
||||
element_box, # First element box call
|
||||
None, # Second scroll call
|
||||
element_box, # Second element box call
|
||||
None, # Third scroll call
|
||||
element_box, # Third element box call
|
||||
None,
|
||||
viewport_info, # Tile 1
|
||||
None,
|
||||
viewport_info, # Tile 2
|
||||
None,
|
||||
viewport_info, # Tile 3
|
||||
None,
|
||||
viewport_info, # Tile 4
|
||||
None,
|
||||
viewport_info, # Tile 5
|
||||
None,
|
||||
viewport_info, # Tile 6
|
||||
None,
|
||||
viewport_info, # Tile 7
|
||||
None, # Reset scroll call
|
||||
]
|
||||
|
||||
@@ -268,7 +327,7 @@ class TestTakeTiledScreenshot:
|
||||
"Dashboard: %sx%spx at (%s, %s)", 800, 5000, 50, 100
|
||||
)
|
||||
# Should log number of tiles with lazy logging format
|
||||
mock_logger.info.assert_any_call("Taking %s screenshot tiles", 3)
|
||||
mock_logger.info.assert_any_call("Taking %s screenshot tiles", 7)
|
||||
|
||||
def test_exception_handling_returns_none(self):
|
||||
"""Test that exceptions are handled and None is returned."""
|
||||
@@ -289,8 +348,8 @@ class TestTakeTiledScreenshot:
|
||||
with patch("superset.utils.screenshot_utils.combine_screenshot_tiles"):
|
||||
take_tiled_screenshot(mock_page, "dashboard", viewport_height=2000)
|
||||
|
||||
# Should have called wait_for_timeout for each tile (3 tiles)
|
||||
assert mock_page.wait_for_timeout.call_count == 3
|
||||
# Should have called wait_for_timeout for each tile (7 tiles)
|
||||
assert mock_page.wait_for_timeout.call_count == 7
|
||||
|
||||
# Each wait should be 2000ms (2 seconds)
|
||||
for call in mock_page.wait_for_timeout.call_args_list:
|
||||
@@ -315,3 +374,367 @@ class TestTakeTiledScreenshot:
|
||||
assert clip["width"] == 800
|
||||
# Height should be min of viewport_height and remaining content
|
||||
assert clip["height"] <= 600 # Element height from mock
|
||||
|
||||
def test_negative_element_position_clipped_to_zero(self):
|
||||
"""Test that negative element positions are clipped to viewport bounds."""
|
||||
mock_page = MagicMock()
|
||||
mock_page.viewport_size = {"width": 1024, "height": 768}
|
||||
|
||||
# Mock element locator
|
||||
element = MagicMock()
|
||||
mock_page.locator.return_value = element
|
||||
|
||||
# Simulate element scrolled above viewport (negative Y position)
|
||||
element_info = {"height": 3000, "top": 100, "left": 0, "width": 800}
|
||||
viewport_info = {
|
||||
"elementX": 0,
|
||||
"elementY": -200, # Element is scrolled 200px above viewport
|
||||
"elementWidth": 800,
|
||||
"elementHeight": 600,
|
||||
"viewportWidth": 1024,
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
# For 4 tiles (3000px / 768px = 3.9, rounded up to 4):
|
||||
# 1 initial + 4 * (scroll + viewport info) + 1 reset = 10 calls
|
||||
mock_page.evaluate.side_effect = [
|
||||
element_info,
|
||||
None,
|
||||
viewport_info, # Tile 1
|
||||
None,
|
||||
viewport_info, # Tile 2
|
||||
None,
|
||||
viewport_info, # Tile 3
|
||||
None,
|
||||
viewport_info, # Tile 4
|
||||
None, # Reset scroll
|
||||
]
|
||||
|
||||
mock_page.screenshot.return_value = b"screenshot"
|
||||
|
||||
with patch("superset.utils.screenshot_utils.combine_screenshot_tiles"):
|
||||
result = take_tiled_screenshot(mock_page, "dashboard", viewport_height=2000)
|
||||
|
||||
# Should complete successfully
|
||||
assert result is not None
|
||||
|
||||
# Check that clip Y was adjusted to 0 (not negative)
|
||||
screenshot_calls = mock_page.screenshot.call_args_list
|
||||
for call in screenshot_calls:
|
||||
clip = call[1]["clip"]
|
||||
assert clip["y"] >= 0, "Clip Y should never be negative"
|
||||
assert clip["x"] >= 0, "Clip X should never be negative"
|
||||
|
||||
def test_element_extends_beyond_viewport(self):
|
||||
"""Test clipping when element extends beyond viewport boundaries."""
|
||||
mock_page = MagicMock()
|
||||
mock_page.viewport_size = {"width": 1024, "height": 768}
|
||||
|
||||
element = MagicMock()
|
||||
mock_page.locator.return_value = element
|
||||
|
||||
element_info = {"height": 2000, "top": 0, "left": 0, "width": 1200}
|
||||
|
||||
# Element is wider than viewport
|
||||
viewport_info = {
|
||||
"elementX": 0,
|
||||
"elementY": 100,
|
||||
"elementWidth": 1200, # Wider than viewport
|
||||
"elementHeight": 800,
|
||||
"viewportWidth": 1024, # Viewport width
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
# For 3 tiles (2000px / 768px = 2.6, rounded up to 3):
|
||||
# 1 initial + 3 * (scroll + viewport info) + 1 reset = 8 calls
|
||||
mock_page.evaluate.side_effect = [
|
||||
element_info,
|
||||
None,
|
||||
viewport_info, # Tile 1
|
||||
None,
|
||||
viewport_info, # Tile 2
|
||||
None,
|
||||
viewport_info, # Tile 3
|
||||
None, # Reset scroll
|
||||
]
|
||||
|
||||
mock_page.screenshot.return_value = b"screenshot"
|
||||
|
||||
with patch("superset.utils.screenshot_utils.combine_screenshot_tiles"):
|
||||
result = take_tiled_screenshot(mock_page, "dashboard", viewport_height=2000)
|
||||
|
||||
assert result is not None
|
||||
|
||||
# Check that clip width was constrained to viewport
|
||||
clip = mock_page.screenshot.call_args_list[0][1]["clip"]
|
||||
assert clip["width"] <= 1024, "Clip width should not exceed viewport"
|
||||
|
||||
def test_invalid_clip_dimensions_skipped(self):
|
||||
"""Test that tiles with invalid dimensions are skipped with a warning."""
|
||||
mock_page = MagicMock()
|
||||
mock_page.viewport_size = {"width": 1024, "height": 768}
|
||||
|
||||
element = MagicMock()
|
||||
mock_page.locator.return_value = element
|
||||
|
||||
element_info = {"height": 4000, "top": 0, "left": 0, "width": 800}
|
||||
|
||||
# First tile: valid
|
||||
valid_viewport_info = {
|
||||
"elementX": 0,
|
||||
"elementY": 100,
|
||||
"elementWidth": 800,
|
||||
"elementHeight": 600,
|
||||
"viewportWidth": 1024,
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
# Second tile: invalid (negative height after calculation)
|
||||
invalid_viewport_info = {
|
||||
"elementX": 0,
|
||||
"elementY": -1000, # Far above viewport
|
||||
"elementWidth": 800,
|
||||
"elementHeight": 100, # Not enough visible height
|
||||
"viewportWidth": 1024,
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
# For 6 tiles (4000px / 768px = 5.2, rounded up to 6):
|
||||
# 1 initial + 6 * (scroll + viewport info) + 1 reset = 14 calls
|
||||
mock_page.evaluate.side_effect = [
|
||||
element_info,
|
||||
None,
|
||||
valid_viewport_info, # Tile 1 - valid
|
||||
None,
|
||||
invalid_viewport_info, # Tile 2 - invalid, should be skipped
|
||||
None,
|
||||
valid_viewport_info, # Tile 3 - valid
|
||||
None,
|
||||
valid_viewport_info, # Tile 4 - valid
|
||||
None,
|
||||
valid_viewport_info, # Tile 5 - valid
|
||||
None,
|
||||
valid_viewport_info, # Tile 6 - valid
|
||||
None, # Reset scroll
|
||||
]
|
||||
|
||||
mock_page.screenshot.return_value = b"screenshot"
|
||||
|
||||
with patch("superset.utils.screenshot_utils.logger") as mock_logger:
|
||||
with patch("superset.utils.screenshot_utils.combine_screenshot_tiles"):
|
||||
result = take_tiled_screenshot(
|
||||
mock_page, "dashboard", viewport_height=2000
|
||||
)
|
||||
|
||||
# Should complete but with warning
|
||||
assert result is not None
|
||||
|
||||
# Should have logged a warning about skipping tile
|
||||
mock_logger.warning.assert_called_once()
|
||||
warning_msg = mock_logger.warning.call_args[0][0]
|
||||
assert "Skipping tile" in warning_msg
|
||||
assert "invalid clip dimensions" in warning_msg
|
||||
|
||||
# Should have taken 5 screenshots (6 tiles - 1 invalid)
|
||||
assert mock_page.screenshot.call_count == 5
|
||||
|
||||
def test_viewport_bounds_with_offset_element(self):
|
||||
"""Test proper clipping for element with positive offset from viewport edge."""
|
||||
mock_page = MagicMock()
|
||||
mock_page.viewport_size = {"width": 1024, "height": 768}
|
||||
|
||||
element = MagicMock()
|
||||
mock_page.locator.return_value = element
|
||||
|
||||
element_info = {"height": 2000, "top": 500, "left": 200, "width": 600}
|
||||
|
||||
# Element starts 200px from left edge
|
||||
viewport_info = {
|
||||
"elementX": 200, # Offset from left
|
||||
"elementY": 150,
|
||||
"elementWidth": 600,
|
||||
"elementHeight": 500,
|
||||
"viewportWidth": 1024,
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
# For 3 tiles (2000px / 768px = 2.6, rounded up to 3):
|
||||
# 1 initial + 3 * (scroll + viewport info) + 1 reset = 8 calls
|
||||
mock_page.evaluate.side_effect = [
|
||||
element_info,
|
||||
None,
|
||||
viewport_info, # Tile 1
|
||||
None,
|
||||
viewport_info, # Tile 2
|
||||
None,
|
||||
viewport_info, # Tile 3
|
||||
None, # Reset scroll
|
||||
]
|
||||
|
||||
mock_page.screenshot.return_value = b"screenshot"
|
||||
|
||||
with patch("superset.utils.screenshot_utils.combine_screenshot_tiles"):
|
||||
result = take_tiled_screenshot(mock_page, "dashboard", viewport_height=2000)
|
||||
|
||||
assert result is not None
|
||||
|
||||
# Check clip respects element position
|
||||
clip = mock_page.screenshot.call_args_list[0][1]["clip"]
|
||||
assert clip["x"] == 200, "Should preserve element X offset"
|
||||
assert clip["y"] == 150, "Should preserve element Y offset"
|
||||
assert clip["width"] == 600, "Should use element width"
|
||||
|
||||
def test_zero_width_element_skipped(self):
|
||||
"""Test that elements with zero or negative width are skipped."""
|
||||
mock_page = MagicMock()
|
||||
mock_page.viewport_size = {"width": 1024, "height": 768}
|
||||
|
||||
element = MagicMock()
|
||||
mock_page.locator.return_value = element
|
||||
|
||||
element_info = {"height": 2000, "top": 0, "left": 0, "width": 0}
|
||||
|
||||
viewport_info = {
|
||||
"elementX": 0,
|
||||
"elementY": 100,
|
||||
"elementWidth": 0, # Zero width
|
||||
"elementHeight": 600,
|
||||
"viewportWidth": 1024,
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
# For 3 tiles (2000px / 768px = 2.6, rounded up to 3):
|
||||
# 1 initial + 3 * (scroll + viewport info) + 1 reset = 8 calls
|
||||
# All tiles will be skipped due to zero width
|
||||
mock_page.evaluate.side_effect = [
|
||||
element_info,
|
||||
None,
|
||||
viewport_info, # Tile 1 - skipped
|
||||
None,
|
||||
viewport_info, # Tile 2 - skipped
|
||||
None,
|
||||
viewport_info, # Tile 3 - skipped
|
||||
None, # Reset scroll
|
||||
]
|
||||
|
||||
with patch("superset.utils.screenshot_utils.logger") as mock_logger:
|
||||
with patch("superset.utils.screenshot_utils.combine_screenshot_tiles"):
|
||||
result = take_tiled_screenshot(
|
||||
mock_page, "dashboard", viewport_height=2000
|
||||
)
|
||||
|
||||
# Should handle gracefully
|
||||
assert result is not None
|
||||
|
||||
# Should have logged warnings about invalid dimensions
|
||||
# (3 times, once per tile)
|
||||
assert mock_logger.warning.call_count == 3
|
||||
for call in mock_logger.warning.call_args_list:
|
||||
warning_msg = call[0][0]
|
||||
assert "invalid clip dimensions" in warning_msg
|
||||
|
||||
# Should not have taken any screenshots
|
||||
assert mock_page.screenshot.call_count == 0
|
||||
|
||||
def test_element_completely_above_viewport(self):
|
||||
"""Test element that is completely scrolled above the viewport."""
|
||||
mock_page = MagicMock()
|
||||
mock_page.viewport_size = {"width": 1024, "height": 768}
|
||||
|
||||
element = MagicMock()
|
||||
mock_page.locator.return_value = element
|
||||
|
||||
element_info = {"height": 2000, "top": 0, "left": 0, "width": 800}
|
||||
|
||||
# Element completely above viewport
|
||||
viewport_info = {
|
||||
"elementX": 0,
|
||||
"elementY": -800, # Completely above viewport
|
||||
"elementWidth": 800,
|
||||
"elementHeight": 600,
|
||||
"viewportWidth": 1024,
|
||||
"viewportHeight": 768,
|
||||
}
|
||||
|
||||
# For 3 tiles (2000px / 768px = 2.6, rounded up to 3):
|
||||
# 1 initial + 3 * (scroll + viewport info) + 1 reset = 8 calls
|
||||
# All tiles will be skipped because element is completely above viewport
|
||||
mock_page.evaluate.side_effect = [
|
||||
element_info,
|
||||
None,
|
||||
viewport_info, # Tile 1 - skipped
|
||||
None,
|
||||
viewport_info, # Tile 2 - skipped
|
||||
None,
|
||||
viewport_info, # Tile 3 - skipped
|
||||
None, # Reset scroll
|
||||
]
|
||||
|
||||
with patch("superset.utils.screenshot_utils.logger") as mock_logger:
|
||||
with patch("superset.utils.screenshot_utils.combine_screenshot_tiles"):
|
||||
result = take_tiled_screenshot(
|
||||
mock_page, "dashboard", viewport_height=2000
|
||||
)
|
||||
|
||||
# Should handle gracefully
|
||||
assert result is not None
|
||||
|
||||
# Should have skipped all 3 tiles with warnings
|
||||
assert mock_logger.warning.call_count == 3
|
||||
|
||||
# Should not have taken screenshots
|
||||
assert mock_page.screenshot.call_count == 0
|
||||
|
||||
def test_scroll_increment_respects_actual_viewport_height(self):
|
||||
"""When config viewport height > actual viewport, we still cover every tile."""
|
||||
mock_page = MagicMock()
|
||||
mock_page.viewport_size = {"width": 1600, "height": 1200}
|
||||
|
||||
element = MagicMock()
|
||||
mock_page.locator.return_value = element
|
||||
|
||||
element_info = {"height": 3600, "top": 0, "left": 0, "width": 800}
|
||||
viewport_info = {
|
||||
"elementX": 0,
|
||||
"elementY": 0,
|
||||
"elementWidth": 800,
|
||||
"elementHeight": 1200,
|
||||
"viewportWidth": 1600,
|
||||
"viewportHeight": 1200,
|
||||
}
|
||||
|
||||
mock_page.evaluate.side_effect = [
|
||||
element_info, # Initial call for dashboard dimensions
|
||||
None, # First scroll
|
||||
viewport_info, # First viewport info
|
||||
None, # Second scroll
|
||||
viewport_info, # Second viewport info
|
||||
None, # Third scroll
|
||||
viewport_info, # Third viewport info
|
||||
None, # Reset scroll
|
||||
]
|
||||
|
||||
mock_page.screenshot.return_value = b"screenshot"
|
||||
|
||||
with patch("superset.utils.screenshot_utils.combine_screenshot_tiles"):
|
||||
take_tiled_screenshot(mock_page, "dashboard", viewport_height=2000)
|
||||
|
||||
# We expect three tiles (0–1200, 1200–2400, 2400–3600)
|
||||
# even though config says 2000.
|
||||
assert mock_page.screenshot.call_count == 3
|
||||
|
||||
scroll_calls = [
|
||||
call
|
||||
for call in mock_page.evaluate.call_args_list
|
||||
if "scrollTo" in str(call)
|
||||
]
|
||||
actual_scrolls = [call[0][0] for call in scroll_calls]
|
||||
|
||||
# Should have scrolled to positions: 0, 1200, 2400, plus final reset to 0
|
||||
assert len(actual_scrolls) == 4 # 3 tile scrolls + 1 reset
|
||||
assert actual_scrolls == [
|
||||
"window.scrollTo(0, 0)",
|
||||
"window.scrollTo(0, 1200)",
|
||||
"window.scrollTo(0, 2400)",
|
||||
"window.scrollTo(0, 0)", # Reset scroll
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user