Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa52a38be9 | ||
|
|
0ef7482713 | ||
|
|
6828e17516 | ||
|
|
d00bde7b8e | ||
|
|
fb5029d06d | ||
|
|
041d735ddb | ||
|
|
49a4086715 | ||
|
|
31218987ec | ||
|
|
de4def38cb | ||
|
|
4f77538bc2 | ||
|
|
5bbd4c6d23 | ||
|
|
3b98869e0a | ||
|
|
e7fa8529ce | ||
|
|
c487c006e9 | ||
|
|
fd27a0c2fd | ||
|
|
42c6746339 | ||
|
|
fbd2e6032e | ||
|
|
e66b2f8be5 | ||
|
|
04bd07ad6e | ||
|
|
1c98c0711e | ||
|
|
13dd061907 | ||
|
|
bf47750682 | ||
|
|
990785cfa4 | ||
|
|
7174af24ca | ||
|
|
bbd021925a | ||
|
|
464674f193 | ||
|
|
c7a83794d2 | ||
|
|
dbc561f80f | ||
|
|
86003221bc | ||
|
|
9615e7c024 | ||
|
|
80c8d9f388 | ||
|
|
59f1d91b07 | ||
|
|
a4fc9ae493 | ||
|
|
5bbe3ac750 | ||
|
|
1aeff038d7 | ||
|
|
b73f6a8bd5 | ||
|
|
1859b375a7 | ||
|
|
b85468ee17 | ||
|
|
2261c61791 | ||
|
|
9fe31e3ec5 | ||
|
|
c7f0167a28 | ||
|
|
52b5110a53 | ||
|
|
a33ab097e1 | ||
|
|
05ce4d41bf | ||
|
|
8cd636bcd0 | ||
|
|
18231d9bd4 | ||
|
|
ca17830175 | ||
|
|
2be95c6283 | ||
|
|
6edeafff6b | ||
|
|
b2d2aa4452 | ||
|
|
09a034c573 | ||
|
|
f2fd536823 | ||
|
|
9c6b1f0eb6 | ||
|
|
f2055d8446 | ||
|
|
fbd088af48 | ||
|
|
d7c34215a2 | ||
|
|
a82128cde0 | ||
|
|
9ff15cb53e | ||
|
|
ac7f53326f | ||
|
|
feb224686b | ||
|
|
f93cc1a67b | ||
|
|
d2911672bf | ||
|
|
f9dfea8791 | ||
|
|
a5aa619668 | ||
|
|
dfc745c922 | ||
|
|
936ec951d5 | ||
|
|
acc93dfe33 | ||
|
|
a973290890 | ||
|
|
377e8e6345 | ||
|
|
71443460d1 | ||
|
|
dcda71e869 | ||
|
|
d59120a632 | ||
|
|
ba795ccfa0 | ||
|
|
6a5049daed | ||
|
|
83e7098ee8 | ||
|
|
b71ea77080 | ||
|
|
b3435a04cf | ||
|
|
1771f05d33 | ||
|
|
3dfe193ca0 | ||
|
|
c54abcfda8 | ||
|
|
b2849d826a | ||
|
|
2cd9873540 | ||
|
|
8948b5af94 | ||
|
|
3bcb003eeb | ||
|
|
480fbe0e06 | ||
|
|
3abbe1c84a | ||
|
|
311b0087f3 | ||
|
|
0fea3c88a5 | ||
|
|
e61610bd98 | ||
|
|
9729306c06 | ||
|
|
93a02449db | ||
|
|
cbbcf1bed2 | ||
|
|
218c64296f | ||
|
|
39eced2c2e | ||
|
|
bef4680ffd | ||
|
|
5870259219 | ||
|
|
a4bcd2cc87 | ||
|
|
f8dd65cc0b | ||
|
|
b1bc8fa8f2 | ||
|
|
5d86215a9d | ||
|
|
f866f25546 | ||
|
|
3392576923 | ||
|
|
e95b37450e | ||
|
|
ff73f2c070 | ||
|
|
612fd0ac5d | ||
|
|
83dbdfa355 | ||
|
|
fc3872fe9e | ||
|
|
0946df50a1 | ||
|
|
d9c3a2cf4c | ||
|
|
f84d7c664e | ||
|
|
45fd4117a9 | ||
|
|
79acc3a712 | ||
|
|
62d0cfb6d3 | ||
|
|
b885657ad0 | ||
|
|
a191f72698 | ||
|
|
498400e974 | ||
|
|
b9a8321802 | ||
|
|
902ebcdf72 | ||
|
|
f76471f30f | ||
|
|
b671356748 | ||
|
|
ff273478ff | ||
|
|
f1cc9367de | ||
|
|
02e4b4be7d | ||
|
|
ecb4aa93f6 | ||
|
|
4e1913d436 | ||
|
|
b6ae8fb25d | ||
|
|
10f2461b5f | ||
|
|
4e715f66dc | ||
|
|
6dfae09cc5 | ||
|
|
a4f74b09bb | ||
|
|
9f39fe3e10 | ||
|
|
c6f8706aa1 | ||
|
|
07a6406d97 | ||
|
|
a585a0901e | ||
|
|
fff5351a33 | ||
|
|
b4f8d87a49 | ||
|
|
3256ee4fbb | ||
|
|
e5b3ba9efc | ||
|
|
ae93dc2041 | ||
|
|
792d0fd2b6 | ||
|
|
8dcb83fd3c | ||
|
|
8f07ab4840 | ||
|
|
89d64b89b8 | ||
|
|
4ce589dcda | ||
|
|
a31210df08 | ||
|
|
00e95dcb87 | ||
|
|
c9960002f1 | ||
|
|
dbac244857 | ||
|
|
4483cb09f0 | ||
|
|
28d977bc0c | ||
|
|
b248c4d7c0 | ||
|
|
3e9fdc4cdf | ||
|
|
387b742303 | ||
|
|
533f90e4c6 | ||
|
|
b887c30573 | ||
|
|
2cd369d02a | ||
|
|
4b3bbe19f6 | ||
|
|
28eae5956e | ||
|
|
239e3a4323 | ||
|
|
573054346f | ||
|
|
a42c7e3be0 | ||
|
|
935b4acdbd | ||
|
|
bba2d5f812 | ||
|
|
7d45b8ae7e | ||
|
|
5942d570c3 | ||
|
|
45adb8429d | ||
|
|
3a03f0a820 | ||
|
|
105f6d0bc7 | ||
|
|
c8d6faf7e8 | ||
|
|
ae15dd883d | ||
|
|
2afa775db5 | ||
|
|
e17d49bec0 | ||
|
|
68324050cd | ||
|
|
2a55ad77f4 | ||
|
|
cd535f89e2 | ||
|
|
8b2c07f5f3 | ||
|
|
a9045296d9 | ||
|
|
32cbc4a7a6 | ||
|
|
4f47eda5de | ||
|
|
ba2b0d6ea3 | ||
|
|
df176cfa57 | ||
|
|
66e911eeea | ||
|
|
759457264d | ||
|
|
5722b96280 | ||
|
|
deb6cacea7 | ||
|
|
0f8e2a274d | ||
|
|
7e0de356d4 | ||
|
|
4e93b58a61 | ||
|
|
45b232cba0 | ||
|
|
bcc58d27f8 | ||
|
|
b5df673d21 |
@@ -29,7 +29,7 @@
|
||||
"dependencies:python":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'requirements/**'
|
||||
- 'superset/requirements/**'
|
||||
- 'superset/translations/requirements.txt'
|
||||
- 'RELEASING/requirements.txt'
|
||||
|
||||
|
||||
@@ -21,9 +21,6 @@ on:
|
||||
#schedule:
|
||||
# - cron: '0 0 * * *' # Runs daily at midnight UTC
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
bump-python-package:
|
||||
runs-on: ubuntu-slim
|
||||
|
||||
@@ -16,9 +16,6 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check_db_migration_conflict:
|
||||
name: Check DB migration conflict
|
||||
|
||||
@@ -14,9 +14,6 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-26.04
|
||||
|
||||
@@ -33,9 +33,6 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
enforce-single-migration-head:
|
||||
runs-on: ubuntu-26.04
|
||||
|
||||
@@ -7,9 +7,6 @@ on:
|
||||
pull_request:
|
||||
types: [opened, edited]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
superbot-orglabel:
|
||||
runs-on: ubuntu-slim
|
||||
|
||||
@@ -7,9 +7,6 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
permissions:
|
||||
|
||||
@@ -3,9 +3,6 @@ on:
|
||||
release:
|
||||
types: [published] # This makes it run only when a new released is published
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
latest-release:
|
||||
name: Add/update tag to new release
|
||||
|
||||
@@ -19,9 +19,6 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint-check:
|
||||
runs-on: ubuntu-slim
|
||||
|
||||
@@ -17,9 +17,6 @@ env:
|
||||
GITHUB_ORG: ${{ github.repository_owner }}
|
||||
GITHUB_REPO: ${{ github.event.repository.name }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
cleanup-expired:
|
||||
name: Clean up expired showtime environments
|
||||
|
||||
@@ -26,9 +26,6 @@ env:
|
||||
GITHUB_REPO: ${{ github.event.repository.name }}
|
||||
GITHUB_ACTOR: ${{ github.actor }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: 🎪 Sync PR to desired state
|
||||
|
||||
@@ -26,9 +26,6 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-26.04
|
||||
|
||||
@@ -27,9 +27,6 @@ concurrency:
|
||||
group: helm-release
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-26.04
|
||||
|
||||
@@ -22,9 +22,6 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-26.04
|
||||
|
||||
@@ -14,9 +14,6 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-26.04
|
||||
|
||||
@@ -13,9 +13,6 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
supersetbot:
|
||||
runs-on: ubuntu-26.04
|
||||
|
||||
@@ -5,9 +5,6 @@ on:
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
welcome:
|
||||
runs-on: ubuntu-slim
|
||||
|
||||
@@ -24,8 +24,6 @@ assists people when migrating to a new version.
|
||||
|
||||
## Next
|
||||
|
||||
- `SAMPLES_ROW_LIMIT` is now the default for `/datasource/samples` requests without a valid explicit `per_page`, rather than a hard per-request ceiling; explicit limits are honored up to the existing global row-limit ceiling, matching `/chart/data` SAMPLES requests.
|
||||
|
||||
### OAuth2 database callback metrics include their outcome
|
||||
|
||||
The unqualified `DatabaseRestApi.oauth2` StatsD counter has been replaced with
|
||||
@@ -33,7 +31,6 @@ The unqualified `DatabaseRestApi.oauth2` StatsD counter has been replaced with
|
||||
`DatabaseRestApi.oauth2.error`. Update monitoring rules and dashboards that consume
|
||||
the old counter to use the outcome-specific replacements.
|
||||
|
||||
- [42930](https://github.com/apache/superset/pull/42930): Dataset import data-URI fetches no longer honor an HTTP(S) proxy when `DATASET_IMPORT_ALLOW_INTERNAL_DATA_URLS` is `False` (the default): the connection is now made directly to the destination so the peer-address check validates the real target instead of a proxy's. Deployments that require an egress proxy to reach legitimate external data URLs for dataset import should set `DATASET_IMPORT_ALLOW_INTERNAL_DATA_URLS = True` or otherwise ensure those URLs resolve without one.
|
||||
- [42935](https://github.com/apache/superset/pull/42935): The MCP service now refuses to start (`MCPAuthConfigError`) when `MCP_JWT_ISSUER` trusts more than one issuer and no `MCP_USER_RESOLVER` is configured, instead of only logging a warning. This was already a documented misconfiguration (the default resolver isn't issuer-scoped, so distinct trusted issuers minting the same username/email would resolve to the same Superset user); deployments trusting multiple issuers must configure an `MCP_USER_RESOLVER` that derives its identity from the token's `iss` claim before upgrading. Single-issuer deployments are unaffected.
|
||||
- [42393](https://github.com/apache/superset/pull/42393): Exported dataset YAML now carries a `uuid` for each metric and column so that custom folder assignments (which reference metrics/columns by UUID) survive an import into another workspace. This affects any export bundle that contains datasets, not just a dataset export: chart, dashboard, database and full-asset exports all embed the same dataset YAML, so a dashboard exported from this release also fails to import into an older one even though no dataset was exported directly. As with `folders` and `currency_code_column`, the affected `datasets/` files fail schema validation (`Unknown field: uuid`) when imported into Superset releases that predate this change; regenerate or hand-edit exports for older targets in mixed-version fleets.
|
||||
- [42300](https://github.com/apache/superset/pull/42300): Timeseries charts (line/area/bar) with a Y-axis bound in effect — either an explicit `yAxisBounds` or one derived from `truncateYAxis` — now clamp out-of-range data points to that bound instead of letting ECharts drop the point (and the line segments around it) entirely. Any existing chart with a configured Y-axis bound and data outside it will look different after upgrading: a gap becomes a point pinned to the boundary. The clamp also rewrites the value ECharts reads for that point's tooltip and data label, so the displayed value is the bound rather than the true observation.
|
||||
|
||||
@@ -97,54 +97,6 @@ for more information on how to configure it.
|
||||
|
||||
At the very least, you'll want to change `SECRET_KEY` and `SQLALCHEMY_DATABASE_URI`. Continue reading for more about each of these.
|
||||
|
||||
## Localizing D3 date and time labels
|
||||
|
||||
`BABEL_DEFAULT_LOCALE` controls Superset's application translations, while
|
||||
`D3_TIME_FORMAT` provides localized date and time names to visualizations that
|
||||
use the D3 formatter registry, including Calendar Heatmap. Configure both when
|
||||
you want the application and chart labels to use the same locale.
|
||||
|
||||
`D3_TIME_FORMAT` accepts partial overrides. For example, Russian month names
|
||||
can be configured in `superset_config.py` as follows:
|
||||
|
||||
```python
|
||||
BABEL_DEFAULT_LOCALE = "ru"
|
||||
|
||||
D3_TIME_FORMAT = {
|
||||
"months": [
|
||||
"Январь",
|
||||
"Февраль",
|
||||
"Март",
|
||||
"Апрель",
|
||||
"Май",
|
||||
"Июнь",
|
||||
"Июль",
|
||||
"Август",
|
||||
"Сентябрь",
|
||||
"Октябрь",
|
||||
"Ноябрь",
|
||||
"Декабрь",
|
||||
],
|
||||
"shortMonths": [
|
||||
"Янв",
|
||||
"Фев",
|
||||
"Мар",
|
||||
"Апр",
|
||||
"Май",
|
||||
"Июн",
|
||||
"Июл",
|
||||
"Авг",
|
||||
"Сен",
|
||||
"Окт",
|
||||
"Ноя",
|
||||
"Дек",
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Restart Superset after changing `superset_config.py` so the frontend receives
|
||||
the updated formatter configuration.
|
||||
|
||||
## Chart-data query timing
|
||||
|
||||
Set `CHART_DATA_INCLUDE_TIMING = True` to add an optional versioned timing object
|
||||
|
||||
@@ -400,7 +400,7 @@ Once enabled, each user manages their own keys from their profile page:
|
||||
1. Open the user menu (top-right) and click **Info** to navigate to the User Info page
|
||||
2. Expand the **API Keys** section
|
||||
3. Click **+ API Key**
|
||||
4. Enter a name and optionally select resource scopes
|
||||
4. Enter a name and (optionally) an expiration date
|
||||
5. Copy the generated token — it is shown only once
|
||||
|
||||
Only users with the `can_read` and `can_write` permissions on `ApiKey` (granted by default to Admins) can manage API keys.
|
||||
@@ -415,18 +415,6 @@ Authorization: Bearer <your-api-key>
|
||||
|
||||
This works for all REST API endpoints and the MCP server. The request is executed with the permissions of the user who created the key.
|
||||
|
||||
#### API Key Scopes
|
||||
|
||||
The creation dialog can restrict an API key to MCP resource actions such as
|
||||
`superset:dashboard:read` or `superset:chart:write`. A scope is an additional
|
||||
restriction: it never grants a permission that the creating user does not
|
||||
already have through Superset RBAC. Write scopes also cover update and delete
|
||||
operations for that resource; `superset:sqllab:write` covers SQL execution.
|
||||
|
||||
Keys created without scopes retain legacy RBAC-only behavior. The scoped-key
|
||||
restrictions described here are enforced by the MCP server; regular REST API
|
||||
routes continue to apply their existing Superset RBAC checks.
|
||||
|
||||
#### Use Cases
|
||||
|
||||
- **CI/CD pipelines** — automated chart/dashboard exports and imports
|
||||
|
||||
@@ -46,43 +46,13 @@ import FAQSchema from '@site/src/components/FAQSchema';
|
||||
answer:
|
||||
'You need to register a free account at Mapbox.com, obtain an API key, and add it to your .env file at the key MAPBOX_API_KEY.',
|
||||
},
|
||||
{
|
||||
question: 'How to limit the timed refresh on a dashboard?',
|
||||
answer:
|
||||
'To exclude specific slices from the timed refresh process, add the timed_refresh_immune_slices key to the dashboard JSON Metadata field with the slice IDs to exclude.',
|
||||
},
|
||||
{
|
||||
question: "Why does 'flask fab' or Superset freeze, hang, or not respond when started (my home directory is NFS mounted)?",
|
||||
answer:
|
||||
'By default, Superset creates and uses an SQLite database at ~/.superset/superset.db. SQLite is known to not work well if used on NFS due to broken file locking. Override the path with the SUPERSET_HOME environment variable or change SQLALCHEMY_DATABASE_URI in superset_config.py.',
|
||||
},
|
||||
{
|
||||
question: 'What if the table schema changed?',
|
||||
answer:
|
||||
'Go to Data -> Datasets, click the edit icon next to the dataset whose schema has changed, and hit Sync columns from source from the Columns tab. The new columns will get merged.',
|
||||
},
|
||||
{
|
||||
question: 'What database engine can I use as a backend for Superset?',
|
||||
answer:
|
||||
'Superset is tested using MySQL, PostgreSQL, and SQLite backends for storing its internal metadata. While Superset supports many databases as data sources, only these are recommended for the metadata store in production.',
|
||||
},
|
||||
{
|
||||
question: 'How can I configure OAuth authentication and authorization?',
|
||||
answer:
|
||||
'Take a look at the Flask-AppBuilder OAuth configuration example, which shows how to configure OAuth authentication and authorization in Superset.',
|
||||
},
|
||||
{
|
||||
question: 'Is there a way to force the dashboard to use specific colors?',
|
||||
answer:
|
||||
'It is possible on a per-dashboard basis by providing a mapping of labels to colors in the JSON Metadata attribute using the label_colors key. You can use a full hex color, a named color, or the index in the current color palette.',
|
||||
},
|
||||
{
|
||||
question: 'How do I expand all chart descriptions on a dashboard by default?',
|
||||
answer:
|
||||
'Add the expand_all_slices key to the dashboard JSON Metadata field with a value of true. Charts that have already been manually expanded or collapsed keep that per-chart override regardless of the setting.',
|
||||
},
|
||||
{
|
||||
question: 'Does Superset work with [insert database engine here]?',
|
||||
question: 'Does Superset work with my database?',
|
||||
answer:
|
||||
'Superset supports any database with a Python SQLAlchemy dialect and DBAPI driver. Check the Connecting to Databases documentation for the full list of supported databases.',
|
||||
},
|
||||
@@ -91,30 +61,15 @@ import FAQSchema from '@site/src/components/FAQSchema';
|
||||
answer:
|
||||
'Yes, Superset has a public REST API documented using Swagger. Enable FAB_API_SWAGGER_UI in superset_config.py to access interactive API documentation at /swagger/v1.',
|
||||
},
|
||||
{
|
||||
question: 'How can I see usage statistics (e.g., monthly active users)?',
|
||||
answer:
|
||||
'This functionality is not included with Superset, but you can extract and analyze the logs table in Superset\u2019s metadata database to see what actions have occurred.',
|
||||
},
|
||||
{
|
||||
question: 'What does Hours Offset in the Edit Dataset view do?',
|
||||
answer:
|
||||
'In the Edit Dataset view, the hours offset lets you configure the number of hours to be added or subtracted from the time column. This can be used, for example, to convert UTC time to local time.',
|
||||
},
|
||||
{
|
||||
question: 'Does Superset collect any telemetry data?',
|
||||
answer:
|
||||
'Superset uses Scarf by default to collect basic telemetry data to help maintainers understand version usage. Users can opt out by setting the SCARF_ANALYTICS environment variable to false.',
|
||||
},
|
||||
{
|
||||
question: 'Does Superset have an archive panel or trash bin from which a user can recover deleted assets?',
|
||||
question: 'Does Superset have a trash bin to recover deleted assets?',
|
||||
answer:
|
||||
'No. Currently, there is no way to recover a deleted Superset dashboard, chart, dataset, or database from the UI. It is recommended to take periodic backups of the metadata database and use export functionality for recovery.',
|
||||
},
|
||||
{
|
||||
question: 'I ran a security scan of the Superset container image and it showed dozens of "high" and "critical" vulnerabilities! Can you release a version of Superset without these?',
|
||||
answer:
|
||||
'These are dependency CVEs in software that Superset uses, mostly in the Linux kernel or Python. Superset addresses them by regularly updating dependencies and welcomes pull requests that fix dependency CVEs. The Superset security team focuses primarily on vulnerabilities in Superset itself.',
|
||||
'No, there is no built-in way to recover deleted dashboards, charts, or datasets. It is recommended to take periodic backups of the metadata database and use export functionality for recovery.',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
@@ -259,7 +214,8 @@ frontend falls back to a built-in default of `5000` milliseconds.
|
||||
SUPERSET_DASHBOARD_MANUAL_REFRESH_STAGGER_MS = 0
|
||||
```
|
||||
|
||||
## Why does `flask fab` or Superset freeze, hang, or not respond when started (my home directory is NFS mounted)?
|
||||
**Why does ‘flask fab’ or superset freeze/hang/not responding when started (my home directory is
|
||||
NFS mounted)?**
|
||||
|
||||
By default, Superset creates and uses an SQLite database at `~/.superset/superset.db`. SQLite is
|
||||
known to [not work well if used on NFS](https://www.sqlite.org/lockingv3.html) due to broken file
|
||||
|
||||
@@ -61,9 +61,9 @@
|
||||
"@storybook/addon-docs": "^10.5.7",
|
||||
"@superset-ui/core": "^0.20.4",
|
||||
"@swc/core": "^1.15.47",
|
||||
"antd": "^6.6.0",
|
||||
"baseline-browser-mapping": "^2.11.13",
|
||||
"caniuse-lite": "^1.0.30001809",
|
||||
"antd": "^6.5.4",
|
||||
"baseline-browser-mapping": "^2.11.12",
|
||||
"caniuse-lite": "^1.0.30001807",
|
||||
"docusaurus-plugin-openapi-docs": "^5.1.3",
|
||||
"docusaurus-theme-openapi-docs": "^5.1.3",
|
||||
"js-yaml": "^5.2.3",
|
||||
@@ -89,14 +89,14 @@
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/react": "^19.1.8",
|
||||
"@typescript-eslint/eslint-plugin": "^8.67.0",
|
||||
"@typescript-eslint/parser": "^8.67.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.66.0",
|
||||
"@typescript-eslint/parser": "^8.66.0",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^17.9.0",
|
||||
"oxfmt": "^0.63.0",
|
||||
"oxfmt": "^0.62.0",
|
||||
"typescript": "~6.0.3",
|
||||
"typescript-eslint": "^8.67.0",
|
||||
"typescript-eslint": "^8.66.0",
|
||||
"webpack": "^5.109.2"
|
||||
},
|
||||
"browserslist": {
|
||||
|
||||
@@ -3407,26 +3407,22 @@
|
||||
"nullable": true,
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"nullable": true,
|
||||
"type": "string"
|
||||
},
|
||||
"editors": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list.Subject"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"is_managed_externally": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"owners": {
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list.User2"
|
||||
},
|
||||
"published": {
|
||||
"nullable": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"roles": {
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list.Role"
|
||||
},
|
||||
"slug": {
|
||||
"maxLength": 255,
|
||||
"nullable": true,
|
||||
@@ -3436,10 +3432,10 @@
|
||||
"readOnly": true
|
||||
},
|
||||
"tags": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list.Tag"
|
||||
},
|
||||
"type": "array"
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list.Tag"
|
||||
},
|
||||
"thumbnail_url": {
|
||||
"readOnly": true
|
||||
},
|
||||
"url": {
|
||||
"readOnly": true
|
||||
@@ -3448,46 +3444,21 @@
|
||||
"format": "uuid",
|
||||
"nullable": true,
|
||||
"type": "string"
|
||||
},
|
||||
"viewers": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list.Subject1"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"DashboardRestApi.get_list.Subject": {
|
||||
"DashboardRestApi.get_list.Role": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"label": {
|
||||
"maxLength": 255,
|
||||
"name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": ["label", "type"],
|
||||
"type": "object"
|
||||
},
|
||||
"DashboardRestApi.get_list.Subject1": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"label": {
|
||||
"maxLength": 255,
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": ["label", "type"],
|
||||
"required": ["name"],
|
||||
"type": "object"
|
||||
},
|
||||
"DashboardRestApi.get_list.Tag": {
|
||||
@@ -3540,6 +3511,23 @@
|
||||
"required": ["first_name", "last_name"],
|
||||
"type": "object"
|
||||
},
|
||||
"DashboardRestApi.get_list.User2": {
|
||||
"properties": {
|
||||
"first_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["first_name", "last_name"],
|
||||
"type": "object"
|
||||
},
|
||||
"DashboardRestApi.post": {
|
||||
"properties": {
|
||||
"certification_details": {
|
||||
@@ -16518,7 +16506,7 @@
|
||||
},
|
||||
"result": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list"
|
||||
"type": "object"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
|
||||
@@ -1142,11 +1142,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.7.tgz#12022450c45a4da6d8d8287b18a4ff2ddb23f768"
|
||||
integrity sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==
|
||||
|
||||
"@babel/runtime@^8.0.0":
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-8.0.0.tgz#d7bd513e6843662346552c2798ab895716cf97f2"
|
||||
integrity sha512-sL6cvO2IfkSu/iU+zs2S/w01B7A8V7suXSIKEN4hPFFdZoiPGxrj5pAG0lCaqLWiEIrjKzdznIWuaLcxPR53qw==
|
||||
|
||||
"@babel/template@^7.29.7":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.29.7.tgz#4d9d4004f645cdd304de958c725162784ecac700"
|
||||
@@ -3175,100 +3170,100 @@
|
||||
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.23.0.tgz#8b66dbfa7b796139e719063fc0e44084e80a1c15"
|
||||
integrity sha512-gUGJpr+Rn6zMxm5juApV0K3U845i8t47o8k+rbO0BHbi4PoJIfSPeQmrE2dgohQm2g5k6iviNFyXCGqvmaYUpw==
|
||||
|
||||
"@oxfmt/binding-android-arm-eabi@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.63.0.tgz#136176dc94fdc41e21415cc770d86f5066282e0f"
|
||||
integrity sha512-YmRth4ZPGgEXcgmkhvANbC9uD67dxmSobW7DQuyt5tOBOKvPnIpk5SVHBj88E+7wMNRI2FhqaDbOhQFBix+b8A==
|
||||
"@oxfmt/binding-android-arm-eabi@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.62.0.tgz#3f5b9d3ba944f42ad3fa2697b9fef88a8c9d4ce0"
|
||||
integrity sha512-pdsv0C4gPjJ8H1+sd8u0BDx+yLACTL+rgeMIOL1ln4ihSnhw8CWXtYWgvcSkyTfgGBIzFKab+d8rx9Xl4en/Kw==
|
||||
|
||||
"@oxfmt/binding-android-arm64@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.63.0.tgz#10bc42457179210061c801122a64304619e3bdab"
|
||||
integrity sha512-icbahX8X2X3sRamOMecvdYeZXWjPDazRDIfvWfy7Ca1nc/ZDT2Y9k5Nt7s46EqFd7NQPdgk+CM3/SgIT5LPCaQ==
|
||||
"@oxfmt/binding-android-arm64@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.62.0.tgz#4c7e2c567f645ed051be100318e9e3f716630c1b"
|
||||
integrity sha512-WC3YQ7uS/KtDrjmqwBviwFKe9qeoi+eXx8aX1z/ffG23Md75myjrJaQqTuJvdOLPoa4EYTjDWH0dHXfwulCVog==
|
||||
|
||||
"@oxfmt/binding-darwin-arm64@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.63.0.tgz#5f9084d9a760a1836387f8970a7f9d614ec3d909"
|
||||
integrity sha512-WV+Ze5v5gI2qoj8jpAovt8KBTW8pjEz/AiMXXjeTQS+Bmf/MmZXTS40S8xNPDszX+W8WDv2Bbk6qKrMTtUGu1A==
|
||||
"@oxfmt/binding-darwin-arm64@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.62.0.tgz#6c8007ae65ed17f9d1ecc6c680da19ec19276c67"
|
||||
integrity sha512-GM8Yf3LjjaR1I8PD0SfeoIlwhsh9GvSF+cQ8sf624Yxnjsyumn95aFzYfKJVefblfDIiOAnZ7QVm2sa21Er/0Q==
|
||||
|
||||
"@oxfmt/binding-darwin-x64@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.63.0.tgz#badd4a02218a9a62319817d5c337b30159a54a21"
|
||||
integrity sha512-CJGSBdDxXOWIpoFXHpverimCvz084KA7L483rqJ44c3jDtzv6d4qOSoR/V9ywSHfV+Ks1lwIj2P49BFhunLNAA==
|
||||
"@oxfmt/binding-darwin-x64@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.62.0.tgz#0661a0274e8625921c5a054aeb21a36251946e6b"
|
||||
integrity sha512-d5THp7F8bCxLqNogEXDORRsQD6dosf3EyFtnXfBer6v+8tGdcWIjoDX9WaXrrF/26zOmL8qHpPTKCEvpBDmZkQ==
|
||||
|
||||
"@oxfmt/binding-freebsd-x64@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.63.0.tgz#a17261e95c8ebef1f76d8aaac746a64fdb6ba51e"
|
||||
integrity sha512-BDfKY+KhL2078cgswBBFQPAYuxCy93bS/iC5frdSeSbTLcGrR6VC2hsuPTanoJmg84+wSyWl0wWC1eR+uTnkRg==
|
||||
"@oxfmt/binding-freebsd-x64@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.62.0.tgz#f3345001102ac3e6c2947920d6d1676e9cf97e75"
|
||||
integrity sha512-1DnrtXGZooOZ0fHgAXZUaDQzBVh1CM2MNW4oBXyQ2aWKvCHjyljvT9fgBkOM0fEOb96X5eqtcfJ0YUVt9jj66g==
|
||||
|
||||
"@oxfmt/binding-linux-arm-gnueabihf@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.63.0.tgz#baeee34bb08e0769af878623f442e83bc0aacd7a"
|
||||
integrity sha512-Ov1cQEXT4mj7cojAokWSS1eoxkoyvbDfAbxNsGIKY2o36kvdAaFzPxRN6NxFRk9fD72B8oCoTTX/NuYTUWlpsg==
|
||||
"@oxfmt/binding-linux-arm-gnueabihf@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.62.0.tgz#ddc03bc2a899f2071d6706c06dfdec3a7f3e8b5a"
|
||||
integrity sha512-4pQDHOYRH+Huqe0StIaWyvk2CVl/aTaqSrbZpA3/pLS2xH24ME7lBgYprhQF2fRkHBzhGGGKliwxFsDdHwx59g==
|
||||
|
||||
"@oxfmt/binding-linux-arm-musleabihf@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.63.0.tgz#e70d5697ec4b6bb5f87a3f019e01b3f956b8e44b"
|
||||
integrity sha512-0LE7ro3+6L79jcMANycAZfRaC7zxr9YZ2+vEL5uMD9QlEep+rS/r1kSJsnuLl991NXJZD60euh0PC1GHrR20vw==
|
||||
"@oxfmt/binding-linux-arm-musleabihf@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.62.0.tgz#5e82208d612c4caf64ada75e129e34d1a9eefb2c"
|
||||
integrity sha512-X0jAaZJFMCVKhB6YyWVTQ/wN2DLsBcZKSMqTS76bF6riT+XZdtg2FPEdjDvdVbunO9cG+tWiVaEs4Zs38lxYog==
|
||||
|
||||
"@oxfmt/binding-linux-arm64-gnu@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.63.0.tgz#638a8ed4f3d256c50aeb6d2c19cfc65792c902e1"
|
||||
integrity sha512-izPk+2Z4gjuZK32Fqh5qXoMpT/2NXzLh++ob57HiEiVSQZ1iYXu8EKMzb+K5AvWyIEXhdDIt7ADjGGtFhkT9Bw==
|
||||
"@oxfmt/binding-linux-arm64-gnu@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.62.0.tgz#eb379bc58aa962e753d58b4cc68ff4081bc19a5d"
|
||||
integrity sha512-682Z8T5s8T5ATArYtsejKvbIfd8LEAXyyDkKkoZVq8HND7Vx8TYLlrDjDSeYfodMeVwHOgkj13lJYR8cj6vUSg==
|
||||
|
||||
"@oxfmt/binding-linux-arm64-musl@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.63.0.tgz#af5a9b787f5233f27a3360ad56235fc1b011f760"
|
||||
integrity sha512-alPmbOuWXFXiSo+lOtv6X71C7SYMEDW2WVvywOvf9BwKgEhSNGhMTLeFVSjKUMCamcjbbgVdsWF8GN1uy8xshg==
|
||||
"@oxfmt/binding-linux-arm64-musl@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.62.0.tgz#dc1c62510405e874bf6a53a34f548032eb6dfed7"
|
||||
integrity sha512-lk25fAl7KWaLWVJcW0CHEXB7QlQZtx5eDkjpaGMK0hzXTjUe0Wmlu8IKuFHoviSOcEJedRTs4VE/506VqGxGew==
|
||||
|
||||
"@oxfmt/binding-linux-ppc64-gnu@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.63.0.tgz#c1a211206134a5577e355a495989e0d733218d60"
|
||||
integrity sha512-BdzCPvolJc4AWZ+YMzgUDJcDzbQWrFjYuqBHoNHNqP1aCaluQRJNs4k3vNU5IG7vTpjf9zeD73D7MFM1TecZpg==
|
||||
"@oxfmt/binding-linux-ppc64-gnu@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.62.0.tgz#9f9afee327090024db86b70ec81a57ad06bb2f00"
|
||||
integrity sha512-SFyNqHQLwySceWNLhiSldx7wPXRAzP0L0WcW9GegP3uWrpZGJiZlQO85NbHAFPEfxR9PhZ9qSnZryEh7+v+4Gw==
|
||||
|
||||
"@oxfmt/binding-linux-riscv64-gnu@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.63.0.tgz#4863f0311e5c1b88f75ef822959b3ca4fd938937"
|
||||
integrity sha512-7sIgfLzqtNKSkMGsGVyRpHwpjNezRg2XONvUOheFZs95TSZpM0JAuPpA8KrQFsWc4wPU95roX2O69JgH8igOgw==
|
||||
"@oxfmt/binding-linux-riscv64-gnu@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.62.0.tgz#4427d42ee3bad0e55b38dc76fe14a7e5318c360c"
|
||||
integrity sha512-KYj55C1ywJfHo6+aKDuEmUtVEdJALsC5GwayDGsI6FGz2GxFqNr/mA8nxVsNbJzm7sE5MRqTQ9ziImSzhYXysA==
|
||||
|
||||
"@oxfmt/binding-linux-riscv64-musl@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.63.0.tgz#ad05a017d12553e2f544743c4940adb552aa1d1c"
|
||||
integrity sha512-9Tcg0y0WcVa6Mm9AgcgFMseDS+VkFJZpKZ8We9SpDY4gg5jewSwln+0sO04QLcTS1BtfDl9MwR+NfID8L7PUTg==
|
||||
"@oxfmt/binding-linux-riscv64-musl@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.62.0.tgz#a117f82909f075cf07c333842d89a5638429e21d"
|
||||
integrity sha512-BhZDNo5GOU5nC378RhD0/XpvaEBHsH3HLgJp8YZX3A0InC7oivzA63HsRmiXFLtLSHAstEVrDf6fbC7Rs8Jh/A==
|
||||
|
||||
"@oxfmt/binding-linux-s390x-gnu@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.63.0.tgz#2803f539db15bc66db115888fa8f84d6531ed2b9"
|
||||
integrity sha512-qWKC1pEOpx1qYhXaugPhHUeXwSfqEOk2wJH2LqVXGPV5iQYfdAZdt+d2XDiX4DTSWA2QDMUcFB+wEORh3Xn/sA==
|
||||
"@oxfmt/binding-linux-s390x-gnu@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.62.0.tgz#3fac79fefe7ffc3f0a9393678ebd782aac918fcd"
|
||||
integrity sha512-UyAFmyHkgSgUJ/wOM4p3U8AC2yAFvRH5PNBs7TnK0fObTT/XSWcdr/lAzPSWaekHaZFaMeFZyk9n93Joq3J93A==
|
||||
|
||||
"@oxfmt/binding-linux-x64-gnu@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.63.0.tgz#c22a06a60ae2d6b3de522095e0c50a816040a033"
|
||||
integrity sha512-S9wXYOiGSqYGS4Fx/TFsY+xDd/7dE5s+rUgbA4TsHiVF9e8J3ZcKmP7dsP/7iqLI9Wz7Ic7TzEr3mdthRCTdrA==
|
||||
"@oxfmt/binding-linux-x64-gnu@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.62.0.tgz#8da207bef27941f0265c129d1c7c82c7cf91d1ce"
|
||||
integrity sha512-1iYMP0leytWazFubD/WnINJuIrzRPuoL1aWEJdlGezEzDbTxcd29R4r8IUzP2oWeKst5V02uMJgR2NILlPlG6w==
|
||||
|
||||
"@oxfmt/binding-linux-x64-musl@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.63.0.tgz#48d3eeaf8e3757f638cf92de5ee4858befc9c0a3"
|
||||
integrity sha512-5eGyTJuMZNwBSHCivXt8Yuta6GeTYksOPXRk2MIhajiyFGQx7bjaHIwY+ZusAoFHhT157A9x6sktLjYo9D5oMQ==
|
||||
"@oxfmt/binding-linux-x64-musl@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.62.0.tgz#e55cf9b7c8c2204fdbb5d4818f8c5ba02aa49360"
|
||||
integrity sha512-4rA/URtJSTVNVAQz6Q8wf7SaRvOXVy+TizriT9hs/Y1XhLR/R+92uWKRQG8yFWRAIEBbFHJ6WevQcl/G9SXEfw==
|
||||
|
||||
"@oxfmt/binding-openharmony-arm64@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.63.0.tgz#02be9e140ae35ba30f52bdce27612fece4a01ab3"
|
||||
integrity sha512-Rz7hx+Dv3DoW/S6pwVAyjfFXp7/trdQ1zg+vNmsdsdDNlUccugp4XNqambSuEAeP0DaG9k72AtNyfDXCEg0AGw==
|
||||
"@oxfmt/binding-openharmony-arm64@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.62.0.tgz#4998769ee1b5894efcd6cb99729d5a75f4c09dd1"
|
||||
integrity sha512-mSZuFHU2ar1KLUjXpI2QBQcJ1VsOB3mOCgQXuXCpKs19dgh4u+OaovNfrWDfiJb+ihJ2+f7YFcaO9bS2dlTCXA==
|
||||
|
||||
"@oxfmt/binding-win32-arm64-msvc@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.63.0.tgz#2226eaf52b6345a2cb926499216b2486cf0dbec2"
|
||||
integrity sha512-T/IuizKN9mr4Xw6YYnptkXRNdLkyIlUZ7c8zfTOBpoytZyJ1BAsMUvsMDEx0X4YvSMpaivm+DR8112rQfzC25g==
|
||||
"@oxfmt/binding-win32-arm64-msvc@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.62.0.tgz#e09eaabdde76c885c4f8a190518c2eb2de08548a"
|
||||
integrity sha512-OfwuhkcjDlqC4EgDojtiV9mzpLqeB9KqTOWPOjLEYBVdDCVSxqW3qzp/xcIxsbtI0UgGCnKvAqYKyY25kf5JZw==
|
||||
|
||||
"@oxfmt/binding-win32-ia32-msvc@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.63.0.tgz#58d263bb5ecd7330c02f9dcd8cda10f66e42e74b"
|
||||
integrity sha512-XjrO5FJ5Wl9vsAxtCP1G/eaeT6y1K2s9CICUHGE42cEjou32/J6S+B1KnrOAboj6E7uhJnwPbRSvznWcxNdA0g==
|
||||
"@oxfmt/binding-win32-ia32-msvc@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.62.0.tgz#f36e306308923977365270d8b26290f4ca2fcfa5"
|
||||
integrity sha512-P9uDDNFRzghO3X8QAzhkjKhK7JvtABsVn8UYtFX7uor12IAnwNt8nNIctvfWj1JkQU/kE+fmLRPiw7XlrIHsZw==
|
||||
|
||||
"@oxfmt/binding-win32-x64-msvc@0.63.0":
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.63.0.tgz#02a166c8a8049c55d0096d1ba9d8e73f3a4d26a7"
|
||||
integrity sha512-sgsHCQy432OTQH4Ikk3tZptp3GqwnhwUDuY0loBH41zyHWfMZY9v8Dy78wsnSofHejvFozZGgJgBB1A0LQRwMQ==
|
||||
"@oxfmt/binding-win32-x64-msvc@0.62.0":
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.62.0.tgz#bb6545e581d5ee7111084dbabeec7fe548bae418"
|
||||
integrity sha512-dlI5SY7XYQCiCBafntWagCR6HcAJB/NpsLtdlPx8x08+Osz8Ok1HHz1GZuusegCe/VoJ6pAnF5a4pd5OZAq7qQ==
|
||||
|
||||
"@parcel/watcher-android-arm64@2.5.6":
|
||||
version "2.5.6"
|
||||
@@ -3537,13 +3532,13 @@
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.24.4"
|
||||
|
||||
"@rc-component/cascader@~1.22.0":
|
||||
version "1.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/cascader/-/cascader-1.22.0.tgz#eec0b6f4d2df5903aa12cfed321a578705926937"
|
||||
integrity sha512-SffrA57aS9oub3VuI7ajPhJTPtaNxngSvtRhD40Rd8dwJ5vfWPSrVanWgeepdWFGBt7EHftIK5RUU0u3rCTwWw==
|
||||
"@rc-component/cascader@~1.17.0":
|
||||
version "1.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/cascader/-/cascader-1.17.0.tgz#52c0eceada2c7b4b37ebe822c19a6544b9562edf"
|
||||
integrity sha512-3cVNG0zrQF1PoXq262L3wGCU+/YLEC1mGSVHDl577dQmA0ZKkXFbY6nwyXo+beCcM7buo49t24jkr+QZdL7O8w==
|
||||
dependencies:
|
||||
"@rc-component/select" "~1.10.0"
|
||||
"@rc-component/tree" "~1.4.0"
|
||||
"@rc-component/select" "~1.8.0"
|
||||
"@rc-component/tree" "~1.3.2"
|
||||
"@rc-component/util" "^1.11.1"
|
||||
clsx "^2.1.1"
|
||||
|
||||
@@ -3619,14 +3614,14 @@
|
||||
"@rc-component/util" "^1.11.1"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/image@~1.10.0":
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/image/-/image-1.10.0.tgz#5d7a82d20e4c91f75875ea64eb1dadd7af676b1d"
|
||||
integrity sha512-BjeZCRQ+hw+4WAhvrw8rJvy5fckA2xpf/X2XQEOABUHvLTNB9inB98X3Mp54jYQ7g10DfWERQWHXeC4ylxp1Uw==
|
||||
"@rc-component/image@~1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/image/-/image-1.9.0.tgz#110785d735d20336afcdbac84e8fbfd059a7a44e"
|
||||
integrity sha512-khF7w7xkBH5B1bsBcI1FSUZdkyd1aqpl2eYyILCqCzzQH3XdfehGUaZTnptyaJJfs09/R5hv9jXWyazOMFIClQ==
|
||||
dependencies:
|
||||
"@rc-component/motion" "^1.0.0"
|
||||
"@rc-component/portal" "^2.1.2"
|
||||
"@rc-component/util" "^1.11.1"
|
||||
"@rc-component/util" "^1.10.1"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/input-number@~1.6.2":
|
||||
@@ -3638,7 +3633,7 @@
|
||||
"@rc-component/util" "^1.4.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/input@~1.3.1":
|
||||
"@rc-component/input@~1.3.0", "@rc-component/input@~1.3.1":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/input/-/input-1.3.1.tgz#230b8b59cdde8521d50f0eede63ddacb61cc0cd3"
|
||||
integrity sha512-iFvTUT9W+JC/MSin2aGAk8NqsVlTzcExNC9DZariON1IWirju9NoNeEk47an4Q8iHazkoVI/y1LnDi88+CPcig==
|
||||
@@ -3647,27 +3642,15 @@
|
||||
"@rc-component/util" "^1.11.1"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/listy@~1.2.3":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/listy/-/listy-1.2.3.tgz#e9c8ef4f409c231b44dded37e63ae2875bbe0334"
|
||||
integrity sha512-IXiMjV5s0rczLBlfh7G5nB4M3365mrEeedjwKtf5I+Ns3PqRUsebR2h5u8CeFarsVfLUPC2I5p0h09TNoOWyvQ==
|
||||
"@rc-component/mentions@~1.10.0":
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/mentions/-/mentions-1.10.0.tgz#46b1117cfb0c716b476e97f342555eccc2f41c97"
|
||||
integrity sha512-CI1njYUVY0NjHtLhNoVmXlJyy568Sfep9Wsak6vmGjtT6uazx98djGYlCXz2xkHhEm73g91Y3MTvzUyE5avI7w==
|
||||
dependencies:
|
||||
"@rc-component/motion" "^1.1.4"
|
||||
"@rc-component/portal" "^2.0.0"
|
||||
"@rc-component/resize-observer" "^1.0.0"
|
||||
"@rc-component/util" "^1.3.1"
|
||||
"@rc-component/virtual-list" "^1.4.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/mentions@~1.11.0":
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/mentions/-/mentions-1.11.0.tgz#cee0c4710f26766ad8550d386cfec5ff86fd58d9"
|
||||
integrity sha512-IC2qXuEBMFHxPIXEFfYWj6Sr7UiDZnOqJHCYQBbwPzopBJOPZIR6mV9U4QH1bYQRlKYlYnIsajWDMgVGgWQyWQ==
|
||||
dependencies:
|
||||
"@rc-component/input" "~1.3.1"
|
||||
"@rc-component/input" "~1.3.0"
|
||||
"@rc-component/menu" "~1.4.0"
|
||||
"@rc-component/trigger" "^3.0.0"
|
||||
"@rc-component/util" "^1.11.1"
|
||||
"@rc-component/util" "^1.3.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/menu@~1.4.0", "@rc-component/menu@~1.4.1":
|
||||
@@ -3741,7 +3724,7 @@
|
||||
"@rc-component/util" "^1.11.1"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/portal@^2.0.0", "@rc-component/portal@^2.1.0", "@rc-component/portal@^2.1.2", "@rc-component/portal@^2.1.3", "@rc-component/portal@^2.2.0", "@rc-component/portal@^2.2.1":
|
||||
"@rc-component/portal@^2.1.0", "@rc-component/portal@^2.1.2", "@rc-component/portal@^2.1.3", "@rc-component/portal@^2.2.0", "@rc-component/portal@^2.2.1":
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/portal/-/portal-2.2.1.tgz#37c34b4c8cd73f53cc7072c96dd0e9ac332669ec"
|
||||
integrity sha512-ck+r1kW/JSv0wxPji3KN2ss9K6Z0qqwusw/mf/0JobXhZ8hC2ejZwCJObW/SvDi0uhA0VzmCnx0CaCci95tcmA==
|
||||
@@ -3789,10 +3772,10 @@
|
||||
"@rc-component/util" "^1.3.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/select@~1.10.0":
|
||||
version "1.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/select/-/select-1.10.1.tgz#323b2f458a637e8e752f8341094783741c613c34"
|
||||
integrity sha512-H+yQsl+qED9NilQ3g6zdpsMwUgwVjrcMTkNHAWRVU/MoNCYgTbDgU+MIMgZDK+rVdd2JUfI/MkysMcZZ0cyQKw==
|
||||
"@rc-component/select@~1.8.0", "@rc-component/select@~1.8.2":
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/select/-/select-1.8.2.tgz#f016992dae5c57186535512d73783e2fc7e4c59e"
|
||||
integrity sha512-HQ9zuYqjfZTlcEMWlU1GAPBajd2OHIMVHyjZSGVTCVARwkfCgvXZMTEn0cduy3L+ejAKkaZluOQvxovZoaJaQw==
|
||||
dependencies:
|
||||
"@rc-component/overflow" "^1.0.0"
|
||||
"@rc-component/trigger" "^3.0.0"
|
||||
@@ -3824,10 +3807,10 @@
|
||||
"@rc-component/util" "^1.3.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/table@~1.11.0":
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/table/-/table-1.11.1.tgz#7b5c2a7c26fd37b6a403082029b5a72fcb330a4d"
|
||||
integrity sha512-OWdS6DMmeWb7bJBGqPxYZpQbzBlBiXZUu2sqo6Ii7Sjs9GeK1IsrXrWk26SL2c6KEseabswdxrRj7WUm9LdECw==
|
||||
"@rc-component/table@~1.10.4":
|
||||
version "1.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/table/-/table-1.10.4.tgz#8c4e33bc150aa39f579c15426421348a789de326"
|
||||
integrity sha512-HwoTnrwc29zeoXkXGhWqzJh8FIibGUxi1jM4LtoSzmR9d5Vv5osUQpZxnXKBP8iOCvyD6BQzZm1nXJRcnrxpAg==
|
||||
dependencies:
|
||||
"@rc-component/context" "^2.0.1"
|
||||
"@rc-component/resize-observer" "^1.0.0"
|
||||
@@ -3835,10 +3818,10 @@
|
||||
"@rc-component/virtual-list" "^1.0.1"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/tabs@~1.12.0":
|
||||
version "1.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/tabs/-/tabs-1.12.0.tgz#41a1a77ed1afc4f1b8b727003a058c631aceea1b"
|
||||
integrity sha512-XL7Kqy5fnUE2WTlO1/fCGrrfNlGFebdr7JseGkEIjzcVMAtIFQJ8sqCSOmxcXstjU6fonD/4rnhZHxj7sDTajQ==
|
||||
"@rc-component/tabs@~1.11.0":
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/tabs/-/tabs-1.11.0.tgz#c157b2fadcdc2f3ab6c69d0098f73e03c6aa0c12"
|
||||
integrity sha512-hA/drZYOVa/MMIb4M2fWf3yaTyTG4qVuIABmghvEhyfw2nBob5VTH69lMCDjSVKmgODjO6nWlCV+gVn3xBrj5Q==
|
||||
dependencies:
|
||||
"@rc-component/dropdown" "~1.0.0"
|
||||
"@rc-component/menu" "~1.4.0"
|
||||
@@ -3847,13 +3830,13 @@
|
||||
"@rc-component/util" "^1.11.1"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/tooltip@~1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/tooltip/-/tooltip-1.5.0.tgz#422aa0760b310e0a1d0f9f7223e7f0d455de57a2"
|
||||
integrity sha512-agQ/+mBqrEQfTX4D3KhQ7j+ZbX4/VHjoJ7Noa2wIdZ1/FbQTOd7Sn92rp+jtCoqAVTLUgSOydePIgZ204gi2EQ==
|
||||
"@rc-component/tooltip@~1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/tooltip/-/tooltip-1.4.0.tgz#c8cf15c6773218a5a36271467f06e663f99c28e7"
|
||||
integrity sha512-8Rx5DCctIlLI4raR0I0xHjVTf1aF48+gKCNeAAo5bmF5VoR5YED+A/XEqzXv9KKqrJDRcd3Wndpxh2hyzrTtSg==
|
||||
dependencies:
|
||||
"@rc-component/trigger" "^3.10.0"
|
||||
"@rc-component/util" "^1.11.1"
|
||||
"@rc-component/trigger" "^3.7.1"
|
||||
"@rc-component/util" "^1.3.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/tour@~2.4.0":
|
||||
@@ -3866,27 +3849,27 @@
|
||||
"@rc-component/util" "^1.7.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/tree-select@~1.16.0":
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/tree-select/-/tree-select-1.16.1.tgz#dcaea96e396e98108cb29cc051840d4fbdda38cc"
|
||||
integrity sha512-a1Oi6EJhqAhdOxxupdJi6fP0RPHMKn5TcfkX2+llaQ4lF4nwfH7b6SCHcnsybaa2s+pk1yZYwVyeOYkDnEBRdg==
|
||||
"@rc-component/tree-select@~1.11.0":
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/tree-select/-/tree-select-1.11.0.tgz#9080cdf1d28f2ddd6d8a4879b7aa90d3170f7db9"
|
||||
integrity sha512-EhS0X0wtUhBfK4S5TlpSY3MR9ndPMGgujtt1PJW3Ej+ToAlnS/6ohYURtCoXBYGqazUwHmgQGVUDsfpVwhWPkg==
|
||||
dependencies:
|
||||
"@rc-component/select" "~1.10.0"
|
||||
"@rc-component/tree" "~1.4.0"
|
||||
"@rc-component/select" "~1.8.0"
|
||||
"@rc-component/tree" "~1.3.2"
|
||||
"@rc-component/util" "^1.11.1"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/tree@~1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/tree/-/tree-1.4.0.tgz#c0031180e681389bf0bdcb867a0087525b45c8a9"
|
||||
integrity sha512-dGsJGDJQedA0BqqVgj3F8BvHXTSZijyhTXdbAdkcx8lynzZkty/CV3Z3LOm/fxz+BCfl3dfGiAQpb7Q5XNvl0Q==
|
||||
"@rc-component/tree@~1.3.2":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/tree/-/tree-1.3.2.tgz#4b0c13564314eff61ca948c18ef923b87c9d7e44"
|
||||
integrity sha512-bJFj46wEkpBPnWyTm18XmgAgNQ/4YvprxMOPPY2a6rmhGJYxLuNKEFiL5Qej4Qctu9wHJm8WW+v2SYskafE0kA==
|
||||
dependencies:
|
||||
"@rc-component/motion" "^1.0.0"
|
||||
"@rc-component/util" "^1.11.1"
|
||||
"@rc-component/virtual-list" "^1.2.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/trigger@^3.0.0", "@rc-component/trigger@^3.10.0", "@rc-component/trigger@^3.10.1", "@rc-component/trigger@^3.6.15":
|
||||
"@rc-component/trigger@^3.0.0", "@rc-component/trigger@^3.10.1", "@rc-component/trigger@^3.6.15", "@rc-component/trigger@^3.7.1":
|
||||
version "3.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/trigger/-/trigger-3.10.1.tgz#cb28e1bc0745a2af6897dd7ec774f9b56dc88f86"
|
||||
integrity sha512-mXlDN0IXdtV8Yqqm8195ECCyrbmfvvfKvwVvSlH0+qvKD6BUF8gRhEjSy0FOcD1+CcDRHgTiX99LoxfQrmh3Cw==
|
||||
@@ -3905,7 +3888,7 @@
|
||||
"@rc-component/util" "^1.11.1"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/util@^1.11.0", "@rc-component/util@^1.11.1", "@rc-component/util@^1.12.0", "@rc-component/util@^1.2.0", "@rc-component/util@^1.2.1", "@rc-component/util@^1.3.0", "@rc-component/util@^1.3.1", "@rc-component/util@^1.4.0", "@rc-component/util@^1.7.0", "@rc-component/util@^1.9.0":
|
||||
"@rc-component/util@^1.10.1", "@rc-component/util@^1.11.0", "@rc-component/util@^1.11.1", "@rc-component/util@^1.12.0", "@rc-component/util@^1.2.0", "@rc-component/util@^1.2.1", "@rc-component/util@^1.3.0", "@rc-component/util@^1.4.0", "@rc-component/util@^1.7.0", "@rc-component/util@^1.9.0":
|
||||
version "1.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/util/-/util-1.12.0.tgz#58e453585810bcb8a35ff1aafd5e01187457b86f"
|
||||
integrity sha512-AEjPL8JVdohIITaiXokyjL9WQ6tKWWjAYK9QU16tGNE9JaQABBQy+hA4H2Lup5MgXy9yY3iLrbZJheuU13hTdQ==
|
||||
@@ -3923,16 +3906,6 @@
|
||||
"@rc-component/util" "^1.4.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@rc-component/virtual-list@^1.4.0":
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@rc-component/virtual-list/-/virtual-list-1.5.1.tgz#71c5844a8d6bd5b3501dfb66419d3a4612b2bb18"
|
||||
integrity sha512-boqHxdtyWC88u8quYgEO49bcBy5fzRiOcnBge+N4nLzs2k8hUQ/yw7JE9dM6yCBE4jSm5YSHVCVMS+suBuJGKA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^8.0.0"
|
||||
"@rc-component/resize-observer" "^1.0.1"
|
||||
"@rc-component/util" "^1.4.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@redocly/ajv@^8.18.1":
|
||||
version "8.18.3"
|
||||
resolved "https://registry.yarnpkg.com/@redocly/ajv/-/ajv-8.18.3.tgz#a925753d9a33375219f1b2ba91aef320f9929577"
|
||||
@@ -5685,100 +5658,110 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@8.67.0", "@typescript-eslint/eslint-plugin@^8.67.0":
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.67.0.tgz#52f9f0e47d5a7571c4336e69bfeea581509ef2cf"
|
||||
integrity sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==
|
||||
"@typescript-eslint/eslint-plugin@8.66.0", "@typescript-eslint/eslint-plugin@^8.66.0":
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.66.0.tgz#76e86aa5a2459fbf5bbd7a839c0dc0cce1d56224"
|
||||
integrity sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.12.2"
|
||||
"@typescript-eslint/scope-manager" "8.67.0"
|
||||
"@typescript-eslint/type-utils" "8.67.0"
|
||||
"@typescript-eslint/utils" "8.67.0"
|
||||
"@typescript-eslint/visitor-keys" "8.67.0"
|
||||
"@typescript-eslint/scope-manager" "8.66.0"
|
||||
"@typescript-eslint/type-utils" "8.66.0"
|
||||
"@typescript-eslint/utils" "8.66.0"
|
||||
"@typescript-eslint/visitor-keys" "8.66.0"
|
||||
ignore "^7.0.5"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/parser@8.67.0", "@typescript-eslint/parser@^8.67.0":
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.67.0.tgz#0158022ec9927e0afcd58a8cc2ad57e01d892f5c"
|
||||
integrity sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==
|
||||
"@typescript-eslint/parser@8.66.0", "@typescript-eslint/parser@^8.66.0":
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.66.0.tgz#88e3865ecf73b0118134e7cb831da87a961a57a1"
|
||||
integrity sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.67.0"
|
||||
"@typescript-eslint/types" "8.67.0"
|
||||
"@typescript-eslint/typescript-estree" "8.67.0"
|
||||
"@typescript-eslint/visitor-keys" "8.67.0"
|
||||
"@typescript-eslint/scope-manager" "8.66.0"
|
||||
"@typescript-eslint/types" "8.66.0"
|
||||
"@typescript-eslint/typescript-estree" "8.66.0"
|
||||
"@typescript-eslint/visitor-keys" "8.66.0"
|
||||
debug "^4.4.3"
|
||||
|
||||
"@typescript-eslint/project-service@8.67.0":
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.67.0.tgz#1552db007ca9206a1c6c7acf49e210bd17a8c56f"
|
||||
integrity sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==
|
||||
"@typescript-eslint/project-service@8.66.0":
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.66.0.tgz#828f788895df52d9eb2b543445a3a5a13e35ab4e"
|
||||
integrity sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==
|
||||
dependencies:
|
||||
"@typescript-eslint/tsconfig-utils" "^8.67.0"
|
||||
"@typescript-eslint/types" "^8.67.0"
|
||||
"@typescript-eslint/tsconfig-utils" "^8.66.0"
|
||||
"@typescript-eslint/types" "^8.66.0"
|
||||
debug "^4.4.3"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.67.0":
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.67.0.tgz#4d4c2da09560d10dd7d947cba2d29d14d25af16d"
|
||||
integrity sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==
|
||||
"@typescript-eslint/scope-manager@8.66.0":
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.66.0.tgz#4fffcc6ebd0df9fe7983c0256967567ea6f5ac63"
|
||||
integrity sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.67.0"
|
||||
"@typescript-eslint/visitor-keys" "8.67.0"
|
||||
"@typescript-eslint/types" "8.66.0"
|
||||
"@typescript-eslint/visitor-keys" "8.66.0"
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@8.67.0", "@typescript-eslint/tsconfig-utils@^8.67.0":
|
||||
"@typescript-eslint/tsconfig-utils@8.66.0":
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.66.0.tgz#3a89066c507aa30541dc176804685b4b444e1e52"
|
||||
integrity sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@^8.66.0":
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz#f45a3eba6b9132fb47141ec03ce2f275f1ea991d"
|
||||
integrity sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==
|
||||
|
||||
"@typescript-eslint/type-utils@8.67.0":
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.67.0.tgz#96bed105275559df3bcf0449b73a6414d35c59ce"
|
||||
integrity sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==
|
||||
"@typescript-eslint/type-utils@8.66.0":
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.66.0.tgz#b2315303eca72fad9afa7be4f58f053c8f2a0479"
|
||||
integrity sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.67.0"
|
||||
"@typescript-eslint/typescript-estree" "8.67.0"
|
||||
"@typescript-eslint/utils" "8.67.0"
|
||||
"@typescript-eslint/types" "8.66.0"
|
||||
"@typescript-eslint/typescript-estree" "8.66.0"
|
||||
"@typescript-eslint/utils" "8.66.0"
|
||||
debug "^4.4.3"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/types@8.67.0", "@typescript-eslint/types@^8.67.0":
|
||||
"@typescript-eslint/types@8.66.0":
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.66.0.tgz#3cacab94d3b564c1d48c56eb37b89f89a6d48479"
|
||||
integrity sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==
|
||||
|
||||
"@typescript-eslint/types@^8.66.0":
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.67.0.tgz#4a8d00cc1faba5c14feabc60f85b7a32652f34b6"
|
||||
integrity sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.67.0":
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz#116c3a47c06119c5a050e8851861d6497dd64bc2"
|
||||
integrity sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==
|
||||
"@typescript-eslint/typescript-estree@8.66.0":
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.66.0.tgz#1a38c3a97dc6c669b66d585d7f90ebc4fbb32a50"
|
||||
integrity sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==
|
||||
dependencies:
|
||||
"@typescript-eslint/project-service" "8.67.0"
|
||||
"@typescript-eslint/tsconfig-utils" "8.67.0"
|
||||
"@typescript-eslint/types" "8.67.0"
|
||||
"@typescript-eslint/visitor-keys" "8.67.0"
|
||||
"@typescript-eslint/project-service" "8.66.0"
|
||||
"@typescript-eslint/tsconfig-utils" "8.66.0"
|
||||
"@typescript-eslint/types" "8.66.0"
|
||||
"@typescript-eslint/visitor-keys" "8.66.0"
|
||||
debug "^4.4.3"
|
||||
minimatch "^10.2.2"
|
||||
semver "^7.7.3"
|
||||
tinyglobby "^0.2.15"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/utils@8.67.0":
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.67.0.tgz#3e478a3d69d330a1fc50c12746cc2ee0732ccfcd"
|
||||
integrity sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==
|
||||
"@typescript-eslint/utils@8.66.0":
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.66.0.tgz#e277d67427043cdca2580ee91aa62921e4689969"
|
||||
integrity sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.9.1"
|
||||
"@typescript-eslint/scope-manager" "8.67.0"
|
||||
"@typescript-eslint/types" "8.67.0"
|
||||
"@typescript-eslint/typescript-estree" "8.67.0"
|
||||
"@typescript-eslint/scope-manager" "8.66.0"
|
||||
"@typescript-eslint/types" "8.66.0"
|
||||
"@typescript-eslint/typescript-estree" "8.66.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.67.0":
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.67.0.tgz#601d40af9acf82a28da2286f3edafc69bba9017f"
|
||||
integrity sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==
|
||||
"@typescript-eslint/visitor-keys@8.66.0":
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.66.0.tgz#4c494e94745fb2724a4f37a310091e56b644d18a"
|
||||
integrity sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.67.0"
|
||||
"@typescript-eslint/types" "8.66.0"
|
||||
eslint-visitor-keys "^5.0.0"
|
||||
|
||||
"@ungap/structured-clone@^1.0.0":
|
||||
@@ -6181,10 +6164,10 @@ ansis@^3.2.0:
|
||||
resolved "https://registry.yarnpkg.com/ansis/-/ansis-3.17.0.tgz#fa8d9c2a93fe7d1177e0c17f9eeb562a58a832d7"
|
||||
integrity sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==
|
||||
|
||||
antd@^6.6.0:
|
||||
version "6.6.0"
|
||||
resolved "https://registry.yarnpkg.com/antd/-/antd-6.6.0.tgz#8acb84c54b36594b5c1a9084c8acb6a03b79961b"
|
||||
integrity sha512-UDwWIbpmrCHB9ZQ+bPh4vQfB6DTI2ulIyoQ0Tc9xxalFblttiNGHl3ySBD9SyV/8+gUjFzfSx1+iU1Fog2i46w==
|
||||
antd@^6.5.4:
|
||||
version "6.5.4"
|
||||
resolved "https://registry.yarnpkg.com/antd/-/antd-6.5.4.tgz#b41665e86a5f46ca761abd3b0abef7460116ca0d"
|
||||
integrity sha512-jchA6i0rEwHjLpgC+l6HeLHP0gL4Q4yjs6Mxqt6PlhGD5ArxCj3ZH+fKFbNquCtd6Rlzzi+emfNFpP2dGLwZzg==
|
||||
dependencies:
|
||||
"@ant-design/colors" "^8.0.1"
|
||||
"@ant-design/cssinjs" "^2.1.2"
|
||||
@@ -6193,7 +6176,7 @@ antd@^6.6.0:
|
||||
"@ant-design/icons" "^6.3.2"
|
||||
"@ant-design/react-slick" "~2.0.0"
|
||||
"@babel/runtime" "^7.29.2"
|
||||
"@rc-component/cascader" "~1.22.0"
|
||||
"@rc-component/cascader" "~1.17.0"
|
||||
"@rc-component/checkbox" "~2.0.0"
|
||||
"@rc-component/collapse" "~1.2.0"
|
||||
"@rc-component/color-picker" "~3.1.1"
|
||||
@@ -6201,11 +6184,10 @@ antd@^6.6.0:
|
||||
"@rc-component/drawer" "~1.4.2"
|
||||
"@rc-component/dropdown" "~1.0.3"
|
||||
"@rc-component/form" "~1.8.6"
|
||||
"@rc-component/image" "~1.10.0"
|
||||
"@rc-component/image" "~1.9.0"
|
||||
"@rc-component/input" "~1.3.1"
|
||||
"@rc-component/input-number" "~1.6.2"
|
||||
"@rc-component/listy" "~1.2.3"
|
||||
"@rc-component/mentions" "~1.11.0"
|
||||
"@rc-component/mentions" "~1.10.0"
|
||||
"@rc-component/menu" "~1.4.1"
|
||||
"@rc-component/motion" "^1.3.3"
|
||||
"@rc-component/mutate-observer" "^2.0.1"
|
||||
@@ -6217,16 +6199,16 @@ antd@^6.6.0:
|
||||
"@rc-component/rate" "~1.0.1"
|
||||
"@rc-component/resize-observer" "^1.1.2"
|
||||
"@rc-component/segmented" "~1.3.0"
|
||||
"@rc-component/select" "~1.10.0"
|
||||
"@rc-component/select" "~1.8.2"
|
||||
"@rc-component/slider" "~1.1.1"
|
||||
"@rc-component/steps" "~1.2.2"
|
||||
"@rc-component/switch" "~1.0.3"
|
||||
"@rc-component/table" "~1.11.0"
|
||||
"@rc-component/tabs" "~1.12.0"
|
||||
"@rc-component/tooltip" "~1.5.0"
|
||||
"@rc-component/table" "~1.10.4"
|
||||
"@rc-component/tabs" "~1.11.0"
|
||||
"@rc-component/tooltip" "~1.4.0"
|
||||
"@rc-component/tour" "~2.4.0"
|
||||
"@rc-component/tree" "~1.4.0"
|
||||
"@rc-component/tree-select" "~1.16.0"
|
||||
"@rc-component/tree" "~1.3.2"
|
||||
"@rc-component/tree-select" "~1.11.0"
|
||||
"@rc-component/trigger" "^3.10.1"
|
||||
"@rc-component/upload" "~1.1.1"
|
||||
"@rc-component/util" "^1.12.0"
|
||||
@@ -6522,10 +6504,10 @@ base64-js@^1.3.1, base64-js@^1.5.1:
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
baseline-browser-mapping@^2.10.38, baseline-browser-mapping@^2.11.13, baseline-browser-mapping@^2.9.19:
|
||||
version "2.11.13"
|
||||
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz#660073103c1bee93e54df55f117b7528adf6af19"
|
||||
integrity sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ==
|
||||
baseline-browser-mapping@^2.10.38, baseline-browser-mapping@^2.11.12, baseline-browser-mapping@^2.9.19:
|
||||
version "2.11.12"
|
||||
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.12.tgz#42ac48770bf73d292f60ce8ba4dc5e7ebb242ec3"
|
||||
integrity sha512-r7WnVImvVCeFpf2DOXfy41aPWzeNg3H/A2X4dKmy1QL0MSyyk/e7z8ihJ3N6Nn2PsdhkVlqnEfnUE4a05P2aTA==
|
||||
|
||||
batch@0.6.1:
|
||||
version "0.6.1"
|
||||
@@ -6763,10 +6745,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.30001799, caniuse-lite@^1.0.30001809:
|
||||
version "1.0.30001809"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz#e6cf71f14ddfe008f114dd2a846923be3c03a07b"
|
||||
integrity sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001799, caniuse-lite@^1.0.30001807:
|
||||
version "1.0.30001807"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001807.tgz#a113854941fb45b4c1f51793f4636920489079b4"
|
||||
integrity sha512-daRXJ9EB/rdRgu7kV+TTl1YUKtlsMWblPl2sLnpg9DZae16QCegol6A1SmCE31Lm9mXC1sRWGt/krouH+/dl7Q==
|
||||
|
||||
ccount@^2.0.0:
|
||||
version "2.0.1"
|
||||
@@ -12262,32 +12244,32 @@ oxc-resolver@^11.19.1:
|
||||
"@oxc-resolver/binding-win32-arm64-msvc" "11.23.0"
|
||||
"@oxc-resolver/binding-win32-x64-msvc" "11.23.0"
|
||||
|
||||
oxfmt@^0.63.0:
|
||||
version "0.63.0"
|
||||
resolved "https://registry.yarnpkg.com/oxfmt/-/oxfmt-0.63.0.tgz#c7338e6c43a68d5cf8dc61c08b617d77cb54e323"
|
||||
integrity sha512-kgdDwv35wvVf6554U2Ab8Jnd0zTM+TsEQWwaB70RAjK3gICFAFGO+2Hd3Be27GMoXj3XRL9IKSNRVl7KBQL6iw==
|
||||
oxfmt@^0.62.0:
|
||||
version "0.62.0"
|
||||
resolved "https://registry.yarnpkg.com/oxfmt/-/oxfmt-0.62.0.tgz#9945728022d26dc0a1d5bc486db112e7e340507a"
|
||||
integrity sha512-vxgGHTmnDU9j4CX7dDBLzxgmHxfda/yPcgJkGCMUSCwRmz+euo/V08xXLNgXTeqAB9Fhf3Pe2nO1RNKLCVgphQ==
|
||||
dependencies:
|
||||
tinypool "2.1.0"
|
||||
optionalDependencies:
|
||||
"@oxfmt/binding-android-arm-eabi" "0.63.0"
|
||||
"@oxfmt/binding-android-arm64" "0.63.0"
|
||||
"@oxfmt/binding-darwin-arm64" "0.63.0"
|
||||
"@oxfmt/binding-darwin-x64" "0.63.0"
|
||||
"@oxfmt/binding-freebsd-x64" "0.63.0"
|
||||
"@oxfmt/binding-linux-arm-gnueabihf" "0.63.0"
|
||||
"@oxfmt/binding-linux-arm-musleabihf" "0.63.0"
|
||||
"@oxfmt/binding-linux-arm64-gnu" "0.63.0"
|
||||
"@oxfmt/binding-linux-arm64-musl" "0.63.0"
|
||||
"@oxfmt/binding-linux-ppc64-gnu" "0.63.0"
|
||||
"@oxfmt/binding-linux-riscv64-gnu" "0.63.0"
|
||||
"@oxfmt/binding-linux-riscv64-musl" "0.63.0"
|
||||
"@oxfmt/binding-linux-s390x-gnu" "0.63.0"
|
||||
"@oxfmt/binding-linux-x64-gnu" "0.63.0"
|
||||
"@oxfmt/binding-linux-x64-musl" "0.63.0"
|
||||
"@oxfmt/binding-openharmony-arm64" "0.63.0"
|
||||
"@oxfmt/binding-win32-arm64-msvc" "0.63.0"
|
||||
"@oxfmt/binding-win32-ia32-msvc" "0.63.0"
|
||||
"@oxfmt/binding-win32-x64-msvc" "0.63.0"
|
||||
"@oxfmt/binding-android-arm-eabi" "0.62.0"
|
||||
"@oxfmt/binding-android-arm64" "0.62.0"
|
||||
"@oxfmt/binding-darwin-arm64" "0.62.0"
|
||||
"@oxfmt/binding-darwin-x64" "0.62.0"
|
||||
"@oxfmt/binding-freebsd-x64" "0.62.0"
|
||||
"@oxfmt/binding-linux-arm-gnueabihf" "0.62.0"
|
||||
"@oxfmt/binding-linux-arm-musleabihf" "0.62.0"
|
||||
"@oxfmt/binding-linux-arm64-gnu" "0.62.0"
|
||||
"@oxfmt/binding-linux-arm64-musl" "0.62.0"
|
||||
"@oxfmt/binding-linux-ppc64-gnu" "0.62.0"
|
||||
"@oxfmt/binding-linux-riscv64-gnu" "0.62.0"
|
||||
"@oxfmt/binding-linux-riscv64-musl" "0.62.0"
|
||||
"@oxfmt/binding-linux-s390x-gnu" "0.62.0"
|
||||
"@oxfmt/binding-linux-x64-gnu" "0.62.0"
|
||||
"@oxfmt/binding-linux-x64-musl" "0.62.0"
|
||||
"@oxfmt/binding-openharmony-arm64" "0.62.0"
|
||||
"@oxfmt/binding-win32-arm64-msvc" "0.62.0"
|
||||
"@oxfmt/binding-win32-ia32-msvc" "0.62.0"
|
||||
"@oxfmt/binding-win32-x64-msvc" "0.62.0"
|
||||
|
||||
p-cancelable@^3.0.0:
|
||||
version "3.0.0"
|
||||
@@ -15485,15 +15467,15 @@ types-ramda@^0.30.1:
|
||||
dependencies:
|
||||
ts-toolbelt "^9.6.0"
|
||||
|
||||
typescript-eslint@^8.67.0:
|
||||
version "8.67.0"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.67.0.tgz#1e92de09ee0ff2d96cc0848f5e9f345ea930d963"
|
||||
integrity sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==
|
||||
typescript-eslint@^8.66.0:
|
||||
version "8.66.0"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.66.0.tgz#0809b6d25c8a0924690ba30dc1f05607093c11fb"
|
||||
integrity sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "8.67.0"
|
||||
"@typescript-eslint/parser" "8.67.0"
|
||||
"@typescript-eslint/typescript-estree" "8.67.0"
|
||||
"@typescript-eslint/utils" "8.67.0"
|
||||
"@typescript-eslint/eslint-plugin" "8.66.0"
|
||||
"@typescript-eslint/parser" "8.66.0"
|
||||
"@typescript-eslint/typescript-estree" "8.66.0"
|
||||
"@typescript-eslint/utils" "8.66.0"
|
||||
|
||||
typescript@~6.0.3:
|
||||
version "6.0.3"
|
||||
|
||||
@@ -42,7 +42,7 @@ dependencies = [
|
||||
# ``google-auth`` 2.53+ dropped it, so Superset must declare it
|
||||
# explicitly to keep fresh ``pip install apache-superset`` working
|
||||
# without the ``base.txt`` lock file (#40962).
|
||||
"cachetools>=7.1.7, <8",
|
||||
"cachetools>=7.1.6, <8",
|
||||
"celery>=5.6.3, <6.0.0",
|
||||
"click>=8.4.2",
|
||||
"click-option-group",
|
||||
@@ -75,7 +75,7 @@ dependencies = [
|
||||
"humanize",
|
||||
"isodate",
|
||||
"jsonpath-ng>=1.8.0, <2",
|
||||
"Mako>=1.4.1",
|
||||
"Mako>=1.2.2",
|
||||
"markdown>=3.10.3",
|
||||
# marshmallow 4 compatibility: see superset/marshmallow_compatibility.py for a
|
||||
# Flask-AppBuilder workaround. Tracking issue:
|
||||
@@ -135,10 +135,10 @@ athena = ["pyathena[pandas]>=3.35.4, <4"]
|
||||
# superset/db_engine_specs/aurora.py's known_incompatibilities metadata.
|
||||
aurora-data-api = ["preset-sqlalchemy-aurora-data-api>=0.2.8,<0.3"]
|
||||
bigquery = [
|
||||
"pandas-gbq>=0.35.1",
|
||||
"pandas-gbq>=0.35.0",
|
||||
# 1.17.1 is likely the final release: googleapis/python-bigquery-sqlalchemy
|
||||
# was archived 2026-05-16. Both 1.17.0 and 1.17.1 support SQLAlchemy 1.4/2.0.
|
||||
"sqlalchemy-bigquery>=1.17.2",
|
||||
"sqlalchemy-bigquery>=1.17.1",
|
||||
"google-cloud-bigquery>=3.42.3",
|
||||
]
|
||||
clickhouse = ["clickhouse-connect>=1.6.0, <2.0"]
|
||||
@@ -185,7 +185,7 @@ excel = ["xlrd>=2.0.2, <2.1"]
|
||||
# installing this extra is only required to actually run exports.
|
||||
excel-export = ["boto3"]
|
||||
fastmcp = [
|
||||
"fastmcp>=3.4.6,<4.0",
|
||||
"fastmcp>=3.4.5,<4.0",
|
||||
# tiktoken backs the response-size-guard token estimator. Without
|
||||
# it, the middleware falls back to a coarser character-based
|
||||
# heuristic that under-counts JSON-heavy MCP responses.
|
||||
@@ -221,7 +221,7 @@ ocient = [
|
||||
# unpinned sqlalchemy>=1.4 declared, but SQLAlchemy 2.0 support is
|
||||
# unverified. Lower confidence than the other bumps in this PR.
|
||||
"sqlalchemy-ocient>=3.0.0, <4",
|
||||
"pyocient>=3.9.0, <4",
|
||||
"pyocient>=1.0.15, <4",
|
||||
"shapely",
|
||||
"geojson",
|
||||
]
|
||||
|
||||
@@ -28,7 +28,7 @@ numexpr>=2.9.0
|
||||
# Security: CVE-2026-34073 (MEDIUM) - Improper Certificate Validation
|
||||
cryptography>=50.0.0,<51.0.0
|
||||
# Security: Snyk - XSS vulnerability in Mako templates
|
||||
mako>=1.4.1,<2.0.0
|
||||
mako>=1.3.11,<2.0.0
|
||||
# Security: CVE-2024-52338 (CRITICAL) - Deserialization of untrusted data in IPC/Parquet readers
|
||||
pyarrow>=24.0.0,<26.0.0
|
||||
# Security: CVE-2026-27459 - pyopenssl certificate validation
|
||||
|
||||
@@ -44,7 +44,7 @@ cachelib==0.13.0
|
||||
# via
|
||||
# flask-caching
|
||||
# flask-session
|
||||
cachetools==7.1.7
|
||||
cachetools==7.1.6
|
||||
# via apache-superset (pyproject.toml)
|
||||
cattrs==25.1.1
|
||||
# via requests-cache
|
||||
@@ -207,7 +207,7 @@ kombu==5.6.2
|
||||
# via celery
|
||||
limits==5.1.0
|
||||
# via flask-limiter
|
||||
mako==1.4.1
|
||||
mako==1.3.12
|
||||
# via
|
||||
# -r requirements/base.in
|
||||
# apache-superset (pyproject.toml)
|
||||
|
||||
@@ -99,7 +99,7 @@ cachelib==0.13.0
|
||||
# -c requirements/base-constraint.txt
|
||||
# flask-caching
|
||||
# flask-session
|
||||
cachetools==7.1.7
|
||||
cachetools==7.1.6
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
@@ -239,9 +239,9 @@ et-xmlfile==2.0.0
|
||||
# openpyxl
|
||||
exceptiongroup==1.3.0
|
||||
# via fastmcp-slim
|
||||
fastmcp==3.4.7
|
||||
fastmcp==3.4.5
|
||||
# via apache-superset
|
||||
fastmcp-slim==3.4.7
|
||||
fastmcp-slim==3.4.5
|
||||
# via fastmcp
|
||||
filelock==3.20.3
|
||||
# via
|
||||
@@ -510,7 +510,7 @@ limits==5.1.0
|
||||
# flask-limiter
|
||||
lz4==4.4.5
|
||||
# via trino
|
||||
mako==1.4.1
|
||||
mako==1.3.12
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# alembic
|
||||
@@ -640,7 +640,7 @@ pandas==2.3.3
|
||||
# db-dtypes
|
||||
# pandas-gbq
|
||||
# prophet
|
||||
pandas-gbq==0.35.1
|
||||
pandas-gbq==0.35.0
|
||||
# via apache-superset
|
||||
parameterized==0.9.0
|
||||
# via apache-superset
|
||||
@@ -964,7 +964,7 @@ sqlalchemy==2.0.51
|
||||
# sqlalchemy-bigquery
|
||||
# sqlalchemy-continuum
|
||||
# sqlalchemy-utils
|
||||
sqlalchemy-bigquery==1.17.2
|
||||
sqlalchemy-bigquery==1.17.1
|
||||
# via apache-superset
|
||||
sqlalchemy-continuum==1.7.0
|
||||
# via
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import enum
|
||||
from dataclasses import dataclass, field
|
||||
from dataclasses import dataclass
|
||||
from datetime import date, datetime, time, timedelta
|
||||
from typing import Any
|
||||
|
||||
import isodate
|
||||
import pyarrow as pa
|
||||
@@ -91,8 +90,6 @@ class Dimension:
|
||||
definition: str | None = None
|
||||
description: str | None = None
|
||||
grain: Grain | None = None
|
||||
verbose_name: str | None = field(default=None, compare=False)
|
||||
metadata: dict[str, Any] = field(default_factory=dict, compare=False)
|
||||
|
||||
|
||||
class AggregationType(str, enum.Enum):
|
||||
@@ -124,9 +121,6 @@ class Metric:
|
||||
definition: str
|
||||
description: str | None = None
|
||||
aggregation: AggregationType | None = None
|
||||
verbose_name: str | None = field(default=None, compare=False)
|
||||
d3format: str | None = field(default=None, compare=False)
|
||||
metadata: dict[str, Any] = field(default_factory=dict, compare=False)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import pyarrow as pa
|
||||
from superset_core.semantic_layers.types import Dimension, Metric
|
||||
|
||||
|
||||
def test_dimension_metadata_is_not_part_of_identity() -> None:
|
||||
first = Dimension(
|
||||
"sales.region",
|
||||
"region",
|
||||
pa.utf8(),
|
||||
verbose_name="Region",
|
||||
metadata={"display_name": "Region"},
|
||||
)
|
||||
second = Dimension(
|
||||
"sales.region",
|
||||
"region",
|
||||
pa.utf8(),
|
||||
verbose_name="Sales region",
|
||||
metadata={"display_name": "Sales region"},
|
||||
)
|
||||
|
||||
assert first == second
|
||||
assert {first, second} == {first}
|
||||
|
||||
|
||||
def test_metric_metadata_is_not_part_of_identity() -> None:
|
||||
first = Metric(
|
||||
"sales.total_revenue",
|
||||
"total_revenue",
|
||||
pa.float64(),
|
||||
"SUM(revenue)",
|
||||
verbose_name="Total revenue",
|
||||
d3format="$,.2f",
|
||||
metadata={"unit": {"kind": "currency", "code": "USD"}},
|
||||
)
|
||||
second = Metric(
|
||||
"sales.total_revenue",
|
||||
"total_revenue",
|
||||
pa.float64(),
|
||||
"SUM(revenue)",
|
||||
verbose_name="Revenue",
|
||||
d3format=",.0f",
|
||||
metadata={"unit": {"kind": "currency", "code": "EUR"}},
|
||||
)
|
||||
|
||||
assert first == second
|
||||
assert {first, second} == {first}
|
||||
|
||||
|
||||
def test_metric_accepts_superset_presentation_fields() -> None:
|
||||
metric = Metric(
|
||||
"sales.total_revenue",
|
||||
"total_revenue",
|
||||
pa.float64(),
|
||||
"SUM(revenue)",
|
||||
verbose_name="Total revenue",
|
||||
d3format="$,.2f",
|
||||
)
|
||||
|
||||
assert metric.verbose_name == "Total revenue"
|
||||
assert metric.d3format == "$,.2f"
|
||||
|
||||
|
||||
def test_dimension_accepts_superset_presentation_fields() -> None:
|
||||
dimension = Dimension(
|
||||
"sales.region",
|
||||
"region",
|
||||
pa.utf8(),
|
||||
verbose_name="Region",
|
||||
)
|
||||
|
||||
assert dimension.verbose_name == "Region"
|
||||
|
||||
|
||||
def test_metadata_defaults_are_not_shared() -> None:
|
||||
first = Metric("first", "first", pa.int64(), "COUNT(*)")
|
||||
second = Metric("second", "second", pa.int64(), "COUNT(*)")
|
||||
|
||||
first.metadata["display_name"] = "First"
|
||||
|
||||
assert second.metadata == {}
|
||||
@@ -19,7 +19,6 @@
|
||||
"@babel/preset-typescript": "7.29.7",
|
||||
"@types/node": "^25.4.0",
|
||||
"babel-loader": "^9.1.3",
|
||||
"jsdom": "^26.1.0",
|
||||
"tscw-config": "^1.1.2",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^4.0.18",
|
||||
@@ -27,27 +26,6 @@
|
||||
"webpack-cli": "^5.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/css-color": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz",
|
||||
"integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@csstools/css-calc": "^2.1.3",
|
||||
"@csstools/css-color-parser": "^3.0.9",
|
||||
"@csstools/css-parser-algorithms": "^3.0.4",
|
||||
"@csstools/css-tokenizer": "^3.0.3",
|
||||
"lru-cache": "^10.4.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/css-color/node_modules/lru-cache": {
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@babel/cli": {
|
||||
"version": "7.29.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.29.7.tgz",
|
||||
@@ -1678,121 +1656,6 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/color-helpers": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
|
||||
"integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT-0",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-calc": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz",
|
||||
"integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-parser-algorithms": "^3.0.5",
|
||||
"@csstools/css-tokenizer": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-color-parser": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz",
|
||||
"integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@csstools/color-helpers": "^5.1.0",
|
||||
"@csstools/css-calc": "^2.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-parser-algorithms": "^3.0.5",
|
||||
"@csstools/css-tokenizer": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-parser-algorithms": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz",
|
||||
"integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-tokenizer": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-tokenizer": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz",
|
||||
"integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@discoveryjs/json-ext": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz",
|
||||
@@ -2638,16 +2501,6 @@
|
||||
"acorn": "^8.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
||||
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "8.20.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
|
||||
@@ -3015,34 +2868,6 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/cssstyle": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz",
|
||||
"integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@asamuzakjp/css-color": "^3.2.0",
|
||||
"rrweb-cssom": "^0.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
|
||||
"integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"whatwg-mimetype": "^4.0.0",
|
||||
"whatwg-url": "^14.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
@@ -3061,13 +2886,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decimal.js": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
|
||||
"integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
@@ -3097,19 +2915,6 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
||||
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/envinfo": {
|
||||
"version": "7.13.0",
|
||||
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz",
|
||||
@@ -3511,60 +3316,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/html-encoding-sniffer": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
|
||||
"integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"whatwg-encoding": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
||||
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
||||
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.2",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/import-local": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
|
||||
@@ -3687,13 +3438,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-potential-custom-element-name": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
||||
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
@@ -3754,46 +3498,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jsdom": {
|
||||
"version": "26.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz",
|
||||
"integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cssstyle": "^4.2.1",
|
||||
"data-urls": "^5.0.0",
|
||||
"decimal.js": "^10.5.0",
|
||||
"html-encoding-sniffer": "^4.0.0",
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"is-potential-custom-element-name": "^1.0.1",
|
||||
"nwsapi": "^2.2.16",
|
||||
"parse5": "^7.2.1",
|
||||
"rrweb-cssom": "^0.8.0",
|
||||
"saxes": "^6.0.0",
|
||||
"symbol-tree": "^3.2.4",
|
||||
"tough-cookie": "^5.1.1",
|
||||
"w3c-xmlserializer": "^5.0.0",
|
||||
"webidl-conversions": "^7.0.0",
|
||||
"whatwg-encoding": "^3.1.1",
|
||||
"whatwg-mimetype": "^4.0.0",
|
||||
"whatwg-url": "^14.1.1",
|
||||
"ws": "^8.18.0",
|
||||
"xml-name-validator": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"canvas": "^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"canvas": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jsesc": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
|
||||
@@ -4273,13 +3977,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nwsapi": {
|
||||
"version": "2.2.24",
|
||||
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.24.tgz",
|
||||
"integrity": "sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/obug": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz",
|
||||
@@ -4336,19 +4033,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
|
||||
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"entities": "^6.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
@@ -4458,16 +4142,6 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
@@ -4640,33 +4314,6 @@
|
||||
"@rolldown/binding-win32-x64-msvc": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/rrweb-cssom": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz",
|
||||
"integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/saxes": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
|
||||
"integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"xmlchars": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v12.22.7"
|
||||
}
|
||||
},
|
||||
"node_modules/schema-utils": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
|
||||
@@ -4800,13 +4447,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
|
||||
@@ -4952,26 +4592,6 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tldts": {
|
||||
"version": "6.1.86",
|
||||
"resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz",
|
||||
"integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tldts-core": "^6.1.86"
|
||||
},
|
||||
"bin": {
|
||||
"tldts": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tldts-core": {
|
||||
"version": "6.1.86",
|
||||
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz",
|
||||
"integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
@@ -4985,32 +4605,6 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
|
||||
"integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"tldts": "^6.1.32"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
|
||||
"integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tscw-config": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tscw-config/-/tscw-config-1.1.2.tgz",
|
||||
@@ -5337,19 +4931,6 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/w3c-xmlserializer": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
|
||||
"integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"xml-name-validator": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz",
|
||||
@@ -5363,16 +4944,6 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.105.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz",
|
||||
@@ -5499,44 +5070,6 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-encoding": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
|
||||
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
|
||||
"deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iconv-lite": "0.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-mimetype": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
|
||||
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "14.2.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
|
||||
"integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tr46": "^5.1.0",
|
||||
"webidl-conversions": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
@@ -5581,45 +5114,6 @@
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.21.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz",
|
||||
"integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml-name-validator": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
|
||||
"integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlchars": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
"@babel/preset-typescript": "7.29.7",
|
||||
"@types/node": "^25.4.0",
|
||||
"babel-loader": "^9.1.3",
|
||||
"jsdom": "^26.1.0",
|
||||
"tscw-config": "^1.1.2",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^4.0.18",
|
||||
|
||||
@@ -1,213 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
// @vitest-environment jsdom
|
||||
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { Switchboard } from "@superset-ui/switchboard";
|
||||
import { embedDashboard } from "./index";
|
||||
|
||||
vi.mock("@superset-ui/switchboard");
|
||||
|
||||
function makeFakeJWT(claims: any) {
|
||||
// not a valid jwt, but close enough for this code
|
||||
const tokenifiedClaims = Buffer.from(JSON.stringify(claims)).toString(
|
||||
"base64",
|
||||
);
|
||||
return `abc.${tokenifiedClaims}.xyz`;
|
||||
}
|
||||
|
||||
describe("embedDashboard", () => {
|
||||
let mountPoint: HTMLElement;
|
||||
let mockSwitchboard: Switchboard;
|
||||
|
||||
beforeEach(() => {
|
||||
mountPoint = document.createElement("div");
|
||||
document.body.appendChild(mountPoint);
|
||||
|
||||
mockSwitchboard = {
|
||||
emit: vi.fn(),
|
||||
get: vi.fn(),
|
||||
start: vi.fn(),
|
||||
defineMethod: vi.fn(),
|
||||
} as any;
|
||||
|
||||
// Constructor mocks must use `function`, since arrow functions cannot be
|
||||
// invoked with `new`.
|
||||
vi.mocked(Switchboard).mockImplementation(function () {
|
||||
return mockSwitchboard;
|
||||
} as any);
|
||||
|
||||
// Mock MessageChannel API
|
||||
globalThis.MessageChannel = vi.fn(function (this: any) {
|
||||
this.port1 = {};
|
||||
this.port2 = {};
|
||||
}) as any;
|
||||
|
||||
// Mock iframe load event and sandbox
|
||||
const originalCreateElement = document.createElement.bind(document);
|
||||
vi.spyOn(document, "createElement").mockImplementation(tagName => {
|
||||
const element = originalCreateElement(tagName);
|
||||
if (tagName === "iframe") {
|
||||
// Mock sandbox DOMTokenList
|
||||
(element as any).sandbox = {
|
||||
add: vi.fn(),
|
||||
};
|
||||
// Mock contentWindow for postMessage
|
||||
Object.defineProperty(element, "contentWindow", {
|
||||
writable: true,
|
||||
value: {
|
||||
postMessage: vi.fn(),
|
||||
},
|
||||
});
|
||||
setTimeout(() => {
|
||||
element.dispatchEvent(new Event("load"));
|
||||
}, 0);
|
||||
}
|
||||
return element;
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(mountPoint);
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
test("setDataMask sends dataMask to iframe", async () => {
|
||||
const fakeToken = makeFakeJWT({ exp: Date.now() / 1000 + 300 });
|
||||
const mockFetchGuestToken = vi.fn().mockResolvedValue(fakeToken);
|
||||
const testDataMask = {
|
||||
"NATIVE_FILTER-1": {
|
||||
filterState: {
|
||||
value: ["value1", "value2"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const dashboard = await embedDashboard({
|
||||
id: "test-id",
|
||||
supersetDomain: "https://superset.example.com",
|
||||
mountPoint,
|
||||
fetchGuestToken: mockFetchGuestToken,
|
||||
});
|
||||
|
||||
dashboard.setDataMask(testDataMask);
|
||||
|
||||
expect(mockSwitchboard.get).toHaveBeenCalledWith("setDataMask", {
|
||||
dataMask: testDataMask,
|
||||
});
|
||||
});
|
||||
|
||||
test("setDataMask sends empty dataMask", async () => {
|
||||
const fakeToken = makeFakeJWT({ exp: Date.now() / 1000 + 300 });
|
||||
const mockFetchGuestToken = vi.fn().mockResolvedValue(fakeToken);
|
||||
const emptyDataMask = {};
|
||||
|
||||
const dashboard = await embedDashboard({
|
||||
id: "test-id",
|
||||
supersetDomain: "https://superset.example.com",
|
||||
mountPoint,
|
||||
fetchGuestToken: mockFetchGuestToken,
|
||||
});
|
||||
|
||||
dashboard.setDataMask(emptyDataMask);
|
||||
|
||||
expect(mockSwitchboard.get).toHaveBeenCalledWith("setDataMask", {
|
||||
dataMask: emptyDataMask,
|
||||
});
|
||||
});
|
||||
|
||||
test("setDataMask drops the change-trigger flags observeDataMask adds", async () => {
|
||||
const fakeToken = makeFakeJWT({ exp: Date.now() / 1000 + 300 });
|
||||
const mockFetchGuestToken = vi.fn().mockResolvedValue(fakeToken);
|
||||
const observedMask = {
|
||||
"NATIVE_FILTER-1": {
|
||||
filterState: {
|
||||
value: ["CA"],
|
||||
},
|
||||
},
|
||||
crossFiltersChanged: false,
|
||||
nativeFiltersChanged: true,
|
||||
};
|
||||
|
||||
const dashboard = await embedDashboard({
|
||||
id: "test-id",
|
||||
supersetDomain: "https://superset.example.com",
|
||||
mountPoint,
|
||||
fetchGuestToken: mockFetchGuestToken,
|
||||
});
|
||||
|
||||
dashboard.setDataMask(observedMask);
|
||||
|
||||
expect(mockSwitchboard.get).toHaveBeenCalledWith("setDataMask", {
|
||||
dataMask: {
|
||||
"NATIVE_FILTER-1": observedMask["NATIVE_FILTER-1"],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("setDataMask sends complex dataMask with multiple filters", async () => {
|
||||
const fakeToken = makeFakeJWT({ exp: Date.now() / 1000 + 300 });
|
||||
const mockFetchGuestToken = vi.fn().mockResolvedValue(fakeToken);
|
||||
const complexDataMask = {
|
||||
"NATIVE_FILTER-1": {
|
||||
filterState: {
|
||||
value: ["CA", "NY"],
|
||||
},
|
||||
},
|
||||
"NATIVE_FILTER-2": {
|
||||
filterState: {
|
||||
value: [2023, 2024],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const dashboard = await embedDashboard({
|
||||
id: "test-id",
|
||||
supersetDomain: "https://superset.example.com",
|
||||
mountPoint,
|
||||
fetchGuestToken: mockFetchGuestToken,
|
||||
});
|
||||
|
||||
dashboard.setDataMask(complexDataMask);
|
||||
|
||||
expect(mockSwitchboard.get).toHaveBeenCalledWith("setDataMask", {
|
||||
dataMask: complexDataMask,
|
||||
});
|
||||
});
|
||||
|
||||
test("setDataMask rejects when the embedded page does not support it", async () => {
|
||||
const fakeToken = makeFakeJWT({ exp: Date.now() / 1000 + 300 });
|
||||
const mockFetchGuestToken = vi.fn().mockResolvedValue(fakeToken);
|
||||
vi.mocked(mockSwitchboard.get).mockRejectedValue(
|
||||
new Error('Method "setDataMask" is not defined'),
|
||||
);
|
||||
|
||||
const dashboard = await embedDashboard({
|
||||
id: "test-id",
|
||||
supersetDomain: "https://superset.example.com",
|
||||
mountPoint,
|
||||
fetchGuestToken: mockFetchGuestToken,
|
||||
});
|
||||
|
||||
await expect(dashboard.setDataMask({})).rejects.toThrow(
|
||||
'Method "setDataMask" is not defined',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -115,12 +115,6 @@ export type EmbeddedDashboard = {
|
||||
getActiveTabs: () => Promise<string[]>;
|
||||
observeDataMask: (callbackFn: ObserveDataMaskCallbackFn) => void;
|
||||
getDataMask: () => Promise<Record<string, any>>;
|
||||
/**
|
||||
* Applies a data mask to the dashboard.
|
||||
* Rejects if the embedded Superset page does not support `setDataMask`,
|
||||
* so a version mismatch surfaces instead of silently doing nothing.
|
||||
*/
|
||||
setDataMask: (dataMask: Record<string, any>) => Promise<void>;
|
||||
getChartStates: () => Promise<Record<string, any>>;
|
||||
getChartDataPayloads: (params?: {
|
||||
chartId?: number;
|
||||
@@ -361,21 +355,6 @@ export async function embedDashboard({
|
||||
ourPort.get<string>("getDashboardPermalink", { anchor });
|
||||
const getActiveTabs = () => ourPort.get<string[]>("getActiveTabs");
|
||||
const getDataMask = () => ourPort.get<Record<string, any>>("getDataMask");
|
||||
// `observeDataMask` hands the host a mask with the change-trigger booleans
|
||||
// mixed in, so feeding that payload straight back into `setDataMask` is a
|
||||
// natural thing for a host to do. Keep only the entries that look like a
|
||||
// filter's mask, so those flags never reach the dashboard as filter ids.
|
||||
// Sent with `get` rather than `emit` so the iframe acknowledges the call:
|
||||
// an embedded page that predates `setDataMask` replies with an error instead
|
||||
// of dropping the message silently.
|
||||
const setDataMask = (dataMask: Record<string, any>) =>
|
||||
ourPort.get<void>("setDataMask", {
|
||||
dataMask: Object.fromEntries(
|
||||
Object.entries(dataMask).filter(
|
||||
([, mask]) => typeof mask === "object" && mask !== null,
|
||||
),
|
||||
),
|
||||
});
|
||||
const getChartStates = () =>
|
||||
ourPort.get<Record<string, any>>("getChartStates");
|
||||
const getChartDataPayloads = (params?: { chartId?: number }) =>
|
||||
@@ -417,7 +396,6 @@ export async function embedDashboard({
|
||||
getActiveTabs,
|
||||
observeDataMask,
|
||||
getDataMask,
|
||||
setDataMask,
|
||||
getChartStates,
|
||||
getChartDataPayloads,
|
||||
setThemeConfig,
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"playwright:debug": "playwright test --debug",
|
||||
"playwright:report": "playwright show-report",
|
||||
"docs:screenshots": "playwright test --config=playwright/generators/playwright.config.ts docs/",
|
||||
"playwright:thumbnails": "CAPTURE_THUMBNAILS=1 playwright test tests/tools/capture-viz-thumbnails.spec.ts --project chromium",
|
||||
"prod": "npm run build",
|
||||
"prune": "rm -rf ./{packages,plugins}/*/{node_modules,lib,esm,tsconfig.tsbuildinfo,package-lock.json} ./.temp_cache",
|
||||
"storybook": "cross-env NODE_ENV=development BABEL_ENV=development storybook dev -p 6006",
|
||||
@@ -110,7 +111,7 @@
|
||||
"@fontsource/fira-code": "^5.3.0",
|
||||
"@fontsource/ibm-plex-mono": "^5.3.0",
|
||||
"@fontsource/inter": "^5.3.0",
|
||||
"@googleapis/sheets": "^14.0.0",
|
||||
"@googleapis/sheets": "^13.0.2",
|
||||
"@great-expectations/jsonforms-antd-renderers": "^2.2.10",
|
||||
"@jsonforms/core": "^3.7.0",
|
||||
"@jsonforms/react": "^3.7.0",
|
||||
@@ -158,7 +159,7 @@
|
||||
"@visx/xychart": "^4.0.0",
|
||||
"ag-grid-community": "36.1.0",
|
||||
"ag-grid-react": "36.1.0",
|
||||
"antd": "^6.6.0",
|
||||
"antd": "^6.5.4",
|
||||
"chrono-node": "^2.10.1",
|
||||
"classnames": "^2.2.5",
|
||||
"content-disposition": "^2.0.1",
|
||||
@@ -176,7 +177,7 @@
|
||||
"geostyler-openlayers-parser": "^5.7.1",
|
||||
"geostyler-style": "11.0.2",
|
||||
"geostyler-wfs-parser": "^3.0.1",
|
||||
"google-auth-library": "^11.0.1",
|
||||
"google-auth-library": "^11.0.0",
|
||||
"immer": "^11.1.16",
|
||||
"interweave": "^13.1.1",
|
||||
"jquery": "^4.0.0",
|
||||
@@ -266,7 +267,7 @@
|
||||
"@swc/plugin-emotion": "^14.15.0",
|
||||
"@swc/plugin-transform-imports": "^12.5.0",
|
||||
"@testing-library/dom": "^10.4.1",
|
||||
"@testing-library/jest-dom": "^7.0.1",
|
||||
"@testing-library/jest-dom": "^7.0.0",
|
||||
"@testing-library/react": "^15.0.0",
|
||||
"@testing-library/user-event": "^12.8.3",
|
||||
"@types/content-disposition": "^0.5.9",
|
||||
@@ -277,7 +278,7 @@
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/mousetrap": "^1.6.15",
|
||||
"@types/node": "^26.2.0",
|
||||
"@types/node": "^26.1.2",
|
||||
"@types/react": "^18.3.0",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/react-loadable": "^5.5.11",
|
||||
@@ -289,19 +290,19 @@
|
||||
"@types/rison": "0.1.0",
|
||||
"@types/tinycolor2": "^1.4.3",
|
||||
"@types/unzipper": "^0.10.11",
|
||||
"@typescript-eslint/eslint-plugin": "^8.67.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.66.0",
|
||||
"@typescript-eslint/parser": "^8.63.0",
|
||||
"babel-jest": "^30.4.1",
|
||||
"babel-loader": "^10.1.1",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
||||
"baseline-browser-mapping": "^2.11.13",
|
||||
"baseline-browser-mapping": "^2.11.12",
|
||||
"cheerio": "1.2.0",
|
||||
"concurrently": "^10.0.4",
|
||||
"copy-webpack-plugin": "^14.0.0",
|
||||
"cross-env": "^10.1.0",
|
||||
"css-loader": "^7.1.4",
|
||||
"eslint": "^10.8.1",
|
||||
"eslint": "^10.8.0",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-import-resolver-typescript": "^4.4.5",
|
||||
"eslint-plugin-i18n-strings": "file:eslint-rules/eslint-plugin-i18n-strings",
|
||||
@@ -331,8 +332,8 @@
|
||||
"mini-css-extract-plugin": "^2.10.2",
|
||||
"minimizer-webpack-plugin": "^5.6.1",
|
||||
"open-cli": "^9.0.0",
|
||||
"oxfmt": "^0.63.0",
|
||||
"oxlint": "^1.78.0",
|
||||
"oxfmt": "^0.62.0",
|
||||
"oxlint": "^1.77.0",
|
||||
"po2json": "^0.4.5",
|
||||
"postcss-styled-syntax": "^0.7.2",
|
||||
"process": "^0.11.10",
|
||||
@@ -349,7 +350,7 @@
|
||||
"swc-loader": "^0.2.7",
|
||||
"ts-jest": "^29.4.12",
|
||||
"tscw-config": "^1.1.2",
|
||||
"tsx": "^4.23.12",
|
||||
"tsx": "^4.23.10",
|
||||
"typescript": "5.4.5",
|
||||
"unzipper": "^0.12.5",
|
||||
"wait-on": "^9.1.0",
|
||||
@@ -415,7 +416,6 @@
|
||||
"minimatch@>=10": {
|
||||
"brace-expansion": ">=5.0.8"
|
||||
},
|
||||
"nanoid@>=3 <4": "3.3.18",
|
||||
"nwsapi": "^2.2.13",
|
||||
"puppeteer": "^22.4.1",
|
||||
"tar": "^7.5.16",
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
"@types/d3-time-format": "^4.0.3",
|
||||
"@types/jquery": "^4.0.1",
|
||||
"@types/lodash": "^4.17.25",
|
||||
"@types/node": "^26.2.0",
|
||||
"@types/node": "^26.1.2",
|
||||
"@types/prop-types": "^15.7.15",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"@types/react-table": "^7.7.20",
|
||||
|
||||
@@ -107,14 +107,12 @@ const getAllSelectOptions = () =>
|
||||
|
||||
const findSelectOption = (text: string) =>
|
||||
waitFor(() =>
|
||||
within(getElementByClassName('.ant-select-dropdown-list')).getByText(text),
|
||||
within(getElementByClassName('.rc-virtual-list')).getByText(text),
|
||||
);
|
||||
|
||||
const querySelectOption = (text: string) =>
|
||||
waitFor(() =>
|
||||
within(getElementByClassName('.ant-select-dropdown-list')).queryByText(
|
||||
text,
|
||||
),
|
||||
within(getElementByClassName('.rc-virtual-list')).queryByText(text),
|
||||
);
|
||||
|
||||
const findAllSelectOptions = () =>
|
||||
@@ -646,7 +644,7 @@ test('does not add a new option if the option already exists', async () => {
|
||||
await type(option);
|
||||
await waitFor(() => {
|
||||
const array = within(
|
||||
getElementByClassName('.ant-select-dropdown-list'),
|
||||
getElementByClassName('.rc-virtual-list'),
|
||||
).getAllByText(option);
|
||||
expect(array.length).toBe(1);
|
||||
});
|
||||
@@ -1400,7 +1398,7 @@ test('appends page>1 results during an active search and discards them when sear
|
||||
// scrollTop via e.currentTarget in its onFallbackScroll handler, which
|
||||
// then forwards to onPopupScroll (handlePagination here).
|
||||
const holder = document.querySelector(
|
||||
'.ant-select-dropdown-list-holder',
|
||||
'.rc-virtual-list-holder',
|
||||
) as HTMLElement | null;
|
||||
if (!holder) throw new Error('virtual-list holder not rendered');
|
||||
Object.defineProperty(holder, 'scrollHeight', {
|
||||
|
||||
@@ -93,14 +93,12 @@ const deselectAllButtonText = (length: number) =>
|
||||
|
||||
const findSelectOption = (text: string) =>
|
||||
waitFor(() =>
|
||||
within(getElementByClassName('.ant-select-dropdown-list')).getByText(text),
|
||||
within(getElementByClassName('.rc-virtual-list')).getByText(text),
|
||||
);
|
||||
|
||||
const querySelectOption = (text: string) =>
|
||||
waitFor(() =>
|
||||
within(getElementByClassName('.ant-select-dropdown-list')).queryByText(
|
||||
text,
|
||||
),
|
||||
within(getElementByClassName('.rc-virtual-list')).queryByText(text),
|
||||
);
|
||||
|
||||
const getAllSelectOptions = () =>
|
||||
|
||||
@@ -19,71 +19,19 @@
|
||||
import { t } from '@apache-superset/core/translation';
|
||||
import { sanitizeHtml } from './html';
|
||||
|
||||
export type TooltipTruncationMode = 'off' | 'end' | 'start' | 'middle';
|
||||
|
||||
export const TRUNCATION_MAX_CHARS = 40;
|
||||
|
||||
const TRUNCATION_STYLE = `
|
||||
max-width: 300px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
`;
|
||||
|
||||
const NOWRAP_STYLE = `
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
/**
|
||||
* Shortens plain text so a tooltip label stays readable, placing the ellipsis
|
||||
* where the caller asked for it.
|
||||
*
|
||||
* Only 'start' and 'middle' slice. 'end' is handled by CSS in tooltipHtml, and
|
||||
* 'off' means no truncation at all, so both return the input untouched.
|
||||
*
|
||||
* The input must be plain text. Callers are responsible for truncating before
|
||||
* any markup (such as the ECharts series marker) is prepended, and before
|
||||
* sanitization — slicing a string that already contains markup would cut into
|
||||
* a tag.
|
||||
*/
|
||||
export function truncateLabel(
|
||||
text: string,
|
||||
mode: TooltipTruncationMode = 'end',
|
||||
): string {
|
||||
if (
|
||||
(mode !== 'start' && mode !== 'middle') ||
|
||||
text.length <= TRUNCATION_MAX_CHARS
|
||||
) {
|
||||
return text;
|
||||
}
|
||||
const budget = TRUNCATION_MAX_CHARS - 1;
|
||||
if (mode === 'start') {
|
||||
return `…${text.slice(-budget)}`;
|
||||
}
|
||||
const head = Math.ceil(budget / 2);
|
||||
const tail = Math.floor(budget / 2);
|
||||
return `${text.slice(0, head)}…${text.slice(-tail)}`;
|
||||
}
|
||||
|
||||
function getTruncationStyle(mode: TooltipTruncationMode): string {
|
||||
if (mode === 'end') {
|
||||
return TRUNCATION_STYLE;
|
||||
}
|
||||
if (mode === 'off') {
|
||||
return '';
|
||||
}
|
||||
// 'start' and 'middle' are already sliced upstream; keep them on one line.
|
||||
return NOWRAP_STYLE;
|
||||
}
|
||||
|
||||
export function tooltipHtml(
|
||||
data: string[][],
|
||||
title?: string,
|
||||
focusedRow?: number,
|
||||
truncation: TooltipTruncationMode = 'end',
|
||||
) {
|
||||
const truncationStyle = getTruncationStyle(truncation);
|
||||
const titleRow = title
|
||||
? `<span style="font-weight: 700;${truncationStyle}">${title}</span>`
|
||||
? `<span style="font-weight: 700;${TRUNCATION_STYLE}">${title}</span>`
|
||||
: '';
|
||||
return sanitizeHtml(`
|
||||
<div>
|
||||
@@ -98,7 +46,7 @@ export function tooltipHtml(
|
||||
const cellStyle = `
|
||||
text-align: ${j > 0 ? 'right' : 'left'};
|
||||
padding-left: ${j === 0 ? 0 : 16}px;
|
||||
${truncationStyle}
|
||||
${TRUNCATION_STYLE}
|
||||
`;
|
||||
return `<td style="${cellStyle}">${cell}</td>`;
|
||||
});
|
||||
|
||||
@@ -16,12 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
sanitizeHtml,
|
||||
tooltipHtml,
|
||||
truncateLabel,
|
||||
TRUNCATION_MAX_CHARS,
|
||||
} from '@superset-ui/core';
|
||||
import { sanitizeHtml, tooltipHtml } from '@superset-ui/core';
|
||||
|
||||
const TITLE_STYLE =
|
||||
'style="font-weight: 700;max-width:300px;overflow:hidden;text-overflow:ellipsis;"';
|
||||
@@ -187,88 +182,3 @@ test('should preserve table styling after sanitization (fixes ECharts tooltip fo
|
||||
expect(html).toContain('padding-left:16px');
|
||||
expect(html).toContain('max-width:300px');
|
||||
});
|
||||
|
||||
describe('truncateLabel', () => {
|
||||
const long = 'prod-us-east-1-service-checkout-latency-p99'; // 43 chars
|
||||
|
||||
test('returns text unchanged for off and end', () => {
|
||||
expect(truncateLabel(long, 'off')).toBe(long);
|
||||
expect(truncateLabel(long, 'end')).toBe(long);
|
||||
});
|
||||
|
||||
test('defaults to end, which does not slice', () => {
|
||||
expect(truncateLabel(long)).toBe(long);
|
||||
});
|
||||
|
||||
test('truncates the start, keeping the distinguishing suffix', () => {
|
||||
expect(truncateLabel(long, 'start')).toBe(
|
||||
'…-us-east-1-service-checkout-latency-p99',
|
||||
);
|
||||
expect(truncateLabel(long, 'start')).toHaveLength(TRUNCATION_MAX_CHARS);
|
||||
});
|
||||
|
||||
test('truncates the middle, keeping both ends', () => {
|
||||
expect(truncateLabel(long, 'middle')).toBe(
|
||||
'prod-us-east-1-servi…heckout-latency-p99',
|
||||
);
|
||||
expect(truncateLabel(long, 'middle')).toHaveLength(TRUNCATION_MAX_CHARS);
|
||||
});
|
||||
|
||||
test('leaves text at or under the limit untouched', () => {
|
||||
const atLimit = 'x'.repeat(TRUNCATION_MAX_CHARS);
|
||||
expect(truncateLabel(atLimit, 'start')).toBe(atLimit);
|
||||
expect(truncateLabel(atLimit, 'middle')).toBe(atLimit);
|
||||
expect(truncateLabel('short', 'start')).toBe('short');
|
||||
expect(truncateLabel('', 'middle')).toBe('');
|
||||
});
|
||||
|
||||
test('truncates text one character over the limit', () => {
|
||||
const overLimit = 'x'.repeat(TRUNCATION_MAX_CHARS + 1);
|
||||
expect(truncateLabel(overLimit, 'start')).toBe(
|
||||
`…${'x'.repeat(TRUNCATION_MAX_CHARS - 1)}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('tooltipHtml truncation modes', () => {
|
||||
const rows = [['label', 'value']];
|
||||
|
||||
// sanitizeHtml normalizes spacing inside style attributes, and it does so
|
||||
// differently across versions, so compare with whitespace stripped.
|
||||
const styles = (
|
||||
title: string | undefined,
|
||||
truncation?: 'off' | 'end' | 'start' | 'middle',
|
||||
) => removeWhitespaces(tooltipHtml(rows, title, undefined, truncation));
|
||||
|
||||
test('emits the 300px cap for end and for the default', () => {
|
||||
expect(styles('Title', 'end')).toContain('max-width:300px');
|
||||
expect(tooltipHtml(rows, 'Title')).toBe(
|
||||
tooltipHtml(rows, 'Title', undefined, 'end'),
|
||||
);
|
||||
});
|
||||
|
||||
test('emits no truncation style for off', () => {
|
||||
const html = styles('Title', 'off');
|
||||
expect(html).not.toContain('max-width');
|
||||
expect(html).not.toContain('text-overflow');
|
||||
expect(html).not.toContain('white-space');
|
||||
});
|
||||
|
||||
test.each(['start', 'middle'] as const)(
|
||||
'emits nowrap instead of a cap for %s',
|
||||
mode => {
|
||||
const html = styles('Title', mode);
|
||||
expect(html).toContain('white-space:nowrap');
|
||||
expect(html).not.toContain('max-width');
|
||||
},
|
||||
);
|
||||
|
||||
test('never slices cell text itself, whatever the mode', () => {
|
||||
const longCell = 'y'.repeat(TRUNCATION_MAX_CHARS + 20);
|
||||
(['off', 'end', 'start', 'middle'] as const).forEach(mode => {
|
||||
expect(tooltipHtml([[longCell]], undefined, undefined, mode)).toContain(
|
||||
longCell,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,630 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
/**
|
||||
* Crawls every dashboard on the target instance and refreshes viz-picker
|
||||
* thumbnails and example galleries from live example charts.
|
||||
*
|
||||
* This is a maintenance tool, not a test: charts are DISCOVERED via the
|
||||
* API (dashboards -> charts), so it keeps working as example dashboards
|
||||
* evolve. Every distinct chart found for a viz type gets captured — the
|
||||
* preferred (or alphabetically-first) chart becomes the 512x512
|
||||
* `thumbnail.png`, and each additional distinct chart fills the next
|
||||
* `exampleGallery` slot declared for that viz type, so the gallery shows
|
||||
* real variety instead of the same chart resized. The two static pieces
|
||||
* are the viz type -> image path maps below (VIZ_TYPE_THUMBNAILS,
|
||||
* VIZ_TYPE_GALLERY), which change when a plugin's images or gallery
|
||||
* shape change — never when examples change. Viz types found on
|
||||
* dashboards but missing from both maps, and gallery slots left unfilled
|
||||
* for lack of enough distinct example charts, are reported at the end
|
||||
* without failing the run.
|
||||
*
|
||||
* It only runs when CAPTURE_THUMBNAILS=1 is set, so the regular
|
||||
* Playwright suites never execute it.
|
||||
*
|
||||
* Usage (requires a running Superset with examples loaded):
|
||||
* npm run playwright:thumbnails
|
||||
* VIZ_TYPES=bullet,rose npm run playwright:thumbnails # subset
|
||||
*
|
||||
* Notes:
|
||||
* - Dark variants (`thumbnail-dark.png`, `example-dark.jpg`) are captured
|
||||
* via prefers-color-scheme emulation whenever the sibling file exists;
|
||||
* if the app ignores the emulation (dark theming disabled) the dark
|
||||
* file is left untouched.
|
||||
* - A brand-new gallery image (rather than an existing file being
|
||||
* refreshed) still needs to be registered in the plugin's metadata
|
||||
* before it renders in the gallery; the capture logs a reminder.
|
||||
*/
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { test, expect, Page } from '@playwright/test';
|
||||
|
||||
const THUMBNAIL_SIZE = 512;
|
||||
const RENDERED_CHART_SELECTOR =
|
||||
'[data-test="chart-container"]:has(svg, canvas, table):not(:has([data-test="loading-indicator"]))';
|
||||
/**
|
||||
* Charts that render plain markup — no svg/canvas/table for the rendered
|
||||
* selector to key on — get a looser signal plus a longer settle.
|
||||
*/
|
||||
const TEXT_ONLY_VIZ_TYPES = new Set([
|
||||
'ag-grid-table',
|
||||
'big_number_total',
|
||||
'handlebars',
|
||||
'pop_kpi',
|
||||
]);
|
||||
|
||||
/**
|
||||
* Hover this element just before the screenshot, so charts whose identity
|
||||
* benefits from an interaction (a visible tooltip) capture mid-hover.
|
||||
*/
|
||||
const HOVER_BEFORE_CAPTURE: Record<string, string> = {
|
||||
cal_heatmap: '[data-test="chart-container"] svg rect[class*=" r"]',
|
||||
};
|
||||
const TEXT_RENDERED_CHART_SELECTOR =
|
||||
'[data-test="chart-container"]:not(:has([data-test="loading-indicator"]))';
|
||||
|
||||
/** superset-frontend root, resolved from this spec's location. */
|
||||
const FRONTEND_ROOT = path.resolve(__dirname, '..', '..', '..');
|
||||
|
||||
const ECHARTS = 'plugins/plugin-chart-echarts/src';
|
||||
const DECKGL = 'plugins/preset-chart-deckgl/src/layers';
|
||||
|
||||
/**
|
||||
* Where each viz type's gallery thumbnail lives, relative to
|
||||
* superset-frontend. One entry per registered viz type with a thumbnail;
|
||||
* add a line when a new plugin ships.
|
||||
*/
|
||||
const VIZ_TYPE_THUMBNAILS: Record<string, string> = {
|
||||
'ag-grid-table':
|
||||
'plugins/plugin-chart-ag-grid-table/src/images/thumbnail.png',
|
||||
big_number: `${ECHARTS}/BigNumber/BigNumberWithTrendline/images/thumbnail.png`,
|
||||
big_number_total: `${ECHARTS}/BigNumber/BigNumberTotal/images/thumbnail.png`,
|
||||
box_plot: `${ECHARTS}/BoxPlot/images/thumbnail.png`,
|
||||
bubble_v2: `${ECHARTS}/Bubble/images/thumbnail.png`,
|
||||
bullet: `${ECHARTS}/Bullet/images/thumbnail.png`,
|
||||
cal_heatmap: 'plugins/plugin-chart-calendar/src/images/thumbnail.png',
|
||||
cartodiagram: 'plugins/plugin-chart-cartodiagram/src/images/thumbnail.png',
|
||||
chord: 'plugins/plugin-chart-chord/src/images/thumbnail.png',
|
||||
country_map: 'plugins/plugin-chart-country-map/src/images/thumbnail.png',
|
||||
deck_arc: `${DECKGL}/Arc/images/thumbnail.png`,
|
||||
deck_contour: `${DECKGL}/Contour/images/thumbnail.png`,
|
||||
deck_geojson: `${DECKGL}/Geojson/images/thumbnail.png`,
|
||||
deck_grid: `${DECKGL}/Grid/images/thumbnail.png`,
|
||||
deck_heatmap: `${DECKGL}/Heatmap/images/thumbnail.png`,
|
||||
deck_hex: `${DECKGL}/Hex/images/thumbnail.png`,
|
||||
deck_multi: 'plugins/preset-chart-deckgl/src/Multi/images/thumbnail.png',
|
||||
deck_path: `${DECKGL}/Path/images/thumbnail.png`,
|
||||
deck_polygon: `${DECKGL}/Polygon/images/thumbnail.png`,
|
||||
deck_scatter: `${DECKGL}/Scatter/images/thumbnail.png`,
|
||||
deck_screengrid: `${DECKGL}/Screengrid/images/thumbnail.png`,
|
||||
echarts_area: `${ECHARTS}/Timeseries/Area/images/thumbnail.png`,
|
||||
echarts_timeseries: `${ECHARTS}/Timeseries/images/thumbnail.png`,
|
||||
echarts_timeseries_bar: `${ECHARTS}/Timeseries/Regular/Bar/images/thumbnail.png`,
|
||||
echarts_timeseries_line: `${ECHARTS}/Timeseries/Regular/Line/images/thumbnail.png`,
|
||||
echarts_timeseries_scatter: `${ECHARTS}/Timeseries/Regular/Scatter/images/thumbnail.png`,
|
||||
echarts_timeseries_smooth: `${ECHARTS}/Timeseries/Regular/SmoothLine/images/thumbnail.png`,
|
||||
echarts_timeseries_step: `${ECHARTS}/Timeseries/Step/images/thumbnail.png`,
|
||||
funnel: `${ECHARTS}/Funnel/images/thumbnail.png`,
|
||||
gantt_chart: `${ECHARTS}/Gantt/images/thumbnail.png`,
|
||||
gauge_chart: `${ECHARTS}/Gauge/images/thumbnail.png`,
|
||||
graph_chart: `${ECHARTS}/Graph/images/thumbnail.png`,
|
||||
// handlebars intentionally unmapped: its generic logo represents the
|
||||
// template-anything nature of the chart better than any one example.
|
||||
heatmap_v2: `${ECHARTS}/Heatmap/images/thumbnail.png`,
|
||||
histogram_v2: `${ECHARTS}/Histogram/images/thumbnail.png`,
|
||||
horizon: 'plugins/plugin-chart-horizon/src/images/thumbnail.png',
|
||||
mixed_timeseries: `${ECHARTS}/MixedTimeseries/images/thumbnail.png`,
|
||||
paired_ttest: 'plugins/plugin-chart-paired-t-test/src/images/thumbnail.png',
|
||||
para: 'plugins/plugin-chart-parallel-coordinates/src/images/thumbnail.png',
|
||||
partition: 'plugins/plugin-chart-partition/src/images/thumbnail.png',
|
||||
pie: `${ECHARTS}/Pie/images/thumbnail.png`,
|
||||
pivot_table_v2: 'plugins/plugin-chart-pivot-table/src/images/thumbnail.png',
|
||||
point_cluster_map:
|
||||
'plugins/plugin-chart-point-cluster-map/src/images/thumbnail.png',
|
||||
pop_kpi: `${ECHARTS}/BigNumber/BigNumberPeriodOverPeriod/images/thumbnail.png`,
|
||||
radar: `${ECHARTS}/Radar/images/thumbnail.png`,
|
||||
rose: `${ECHARTS}/Rose/images/thumbnail.png`,
|
||||
sankey_v2: `${ECHARTS}/Sankey/images/thumbnail.png`,
|
||||
sunburst_v2: `${ECHARTS}/Sunburst/images/thumbnail.png`,
|
||||
table: 'plugins/plugin-chart-table/src/images/thumbnail.png',
|
||||
time_pivot: `${ECHARTS}/TimePivot/images/thumbnail.png`,
|
||||
time_table: 'src/visualizations/TimeTable/images/thumbnail.png',
|
||||
tree_chart: `${ECHARTS}/Tree/images/thumbnail.png`,
|
||||
treemap_v2: `${ECHARTS}/Treemap/images/thumbnail.png`,
|
||||
waterfall: `${ECHARTS}/Waterfall/images/thumbnail.png`,
|
||||
word_cloud: 'plugins/plugin-chart-word-cloud/src/images/thumbnail.png',
|
||||
world_map: 'plugins/plugin-chart-world-map/src/images/thumbnail.png',
|
||||
};
|
||||
|
||||
/**
|
||||
* When several example charts share a viz type, prefer these slices over
|
||||
* the default alphabetically-first pick. Missing slices fall back to the
|
||||
* default, so stale entries degrade gracefully.
|
||||
*/
|
||||
const PREFERRED_SLICES: Record<string, string> = {
|
||||
big_number: 'Sales Year over Year',
|
||||
bubble_v2: 'Life Expectancy VS Rural %',
|
||||
bullet: 'Total Sales Bullet',
|
||||
cal_heatmap: 'Sales Calendar Heatmap',
|
||||
chord: 'Product Line Chord',
|
||||
echarts_area: 'Sales Stacked Area',
|
||||
echarts_timeseries_bar: 'Sales Stacked Bars',
|
||||
echarts_timeseries_line: 'Monthly Sales Line',
|
||||
echarts_timeseries_smooth: 'Monthly Sales Smooth',
|
||||
echarts_timeseries_step: 'Quarterly Sales Steps',
|
||||
funnel: 'Population Funnel',
|
||||
gauge_chart: 'Rural Population Gauge',
|
||||
heatmap_v2: 'Sales Grid Heatmap',
|
||||
histogram_v2: 'Life Expectancy Histogram',
|
||||
horizon: 'Population Growth Horizon',
|
||||
mixed_timeseries: 'Sales Mixed Chart',
|
||||
paired_ttest: 'Population Paired t-Test',
|
||||
partition: 'Population Partition',
|
||||
pie: 'Product Line Donut',
|
||||
pivot_table_v2: 'Sales Pivot Highlights',
|
||||
radar: 'Game Sales Radar',
|
||||
rose: 'Population Nightingale Rose',
|
||||
sunburst_v2: 'Population Sunburst',
|
||||
table: 'Sales Summary Table',
|
||||
time_pivot: 'Sales Period Pivot',
|
||||
time_table: 'Product Line Time Table',
|
||||
tree_chart: 'Sales Territory Tree',
|
||||
treemap_v2: 'Population Treemap',
|
||||
waterfall: 'Quarterly Sales Waterfall',
|
||||
};
|
||||
|
||||
/** Gallery example images use a wide aspect, matching the existing art. */
|
||||
const EXAMPLE_WIDTH = 800;
|
||||
const EXAMPLE_HEIGHT = 460;
|
||||
|
||||
/**
|
||||
* Every plugin's `exampleGallery` image slots (never including
|
||||
* `thumbnail.png`/`thumbnail-dark.png`, which stays governed by
|
||||
* VIZ_TYPE_THUMBNAILS), in the order they appear in that plugin's
|
||||
* `index.ts`. One entry per viz type that declares a gallery — including
|
||||
* `handlebars`, whose gallery is filled even though its picker thumbnail
|
||||
* intentionally stays the generic logo (unmapped in VIZ_TYPE_THUMBNAILS).
|
||||
*
|
||||
* For a viz type with N slots here, the crawler assigns its (N+1)
|
||||
* distinct dashboard charts (the thumbnail's pick, then this many more)
|
||||
* to thumbnail, slot 1, slot 2, ... in that order, so gallery images show
|
||||
* different charts than the thumbnail and each other rather than the same
|
||||
* chart resized. Fewer distinct charts than slots just leaves the
|
||||
* trailing slots untouched (reported, not failed) — add more example
|
||||
* charts to fill them.
|
||||
*
|
||||
* Update this when a plugin's exampleGallery array changes shape.
|
||||
*/
|
||||
const VIZ_TYPE_GALLERY: Record<string, string[]> = {
|
||||
'ag-grid-table': [
|
||||
'plugins/plugin-chart-ag-grid-table/src/images/Table.jpg',
|
||||
'plugins/plugin-chart-ag-grid-table/src/images/Table2.jpg',
|
||||
'plugins/plugin-chart-ag-grid-table/src/images/Table3.jpg',
|
||||
],
|
||||
big_number: [
|
||||
`${ECHARTS}/BigNumber/BigNumberWithTrendline/images/Big_Number_Trendline.jpg`,
|
||||
],
|
||||
big_number_total: [
|
||||
`${ECHARTS}/BigNumber/BigNumberTotal/images/BigNumber.jpg`,
|
||||
`${ECHARTS}/BigNumber/BigNumberTotal/images/BigNumber2.jpg`,
|
||||
],
|
||||
box_plot: [`${ECHARTS}/BoxPlot/images/BoxPlot.jpg`],
|
||||
bubble_v2: [
|
||||
`${ECHARTS}/Bubble/images/example1.png`,
|
||||
`${ECHARTS}/Bubble/images/example2.png`,
|
||||
],
|
||||
bullet: [`${ECHARTS}/Bullet/images/example.jpg`],
|
||||
cal_heatmap: ['plugins/plugin-chart-calendar/src/images/example.jpg'],
|
||||
cartodiagram: [
|
||||
'plugins/plugin-chart-cartodiagram/src/images/example1.png',
|
||||
'plugins/plugin-chart-cartodiagram/src/images/example2.png',
|
||||
],
|
||||
chord: ['plugins/plugin-chart-chord/src/images/chord.jpg'],
|
||||
country_map: [
|
||||
'plugins/plugin-chart-country-map/src/images/exampleUsa.jpg',
|
||||
'plugins/plugin-chart-country-map/src/images/exampleGermany.jpg',
|
||||
],
|
||||
echarts_area: [`${ECHARTS}/Timeseries/Area/images/Area1.png`],
|
||||
echarts_timeseries: [`${ECHARTS}/Timeseries/images/Time-series_Chart.jpg`],
|
||||
echarts_timeseries_bar: [
|
||||
`${ECHARTS}/Timeseries/Regular/Bar/images/Bar1.png`,
|
||||
`${ECHARTS}/Timeseries/Regular/Bar/images/Bar2.png`,
|
||||
`${ECHARTS}/Timeseries/Regular/Bar/images/Bar3.png`,
|
||||
],
|
||||
echarts_timeseries_line: [
|
||||
`${ECHARTS}/Timeseries/Regular/Line/images/Line1.png`,
|
||||
`${ECHARTS}/Timeseries/Regular/Line/images/Line2.png`,
|
||||
`${ECHARTS}/Timeseries/Regular/Line/images/Line3.png`,
|
||||
],
|
||||
echarts_timeseries_scatter: [
|
||||
`${ECHARTS}/Timeseries/Regular/Scatter/images/Scatter1.png`,
|
||||
],
|
||||
echarts_timeseries_smooth: [
|
||||
`${ECHARTS}/Timeseries/Regular/SmoothLine/images/SmoothLine1.png`,
|
||||
],
|
||||
echarts_timeseries_step: [
|
||||
`${ECHARTS}/Timeseries/Step/images/Step1.png`,
|
||||
`${ECHARTS}/Timeseries/Step/images/Step2.png`,
|
||||
],
|
||||
funnel: [`${ECHARTS}/Funnel/images/example.jpg`],
|
||||
gantt_chart: [
|
||||
`${ECHARTS}/Gantt/images/example1.png`,
|
||||
`${ECHARTS}/Gantt/images/example2.png`,
|
||||
],
|
||||
gauge_chart: [
|
||||
`${ECHARTS}/Gauge/images/example1.jpg`,
|
||||
`${ECHARTS}/Gauge/images/example2.jpg`,
|
||||
],
|
||||
graph_chart: [`${ECHARTS}/Graph/images/example.jpg`],
|
||||
handlebars: [
|
||||
'plugins/plugin-chart-handlebars/src/images/example1.jpg',
|
||||
'plugins/plugin-chart-handlebars/src/images/example2.jpg',
|
||||
],
|
||||
heatmap_v2: [
|
||||
`${ECHARTS}/Heatmap/images/example1.png`,
|
||||
`${ECHARTS}/Heatmap/images/example2.png`,
|
||||
`${ECHARTS}/Heatmap/images/example3.png`,
|
||||
],
|
||||
histogram_v2: [
|
||||
`${ECHARTS}/Histogram/images/example1.png`,
|
||||
`${ECHARTS}/Histogram/images/example2.png`,
|
||||
],
|
||||
horizon: ['plugins/plugin-chart-horizon/src/images/Horizon_Chart.jpg'],
|
||||
mixed_timeseries: [`${ECHARTS}/MixedTimeseries/images/example.jpg`],
|
||||
paired_ttest: ['plugins/plugin-chart-paired-t-test/src/images/example.jpg'],
|
||||
para: [
|
||||
'plugins/plugin-chart-parallel-coordinates/src/images/example1.jpg',
|
||||
'plugins/plugin-chart-parallel-coordinates/src/images/example2.jpg',
|
||||
],
|
||||
partition: ['plugins/plugin-chart-partition/src/images/example.jpg'],
|
||||
pie: [
|
||||
`${ECHARTS}/Pie/images/Pie1.jpg`,
|
||||
`${ECHARTS}/Pie/images/Pie2.jpg`,
|
||||
`${ECHARTS}/Pie/images/Pie3.jpg`,
|
||||
`${ECHARTS}/Pie/images/Pie4.jpg`,
|
||||
],
|
||||
pivot_table_v2: ['plugins/plugin-chart-pivot-table/src/images/example.jpg'],
|
||||
point_cluster_map: [
|
||||
'plugins/plugin-chart-point-cluster-map/src/images/MapBox.jpg',
|
||||
'plugins/plugin-chart-point-cluster-map/src/images/MapBox2.jpg',
|
||||
],
|
||||
radar: [
|
||||
`${ECHARTS}/Radar/images/example1.jpg`,
|
||||
`${ECHARTS}/Radar/images/example2.jpg`,
|
||||
],
|
||||
rose: [
|
||||
`${ECHARTS}/Rose/images/example1.jpg`,
|
||||
`${ECHARTS}/Rose/images/example2.jpg`,
|
||||
],
|
||||
sankey_v2: [
|
||||
`${ECHARTS}/Sankey/images/example1.png`,
|
||||
`${ECHARTS}/Sankey/images/example2.png`,
|
||||
],
|
||||
sunburst_v2: [
|
||||
`${ECHARTS}/Sunburst/images/Sunburst1.png`,
|
||||
`${ECHARTS}/Sunburst/images/Sunburst2.png`,
|
||||
],
|
||||
table: [
|
||||
'plugins/plugin-chart-table/src/images/Table.jpg',
|
||||
'plugins/plugin-chart-table/src/images/Table2.jpg',
|
||||
'plugins/plugin-chart-table/src/images/Table3.jpg',
|
||||
],
|
||||
time_pivot: [`${ECHARTS}/TimePivot/images/example.jpg`],
|
||||
time_table: ['src/visualizations/TimeTable/images/example.jpg'],
|
||||
tree_chart: [`${ECHARTS}/Tree/images/tree.png`],
|
||||
treemap_v2: [
|
||||
`${ECHARTS}/Treemap/images/treemap_v2_1.png`,
|
||||
`${ECHARTS}/Treemap/images/treemap_v2_2.jpg`,
|
||||
],
|
||||
waterfall: [
|
||||
`${ECHARTS}/Waterfall/images/example1.png`,
|
||||
`${ECHARTS}/Waterfall/images/example2.png`,
|
||||
`${ECHARTS}/Waterfall/images/example3.png`,
|
||||
],
|
||||
word_cloud: [
|
||||
'plugins/plugin-chart-word-cloud/src/images/Word_Cloud.jpg',
|
||||
'plugins/plugin-chart-word-cloud/src/images/Word_Cloud_2.jpg',
|
||||
],
|
||||
world_map: [
|
||||
'plugins/plugin-chart-world-map/src/images/WorldMap1.jpg',
|
||||
'plugins/plugin-chart-world-map/src/images/WorldMap2.jpg',
|
||||
],
|
||||
deck_arc: [`${DECKGL}/Arc/images/example.png`],
|
||||
deck_contour: [`${DECKGL}/Contour/images/example.png`],
|
||||
deck_geojson: [`${DECKGL}/Geojson/images/example.png`],
|
||||
deck_grid: [`${DECKGL}/Grid/images/example.png`],
|
||||
deck_heatmap: [`${DECKGL}/Heatmap/images/example.png`],
|
||||
deck_hex: [`${DECKGL}/Hex/images/example.png`],
|
||||
deck_multi: ['plugins/preset-chart-deckgl/src/Multi/images/example.png'],
|
||||
deck_path: [`${DECKGL}/Path/images/example.png`],
|
||||
deck_polygon: [`${DECKGL}/Polygon/images/example.png`],
|
||||
deck_scatter: [`${DECKGL}/Scatter/images/example.png`],
|
||||
deck_screengrid: [`${DECKGL}/Screengrid/images/example.png`],
|
||||
};
|
||||
|
||||
interface ExampleChart {
|
||||
id: number;
|
||||
sliceName: string;
|
||||
vizType: string;
|
||||
}
|
||||
|
||||
interface DashboardRow {
|
||||
id: number;
|
||||
}
|
||||
|
||||
interface DashboardChartRow {
|
||||
id?: number;
|
||||
slice_name?: string;
|
||||
form_data?: { viz_type?: string };
|
||||
}
|
||||
|
||||
/** Pages through a list endpoint, returning every result row. */
|
||||
async function fetchAllPages<T>(page: Page, endpoint: string): Promise<T[]> {
|
||||
const rows: T[] = [];
|
||||
const pageSize = 100;
|
||||
for (let pageNum = 0; ; pageNum += 1) {
|
||||
const q = encodeURIComponent(
|
||||
`(page_size:${pageSize},page:${pageNum},order_direction:asc)`,
|
||||
);
|
||||
const response = await page.request.get(`${endpoint}?q=${q}`);
|
||||
expect(response.ok(), `GET ${endpoint} page ${pageNum}`).toBeTruthy();
|
||||
const { result }: { result: T[] } = await response.json();
|
||||
rows.push(...result);
|
||||
if (result.length < pageSize) return rows;
|
||||
}
|
||||
}
|
||||
|
||||
/** Discovers every chart placed on any dashboard. */
|
||||
async function discoverDashboardCharts(page: Page): Promise<ExampleChart[]> {
|
||||
const dashboards = await fetchAllPages<DashboardRow>(
|
||||
page,
|
||||
'/api/v1/dashboard/',
|
||||
);
|
||||
const chartsById = new Map<number, ExampleChart>();
|
||||
for (const dashboard of dashboards) {
|
||||
const response = await page.request.get(
|
||||
`/api/v1/dashboard/${dashboard.id}/charts`,
|
||||
);
|
||||
if (!response.ok()) continue;
|
||||
const { result }: { result: DashboardChartRow[] } = await response.json();
|
||||
for (const chart of result) {
|
||||
const vizType = chart.form_data?.viz_type;
|
||||
if (chart.id && chart.slice_name && vizType) {
|
||||
chartsById.set(chart.id, {
|
||||
id: chart.id,
|
||||
sliceName: chart.slice_name,
|
||||
vizType,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return [...chartsById.values()];
|
||||
}
|
||||
|
||||
/** thumbnail.png -> thumbnail-dark.png, example.jpg -> example-dark.jpg */
|
||||
function darkSibling(output: string): string {
|
||||
return output.replace(/\.(png|jpg)$/, '-dark.$1');
|
||||
}
|
||||
|
||||
async function renderAndShoot(
|
||||
page: Page,
|
||||
chart: ExampleChart,
|
||||
colorScheme: 'light' | 'dark',
|
||||
): Promise<Buffer> {
|
||||
// An explicit navigation timeout keeps one hung load from stalling the
|
||||
// whole crawl until the test timeout.
|
||||
await page.goto(`/explore/?slice_id=${chart.id}&standalone=1`, {
|
||||
timeout: 60_000,
|
||||
});
|
||||
// Dashboards render charts on colorBgContainer cards, but the standalone
|
||||
// explore page paints the gray colorBgLayout (via the antd Layout
|
||||
// wrapper); match the dashboard context so thumbnails look like charts
|
||||
// do where users see them.
|
||||
await page
|
||||
.addStyleTag({
|
||||
content: `body, .ant-layout { background: ${
|
||||
colorScheme === 'dark' ? '#141414' : '#ffffff'
|
||||
} !important; }`,
|
||||
})
|
||||
.catch(() => {});
|
||||
const textOnly = TEXT_ONLY_VIZ_TYPES.has(chart.vizType);
|
||||
await page
|
||||
.locator(textOnly ? TEXT_RENDERED_CHART_SELECTOR : RENDERED_CHART_SELECTOR)
|
||||
.first()
|
||||
.waitFor({ state: 'visible', timeout: 60_000 });
|
||||
// Give animations/map tiles (or text-only chart data) time to settle
|
||||
await page.waitForTimeout(textOnly ? 4_000 : 2_000);
|
||||
// Some thumbnails read better mid-interaction (e.g. the calendar heatmap
|
||||
// showing its tooltip); hover the configured element before the still.
|
||||
const hoverSelector = HOVER_BEFORE_CAPTURE[chart.vizType];
|
||||
if (hoverSelector) {
|
||||
// Hover a mid-chart element rather than the first (often an empty
|
||||
// corner cell), falling back to the first when there are few.
|
||||
const cells = page.locator(hoverSelector);
|
||||
const count = await cells.count().catch(() => 0);
|
||||
await cells
|
||||
.nth(Math.floor(count / 2))
|
||||
.hover({ timeout: 5_000 })
|
||||
.catch(() => {});
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
return page.screenshot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures a chart light and (when a dark variant is wanted) dark. Dark
|
||||
* rendering relies on the app following prefers-color-scheme (theme mode
|
||||
* SYSTEM); if the dark render is byte-identical to the light one the app
|
||||
* ignored the emulation, and the dark file is left untouched rather than
|
||||
* overwritten with light-theme art.
|
||||
*/
|
||||
async function captureChart(
|
||||
page: Page,
|
||||
chart: ExampleChart,
|
||||
output: string,
|
||||
size: { width: number; height: number },
|
||||
): Promise<void> {
|
||||
const outputPath = path.join(FRONTEND_ROOT, output);
|
||||
const darkPath = path.join(FRONTEND_ROOT, darkSibling(output));
|
||||
const isNewImage = !fs.existsSync(outputPath);
|
||||
const wantDark = fs.existsSync(darkPath) || isNewImage;
|
||||
|
||||
await page.setViewportSize(size);
|
||||
await page.emulateMedia({ colorScheme: 'light' });
|
||||
const lightShot = await renderAndShoot(page, chart, 'light');
|
||||
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
||||
fs.writeFileSync(outputPath, lightShot);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`captured ${chart.sliceName} (${chart.vizType}) -> ${output}`);
|
||||
|
||||
if (wantDark) {
|
||||
await page.emulateMedia({ colorScheme: 'dark' });
|
||||
const darkShot = await renderAndShoot(page, chart, 'dark');
|
||||
if (darkShot.equals(lightShot)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`SKIPPED dark variant for ${chart.sliceName}: the app ignored the dark color-scheme emulation (is dark theming enabled?)`,
|
||||
);
|
||||
} else {
|
||||
fs.writeFileSync(darkPath, darkShot);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`captured ${chart.sliceName} (dark) -> ${darkSibling(output)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewImage) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`NOTE: ${output} is a new gallery image — register it in the plugin metadata (exampleGallery) to surface it.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
test.describe('capture viz thumbnails', () => {
|
||||
test.skip(
|
||||
!process.env.CAPTURE_THUMBNAILS,
|
||||
'Thumbnail capture only runs with CAPTURE_THUMBNAILS=1',
|
||||
);
|
||||
|
||||
test('crawls example dashboards and refreshes gallery thumbnails', async ({
|
||||
page,
|
||||
}) => {
|
||||
test.setTimeout(90 * 60_000);
|
||||
|
||||
const vizTypeFilter = process.env.VIZ_TYPES
|
||||
? new Set(process.env.VIZ_TYPES.split(',').map(v => v.trim()))
|
||||
: null;
|
||||
|
||||
const charts = await discoverDashboardCharts(page);
|
||||
expect(
|
||||
charts.length,
|
||||
'no dashboard charts found — are examples loaded?',
|
||||
).toBeGreaterThan(0);
|
||||
|
||||
// Every distinct chart per viz type gets captured: the preferred (or
|
||||
// alphabetically-first) chart becomes the picker thumbnail, and each
|
||||
// subsequent distinct chart fills the next declared gallery slot, so
|
||||
// gallery images show real variety instead of the same chart resized.
|
||||
const byVizType = new Map<string, ExampleChart[]>();
|
||||
for (const chart of charts) {
|
||||
const group = byVizType.get(chart.vizType) ?? [];
|
||||
group.push(chart);
|
||||
byVizType.set(chart.vizType, group);
|
||||
}
|
||||
|
||||
const thumbnailSize = { width: THUMBNAIL_SIZE, height: THUMBNAIL_SIZE };
|
||||
const exampleSize = { width: EXAMPLE_WIDTH, height: EXAMPLE_HEIGHT };
|
||||
const unmapped: string[] = [];
|
||||
const underfilledGalleries: string[] = [];
|
||||
const failures: string[] = [];
|
||||
for (const [vizType, group] of [...byVizType.entries()].sort()) {
|
||||
if (vizTypeFilter && !vizTypeFilter.has(vizType)) continue;
|
||||
|
||||
const thumbOutput = VIZ_TYPE_THUMBNAILS[vizType];
|
||||
const galleryOutputs = VIZ_TYPE_GALLERY[vizType] ?? [];
|
||||
if (!thumbOutput && !galleryOutputs.length) {
|
||||
unmapped.push(vizType);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Preferred slice (if present) leads; the rest follow alphabetically.
|
||||
group.sort((a, b) => a.sliceName.localeCompare(b.sliceName));
|
||||
const preferredIndex = group.findIndex(
|
||||
c => c.sliceName === PREFERRED_SLICES[vizType],
|
||||
);
|
||||
const ordered =
|
||||
preferredIndex > 0
|
||||
? [
|
||||
group[preferredIndex],
|
||||
...group.slice(0, preferredIndex),
|
||||
...group.slice(preferredIndex + 1),
|
||||
]
|
||||
: group;
|
||||
|
||||
// Only advance past the thumbnail's chart when a thumbnail is
|
||||
// actually captured (e.g. handlebars has no VIZ_TYPE_THUMBNAILS
|
||||
// entry by design, so its gallery gets the full ordered list).
|
||||
let nextIndex = 0;
|
||||
if (thumbOutput) {
|
||||
const chart = ordered[0];
|
||||
nextIndex = 1;
|
||||
try {
|
||||
await captureChart(page, chart, thumbOutput, thumbnailSize);
|
||||
} catch (error) {
|
||||
failures.push(`${vizType} (${chart.sliceName}): ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
const missingSlots: string[] = [];
|
||||
for (const output of galleryOutputs) {
|
||||
const chart = ordered[nextIndex];
|
||||
nextIndex += 1;
|
||||
if (!chart) {
|
||||
missingSlots.push(output);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
await captureChart(page, chart, output, exampleSize);
|
||||
} catch (error) {
|
||||
failures.push(`${vizType} gallery (${chart.sliceName}): ${error}`);
|
||||
}
|
||||
}
|
||||
if (missingSlots.length) {
|
||||
underfilledGalleries.push(
|
||||
`${vizType}: not enough distinct dashboard charts for ${missingSlots.join(', ')}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (unmapped.length) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`viz types on dashboards with no thumbnail or gallery mapping (add to VIZ_TYPE_THUMBNAILS/VIZ_TYPE_GALLERY if wanted): ${unmapped.join(', ')}`,
|
||||
);
|
||||
}
|
||||
if (underfilledGalleries.length) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`gallery slots left untouched for lack of distinct example charts:\n${underfilledGalleries.join('\n')}`,
|
||||
);
|
||||
}
|
||||
expect(failures, failures.join('\n')).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 159 KiB |
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 141 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 32 KiB |
@@ -19,14 +19,14 @@
|
||||
import { t } from '@apache-superset/core/translation';
|
||||
import { Behavior, ChartMetadata, ChartPlugin } from '@superset-ui/core';
|
||||
import transformProps from './transformProps';
|
||||
import thumbnail from './images/thumbnail.png';
|
||||
import thumbnailDark from './images/thumbnail-dark.png';
|
||||
import example1 from './images/Table.jpg';
|
||||
import example1Dark from './images/Table-dark.jpg';
|
||||
import example2 from './images/Table2.jpg';
|
||||
import example2Dark from './images/Table2-dark.jpg';
|
||||
import example3 from './images/Table3.jpg';
|
||||
import example3Dark from './images/Table3-dark.jpg';
|
||||
import thumbnail from './images/custom_thumb_thumbnail.png';
|
||||
import thumbnailDark from './images/custom_thumb_thumbnail-dark.png';
|
||||
import example1 from './images/custom_thumb_Table.jpg';
|
||||
import example1Dark from './images/custom_thumb_Table-dark.jpg';
|
||||
import example2 from './images/custom_thumb_Table2.jpg';
|
||||
import example2Dark from './images/custom_thumb_Table2-dark.jpg';
|
||||
import example3 from './images/custom_thumb_Table3.jpg';
|
||||
import example3Dark from './images/custom_thumb_Table3-dark.jpg';
|
||||
import controlPanel from './controlPanel';
|
||||
import buildQuery from './buildQuery';
|
||||
import { TableChartFormData, TableChartProps } from './types';
|
||||
|
||||
@@ -22,7 +22,7 @@ import { getSequentialSchemeRegistry } from '@superset-ui/core';
|
||||
import { SupersetTheme } from '@apache-superset/core/theme';
|
||||
import { t } from '@apache-superset/core/translation';
|
||||
import CalHeatMapImport from './vendor/cal-heatmap';
|
||||
import { convertUTCTimestampToLocal, getFormattedUTCTime } from './utils';
|
||||
import { convertUTCTimestampToLocal } from './utils';
|
||||
|
||||
// The vendor file is @ts-nocheck, so its export lacks type info.
|
||||
// Define a minimal constructor interface for use in this file.
|
||||
@@ -103,8 +103,6 @@ function Calendar(element: HTMLElement, props: CalendarProps) {
|
||||
const subDomainTextFormat = showValues
|
||||
? (_date: Date, value: number) => valueFormatter(value)
|
||||
: null;
|
||||
const dateFormatter = (date: Date, format: string) =>
|
||||
getFormattedUTCTime(date.getTime(), format);
|
||||
|
||||
const metricsData = data.data;
|
||||
|
||||
@@ -168,7 +166,6 @@ function Calendar(element: HTMLElement, props: CalendarProps) {
|
||||
itemName: '',
|
||||
valueFormatter,
|
||||
timeFormatter,
|
||||
dateFormatter,
|
||||
subDomainTextFormat,
|
||||
});
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
@@ -19,8 +19,8 @@
|
||||
import { ChartMetadata, ChartPlugin } from '@superset-ui/core';
|
||||
import { t } from '@apache-superset/core/translation';
|
||||
import transformProps from './transformProps';
|
||||
import example from './images/example.jpg';
|
||||
import exampleDark from './images/example-dark.jpg';
|
||||
import example from './images/custom_thumb_example.jpg';
|
||||
import exampleDark from './images/custom_thumb_example-dark.jpg';
|
||||
import controlPanel from './controlPanel';
|
||||
import thumbnail from './images/thumbnail.png';
|
||||
import thumbnailDark from './images/thumbnail-dark.png';
|
||||
|
||||
@@ -76,8 +76,6 @@ var CalHeatMap = function () {
|
||||
|
||||
timeFormatter: d => d,
|
||||
|
||||
dateFormatter: null,
|
||||
|
||||
domain: 'hour',
|
||||
|
||||
subDomain: 'min',
|
||||
@@ -1992,14 +1990,10 @@ CalHeatMap.prototype = {
|
||||
|
||||
if (typeof format === 'function') {
|
||||
return format(d);
|
||||
} else {
|
||||
var f = d3.time.format(format);
|
||||
return f(d);
|
||||
}
|
||||
|
||||
if (typeof this.options.dateFormatter === 'function') {
|
||||
return this.options.dateFormatter(d, format);
|
||||
}
|
||||
|
||||
var f = d3.time.format(format);
|
||||
return f(d);
|
||||
},
|
||||
|
||||
getSubDomainTitle: function (d) {
|
||||
|
||||
@@ -25,11 +25,9 @@ import {
|
||||
waitFor,
|
||||
} from 'spec/helpers/testing-library';
|
||||
import { CALENDAR_TOOLTIP_CLASS } from '../src/tooltip';
|
||||
import { convertUTCTimestampToLocal } from '../src/utils';
|
||||
|
||||
interface MockCalHeatMapConfig {
|
||||
itemSelector: Element;
|
||||
dateFormatter?: (date: Date, format: string) => string;
|
||||
}
|
||||
|
||||
type MetricNameInput = string | string[];
|
||||
@@ -40,7 +38,6 @@ let mockInitCallCount = 0;
|
||||
let mockThrowOnInitCall: number | null = null;
|
||||
let mockDestroyCallCount = 0;
|
||||
let mockDestroyedInstanceIds: string[] = [];
|
||||
let mockDateFormatter: MockCalHeatMapConfig['dateFormatter'];
|
||||
|
||||
const mockTheme = {
|
||||
colorBgElevated: '#ffffff',
|
||||
@@ -59,7 +56,6 @@ jest.mock('../src/vendor/cal-heatmap', () => ({
|
||||
} = require('../src/tooltip');
|
||||
|
||||
mockInitCallCount += 1;
|
||||
mockDateFormatter = config.dateFormatter;
|
||||
if (mockThrowOnInitCall === mockInitCallCount) {
|
||||
throw new Error('Mock CalHeatMap init failure');
|
||||
}
|
||||
@@ -288,28 +284,9 @@ afterEach(() => {
|
||||
mockThrowOnInitCall = null;
|
||||
mockDestroyCallCount = 0;
|
||||
mockDestroyedInstanceIds = [];
|
||||
mockDateFormatter = undefined;
|
||||
document.body.innerHTML = '';
|
||||
});
|
||||
|
||||
test('Calendar provides a timezone-safe date formatter to CalHeatMap', () => {
|
||||
const calendarOwner = document.createElement('div');
|
||||
document.body.appendChild(calendarOwner);
|
||||
|
||||
Calendar(calendarOwner, {
|
||||
...createCalendarProps('localized-metric'),
|
||||
theme: mockTheme,
|
||||
});
|
||||
|
||||
if (!mockDateFormatter) {
|
||||
throw new Error('Expected Calendar to configure a date formatter');
|
||||
}
|
||||
|
||||
const localDate = new Date(convertUTCTimestampToLocal(Date.UTC(2024, 0, 1)));
|
||||
|
||||
expect(mockDateFormatter(localDate, '%Y-%m-%d')).toBe('2024-01-01');
|
||||
});
|
||||
|
||||
test('rerender and unmount clean up only the affected calendar tooltips', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import CalHeatMapImport from '../src/vendor/cal-heatmap';
|
||||
|
||||
type DateFormatter = (date: Date, format: string) => string;
|
||||
type FunctionalDateFormat = (date: Date) => string;
|
||||
|
||||
interface CalHeatMapInstance {
|
||||
options: {
|
||||
dateFormatter: DateFormatter | null;
|
||||
};
|
||||
formatDate(date: Date, format: string | FunctionalDateFormat): string;
|
||||
}
|
||||
|
||||
const CalHeatMap = CalHeatMapImport as unknown as new () => CalHeatMapInstance;
|
||||
|
||||
test('CalHeatMap delegates string date formats to the configured formatter', () => {
|
||||
const calendar = new CalHeatMap();
|
||||
const date = new Date(2024, 0, 1);
|
||||
const dateFormatter = jest.fn<string, [Date, string]>(() => 'Январь');
|
||||
calendar.options.dateFormatter = dateFormatter;
|
||||
|
||||
expect(calendar.formatDate(date, '%B')).toBe('Январь');
|
||||
expect(dateFormatter).toHaveBeenCalledWith(date, '%B');
|
||||
});
|
||||
|
||||
test('CalHeatMap preserves functional formatters over the configured formatter', () => {
|
||||
const calendar = new CalHeatMap();
|
||||
const date = new Date(2024, 0, 1);
|
||||
const dateFormatter = jest.fn<string, [Date, string]>(() => 'localized');
|
||||
const functionalFormat = jest.fn<string, [Date]>(() => 'custom');
|
||||
calendar.options.dateFormatter = dateFormatter;
|
||||
|
||||
expect(calendar.formatDate(date, functionalFormat)).toBe('custom');
|
||||
expect(functionalFormat).toHaveBeenCalledWith(date);
|
||||
expect(dateFormatter).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('CalHeatMap keeps the D3 formatter fallback', () => {
|
||||
const calendar = new CalHeatMap();
|
||||
const date = new Date(2024, 0, 1);
|
||||
|
||||
expect(calendar.formatDate(date, '%B')).toBe('January');
|
||||
});
|
||||
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 268 KiB After Width: | Height: | Size: 268 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
@@ -21,12 +21,12 @@ import { ChartMetadata, ChartPlugin } from '@superset-ui/core';
|
||||
import buildQuery from './buildQuery';
|
||||
import controlPanel from './controlPanel';
|
||||
import transformProps from './transformProps';
|
||||
import thumbnail from '../images/thumbnail.png';
|
||||
import thumbnailDark from '../images/thumbnail-dark.png';
|
||||
import example1 from '../images/example1.png';
|
||||
import example1Dark from '../images/example1-dark.png';
|
||||
import example2 from '../images/example2.png';
|
||||
import example2Dark from '../images/example2-dark.png';
|
||||
import thumbnail from '../images/custom_thumb_thumbnail.png';
|
||||
import thumbnailDark from '../images/custom_thumb_thumbnail-dark.png';
|
||||
import example1 from '../images/custom_thumb_example1.png';
|
||||
import example1Dark from '../images/custom_thumb_example1-dark.png';
|
||||
import example2 from '../images/custom_thumb_example2.png';
|
||||
import example2Dark from '../images/custom_thumb_example2-dark.png';
|
||||
import { CartodiagramPluginConstructorOpts } from '../types';
|
||||
import { getLayerConfig } from '../util/controlPanelUtil';
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 230 KiB |
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 228 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 59 KiB |
@@ -19,10 +19,10 @@
|
||||
import { t } from '@apache-superset/core/translation';
|
||||
import { ChartMetadata, ChartPlugin, Behavior } from '@superset-ui/core';
|
||||
import transformProps from './transformProps';
|
||||
import exampleUsa from './images/exampleUsa.jpg';
|
||||
import exampleUsaDark from './images/exampleUsa-dark.jpg';
|
||||
import exampleGermany from './images/exampleGermany.jpg';
|
||||
import exampleGermanyDark from './images/exampleGermany-dark.jpg';
|
||||
import exampleUsa from './images/custom_thumb_exampleUsa.jpg';
|
||||
import exampleUsaDark from './images/custom_thumb_exampleUsa-dark.jpg';
|
||||
import exampleGermany from './images/custom_thumb_exampleGermany.jpg';
|
||||
import exampleGermanyDark from './images/custom_thumb_exampleGermany-dark.jpg';
|
||||
import thumbnail from './images/thumbnail.png';
|
||||
import thumbnailDark from './images/thumbnail-dark.png';
|
||||
import controlPanel from './controlPanel';
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -21,8 +21,8 @@ import { ChartMetadata, ChartPlugin } from '@superset-ui/core';
|
||||
import buildQuery from './buildQuery';
|
||||
import controlPanel from './controlPanel';
|
||||
import transformProps from './transformProps';
|
||||
import thumbnail from './images/thumbnail.png';
|
||||
import thumbnailDark from './images/thumbnail-dark.png';
|
||||
import thumbnail from './images/custom_thumb_thumbnail.png';
|
||||
import thumbnailDark from './images/custom_thumb_thumbnail-dark.png';
|
||||
|
||||
export default class PopKPIPlugin extends ChartPlugin {
|
||||
constructor() {
|
||||
|
||||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 36 KiB |