This is an automated email from the ASF dual-hosted git repository.

jli pushed a commit to branch alert-report-test-gaps
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 7136c04c3fdc3064183c30e65d00579cf1e892f2
Merge: 1d762b94529 a6c0d6321f6
Author: Joe Li <[email protected]>
AuthorDate: Fri Mar 6 13:44:32 2026 -0800

    Merge remote-tracking branch 'origin/master' into alert-report-test-gaps
    
    # Conflicts:
    #       superset-frontend/src/features/alerts/AlertReportModal.test.tsx

 .devcontainer/devcontainer.json                    |    2 +-
 .github/workflows/docker.yml                       |    2 +-
 .gitignore                                         |    2 +-
 RESOURCES/INTHEWILD.yaml                           |    3 +
 UPDATING.md                                        |    8 +-
 docs/.gitignore                                    |    8 +-
 docs/.nvmrc                                        |    2 +-
 docs/admin_docs/configuration/alerts-reports.mdx   |   14 +
 docs/admin_docs/configuration/cache.mdx            |   16 +-
 docs/babel.config.js                               |   32 -
 docs/developer_docs/api.mdx                        |   36 +-
 docs/developer_docs/extensions/architecture.md     |   66 +-
 .../developer_docs/extensions/components/alert.mdx |    6 +-
 .../developer_docs/extensions/components/index.mdx |    8 +-
 .../extensions/contribution-types.md               |  255 ++-
 docs/developer_docs/extensions/dependencies.md     |    6 +-
 docs/developer_docs/extensions/development.md      |  210 +-
 .../extensions/extension-points/editors.md         |   49 +-
 .../extensions/extension-points/sqllab.md          |  173 +-
 docs/developer_docs/extensions/mcp-server.md       |  679 ++++++
 docs/developer_docs/extensions/mcp.md              |    6 +-
 docs/developer_docs/extensions/overview.md         |    6 +-
 docs/developer_docs/extensions/quick-start.md      |  164 +-
 docs/developer_docs/extensions/registry.md         |   14 +-
 docs/developer_docs/extensions/tasks.md            |   14 +-
 docs/developer_docs/sidebars.js                    |    1 +
 docs/docusaurus.config.ts                          |   28 +
 docs/package.json                                  |   17 +-
 docs/scripts/generate-database-docs.mjs            |    8 +-
 docs/scripts/generate-extension-components.mjs     |  676 ------
 docs/scripts/generate-if-changed.mjs               |  307 +++
 docs/scripts/generate-superset-components.mjs      |  241 ++-
 docs/sidebarTutorials.js                           |   11 -
 docs/src/components/StorybookWrapper.jsx           |    4 +-
 docs/src/components/databases/DatabaseIndex.tsx    |    1 +
 .../components/ui-components/ComponentIndex.tsx    |  262 +++
 .../src/components/ui-components}/index.ts         |    6 +-
 .../src/components/ui-components/types.ts          |   36 +-
 docs/src/data/databases.json                       |   12 +-
 docs/src/shims/superset-ui-core.ts                 |   57 +
 docs/src/theme/Playground/Preview/index.tsx        |    2 +-
 docs/src/theme/ReactLiveScope/index.tsx            |    2 +-
 docs/src/types/apache-superset-core/index.d.ts     |    6 +-
 docs/src/webpack.extend.ts                         |   19 +-
 .../{sql-snippets.png => editor-snippets.png}      |  Bin
 docs/tsconfig.json                                 |    7 +-
 docs/yarn.lock                                     | 1288 ++++++++---
 pyproject.toml                                     |    8 +-
 requirements/base.in                               |    4 +-
 requirements/base.txt                              |   16 +-
 requirements/development.txt                       |   26 +-
 superset-core/README.md                            |    4 +-
 superset-core/src/superset_core/api/rest_api.py    |   72 -
 .../src/superset_core/{api => common}/__init__.py  |    0
 .../src/superset_core/{api => common}/daos.py      |   82 +-
 .../src/superset_core/{api => common}/models.py    |  192 +-
 .../src/superset_core/extensions/types.py          |  109 +-
 superset-core/src/superset_core/mcp/__init__.py    |  145 --
 .../mcp/{__init__.py => decorators.py}             |    2 +-
 .../src/superset_core/{api => queries}/__init__.py |    0
 superset-core/src/superset_core/queries/daos.py    |   63 +
 superset-core/src/superset_core/queries/models.py  |   79 +
 .../src/superset_core/{api => queries}/query.py    |    4 +-
 .../src/superset_core/{api => queries}/types.py    |    0
 .../superset_core/{api => rest_api}/__init__.py    |    0
 .../{api/__init__.py => rest_api/api.py}           |   16 +
 .../src/superset_core/rest_api/decorators.py       |  103 +
 .../src/superset_core/{api => tasks}/__init__.py   |    0
 superset-core/src/superset_core/tasks/daos.py      |   76 +
 .../src/superset_core/tasks/decorators.py          |  152 ++
 superset-core/src/superset_core/tasks/models.py    |  169 ++
 .../superset_core/{api/tasks.py => tasks/types.py} |  128 +-
 superset-embedded-sdk/.nvmrc                       |    2 +-
 .../src/superset_extensions_cli/cli.py             |  144 +-
 .../templates/backend/pyproject.toml.j2            |    7 +
 .../templates/backend/src/package/__init__.py.j2   |    0
 .../templates/extension.json.j2                    |   20 -
 .../templates/frontend/src/index.tsx.j2            |   17 +-
 .../templates/frontend/webpack.config.js.j2        |    3 +-
 .../src/superset_extensions_cli/types.py           |    4 +-
 .../src/superset_extensions_cli/utils.py           |    2 +-
 superset-extensions-cli/tests/conftest.py          |    9 +-
 superset-extensions-cli/tests/test_cli_build.py    |  237 +-
 superset-extensions-cli/tests/test_cli_bundle.py   |    5 +-
 superset-extensions-cli/tests/test_cli_init.py     |   32 +-
 superset-extensions-cli/tests/test_cli_validate.py |   14 +-
 .../tests/test_name_transformations.py             |   11 +-
 superset-extensions-cli/tests/test_templates.py    |   55 +-
 superset-frontend/.eslintrc.js                     |   41 -
 superset-frontend/.nvmrc                           |    2 +-
 superset-frontend/.storybook/preview.jsx           |    2 +-
 .../.storybook/shared/ResizableChartDemo.tsx       |    2 +-
 .../.storybook/shared/ResizablePanel.tsx           |    2 +-
 superset-frontend/.storybook/shared/VerifyCORS.tsx |    2 +-
 .../e2e/dashboard/_skip.nativeFilters.test.ts      |    4 +-
 .../cypress/e2e/dashboard_list/filter.test.ts      |   47 -
 .../cypress/e2e/dashboard_list/list.test.ts        |  279 ---
 superset-frontend/oxlint.json                      |    4 +-
 superset-frontend/package-lock.json                | 2282 ++++++++------------
 superset-frontend/package.json                     |   24 +-
 .../packages/generator-superset/package.json       |    2 +-
 .../packages/superset-core/package.json            |   62 +
 .../superset-core/src/api/contributions.ts         |  147 --
 .../packages/superset-core/src/api/index.ts        |   42 -
 .../authentication.ts => authentication/index.ts}  |    0
 .../src/{api/commands.ts => commands/index.ts}     |   51 +-
 .../src/{api/core.ts => common/index.ts}           |   74 +-
 .../{ui => }/components/Alert/Alert.stories.tsx    |    0
 .../src/{ui => }/components/Alert/Alert.test.tsx   |    0
 .../src/{ui => }/components/Alert/index.tsx        |    0
 .../superset-core/src/{ui => }/components/index.ts |    0
 .../superset-core/src/contributions/index.ts       |   85 +
 .../src/{api/editors.ts => editors/index.ts}       |  105 +-
 .../src/{api/extensions.ts => extensions/index.ts} |    2 +-
 .../packages/superset-core/src/index.ts            |   16 +-
 .../packages/superset-core/src/menus/index.ts      |  104 +
 .../src/{api/sqlLab.ts => sqlLab/index.ts}         |    4 +-
 .../superset-core/src/{ui => }/testing.tsx         |    0
 .../src/{ui => }/theme/GlobalStyles.tsx            |   11 +
 .../src/{ui => }/theme/Theme.test.tsx              |   73 +
 .../superset-core/src/{ui => }/theme/Theme.tsx     |   14 +
 .../src/{ui => }/theme/exampleThemes.ts            |    0
 .../superset-core/src/{ui => }/theme/index.tsx     |    0
 .../superset-core/src/{ui => }/theme/types.ts      |    0
 .../src/{ui => }/theme/utils/index.ts              |    0
 .../src/{ui => }/theme/utils/themeUtils.test.ts    |    0
 .../src/{ui => }/theme/utils/themeUtils.ts         |    0
 .../src/{ui => }/theme/utils/utils.test.ts         |    0
 .../src/{ui => }/translation/README.md             |    0
 .../src/{ui => }/translation/Translator.ts         |    2 +-
 .../{ui => }/translation/TranslatorSingleton.ts    |    0
 .../src/{ui => }/translation/index.ts              |    0
 .../src/{ui => }/translation/types/index.ts        |    0
 .../src/{ui => }/translation/types/jed.ts          |    0
 .../src/{spec => }/utils/logging.test.ts           |    4 +-
 .../packages/superset-core/src/views/index.ts      |   90 +
 .../src/components/CertifiedIconWithTooltip.tsx    |    4 +-
 .../src/components/ColumnOption.tsx                |    2 +-
 .../components/ColumnTypeLabel/ColumnTypeLabel.tsx |    6 +-
 .../src/components/ControlHeader.tsx               |    4 +-
 .../src/components/ControlSubSectionHeader.tsx     |    2 +-
 .../src/components/MetricOption.tsx                |    2 +-
 .../src/components/SQLPopover.tsx                  |    4 +-
 .../src/components/labelUtils.tsx                  |    4 +-
 .../superset-ui-chart-controls/src/constants.ts    |    4 +-
 .../superset-ui-chart-controls/src/fixtures.ts     |    2 +-
 .../src/sections/advancedAnalytics.tsx             |    2 +-
 .../src/sections/annotationsAndLayers.tsx          |    2 +-
 .../src/sections/chartTitle.tsx                    |    2 +-
 .../src/sections/echartsTimeSeriesQuery.tsx        |    2 +-
 .../src/sections/forecastInterval.tsx              |    2 +-
 .../src/sections/matrixify.tsx                     |    2 +-
 .../src/sections/sections.tsx                      |    2 +-
 .../src/sections/timeComparison.tsx                |    2 +-
 .../components/RadioButtonControl.tsx              |    2 +-
 .../src/shared-controls/customControls.tsx         |    4 +-
 .../src/shared-controls/dndControls.tsx            |    4 +-
 .../src/shared-controls/matrixifyControls.tsx      |    2 +-
 .../src/shared-controls/mixins.tsx                 |    2 +-
 .../src/shared-controls/sharedControls.tsx         |   17 +-
 .../superset-ui-chart-controls/src/types.ts        |    3 +-
 .../src/utils/D3Formatting.ts                      |    2 +-
 .../src/utils/checkColumnType.ts                   |    2 +-
 .../src/utils/columnChoices.ts                     |    2 +-
 .../src/utils/getColorFormatters.ts                |    2 +-
 .../src/utils/isSortable.ts                        |    2 +-
 .../src/utils/metricColumnFilter.test.ts           |    8 +
 .../test/components/ColumnOption.test.tsx          |    2 +-
 .../test/components/ColumnTypeLabel.test.tsx       |    2 +-
 .../test/shared-controls/customControls.test.tsx   |    2 +-
 .../test/utils/checkColumnType.test.ts             |    2 +-
 .../test/utils/columnChoices.test.tsx              |    2 +-
 .../test/utils/getColorFormatters.test.ts          |   43 +-
 .../test/utils/getTemporalColumns.test.ts          |    2 +-
 .../test/utils/isSortable.test.ts                  |    2 +-
 .../packages/superset-ui-core/package.json         |    2 +-
 .../src/chart/components/FallbackComponent.tsx     |    4 +-
 .../Matrixify/MatrixifyGridCell.test.tsx           |    2 +-
 .../components/Matrixify/MatrixifyGridCell.tsx     |    4 +-
 .../Matrixify/MatrixifyGridGenerator.test.ts       |  120 +
 .../components/Matrixify/MatrixifyGridGenerator.ts |    8 +-
 .../Matrixify/MatrixifyGridRenderer.test.tsx       |    4 +-
 .../components/Matrixify/MatrixifyGridRenderer.tsx |    2 +-
 .../src/chart/components/NoResultsComponent.tsx    |    3 +-
 .../src/chart/components/StatefulChart.tsx         |    2 +-
 .../src/chart/components/SuperChartCore.tsx        |    2 +-
 .../src/chart/models/ChartProps.ts                 |    2 +-
 .../src/chart/types/matrixify.mocks.test.ts        |   11 +-
 .../src/chart/types/matrixify.test.ts              |   82 +
 .../superset-ui-core/src/chart/types/matrixify.ts  |   36 +-
 .../src/components/ActionButton/index.tsx          |    2 +-
 .../src/components/AsyncAceEditor/index.tsx        |    8 +-
 .../AsyncAceEditor/useJsonValidation.test.ts       |   25 +
 .../src/components/Badge/index.tsx                 |    2 +-
 .../src/components/Button/index.tsx                |    2 +-
 .../src/components/CachedLabel/TooltipContent.tsx  |    2 +-
 .../src/components/CachedLabel/index.tsx           |    2 +-
 .../superset-ui-core/src/components/Card/index.tsx |    2 +-
 .../CertifiedBadge/CertifiedBadge.stories.tsx      |    2 +-
 .../src/components/CertifiedBadge/index.tsx        |    4 +-
 .../src/components/Checkbox/CheckboxIcons.tsx      |    2 +-
 .../src/components/CodeSyntaxHighlighter/index.tsx |    2 +-
 .../src/components/Collapse/Collapse.tsx           |    2 +-
 .../components/Collapse/CollapseLabelInModal.tsx   |    2 +-
 .../components/ConfirmModal/ConfirmModal.test.tsx  |    2 +-
 .../src/components/ConfirmModal/index.tsx          |    4 +-
 .../src/components/CronPicker/index.tsx            |    4 +-
 .../src/components/DatePicker/index.tsx            |    2 +-
 .../src/components/DeleteModal/index.tsx           |    4 +-
 .../src/components/Divider/index.tsx               |    2 +-
 .../src/components/Dropdown/index.tsx              |    2 +-
 .../src/components/DropdownButton/index.tsx        |    2 +-
 .../DropdownContainer.stories.tsx                  |    2 +-
 .../DropdownContainer/DropdownContainer.tsx        |    4 +-
 .../src/components/DynamicEditableTitle/index.tsx  |    4 +-
 .../src/components/EditableTitle/index.tsx         |    4 +-
 .../src/components/EmptyState/index.tsx            |    4 +-
 .../src/components/FaveStar/index.tsx              |    4 +-
 .../src/components/Flex/Flex.stories.tsx           |    2 +-
 .../src/components/Form/FormItem.tsx               |    2 +-
 .../src/components/Form/FormLabel.tsx              |    2 +-
 .../src/components/Form/LabeledErrorBoundInput.tsx |    4 +-
 .../src/components/IconButton/index.tsx            |    2 +-
 .../components/IconTooltip/IconTooltip.stories.tsx |    2 +-
 .../src/components/Icons/BaseIcon.tsx              |    2 +-
 .../src/components/Icons/Icons.stories.tsx         |    2 +-
 .../src/components/InfoTooltip/index.tsx           |    4 +-
 .../src/components/Label/index.tsx                 |    2 +-
 .../components/Label/reusable/DatasetTypeLabel.tsx |    4 +-
 .../components/Label/reusable/PublishedLabel.tsx   |    4 +-
 .../src/components/LastUpdated/index.tsx           |    4 +-
 .../src/components/List/List.test.tsx              |   10 +
 .../superset-ui-core/src/components/List/index.ts  |    2 +-
 .../src/components/ListViewCard/ImageLoader.tsx    |    4 +-
 .../src/components/ListViewCard/index.tsx          |    2 +-
 .../src/components/Loading/index.test.tsx          |    2 +-
 .../src/components/Loading/index.tsx               |    4 +-
 .../superset-ui-core/src/components/Menu/index.tsx |    2 +-
 .../src/components/Metadata/index.tsx              |    2 +-
 .../src/components/MetadataBar/ContentConfig.tsx   |    4 +-
 .../components/MetadataBar/MetadataBar.stories.tsx |    2 +-
 .../components/MetadataBar/MetadataBar.test.tsx    |    2 +-
 .../src/components/MetadataBar/MetadataBar.tsx     |    2 +-
 .../src/components/Modal/FormModal.tsx             |    2 +-
 .../src/components/Modal/Modal.tsx                 |    4 +-
 .../src/components/PageHeaderWithActions/index.tsx |    4 +-
 .../src/components/PopoverDropdown/index.tsx       |    2 +-
 .../src/components/PopoverSection/index.tsx        |    2 +-
 .../src/components/ProgressBar/index.tsx           |    2 +-
 .../src/components/Radio/Radio.stories.tsx         |    2 +-
 .../src/components/RefreshLabel/index.tsx          |    2 +-
 .../src/components/Select/AsyncSelect.tsx          |    2 +-
 .../src/components/Select/Select.tsx               |    2 +-
 .../src/components/Select/constants.test.ts        |   49 +
 .../src/components/Select/constants.ts             |    2 +-
 .../src/components/Select/styles.tsx               |    5 +-
 .../src/components/Select/utils.tsx                |    2 +-
 .../src/components/Table/VirtualTable.tsx          |    2 +-
 .../Table/cell-renderers/ActionCell/index.tsx      |    2 +-
 .../Table/cell-renderers/NullCell/index.tsx        |    2 +-
 .../Table/cell-renderers/NumericCell/index.tsx     |    2 +-
 .../header-renderers/HeaderWithRadioGroup.tsx      |    2 +-
 .../src/components/Table/index.tsx                 |    6 +-
 .../Table/utils/InteractiveTableUtils.test.ts      |  574 +++++
 .../src/components/TableCollection/index.tsx       |    2 +-
 .../src/components/TableView/TableView.tsx         |    2 +-
 .../superset-ui-core/src/components/Tabs/Tabs.tsx  |    2 +-
 .../ThemedAgGridReact/ThemedAgGridReact.test.tsx   |    8 +-
 .../src/components/ThemedAgGridReact/index.tsx     |    2 +-
 .../src/components/Timer/index.tsx                 |    2 +-
 .../src/components/TimezoneSelector/index.tsx      |    2 +-
 .../src/components/TruncatedList/index.tsx         |    4 +-
 .../src/components/Typography/index.tsx            |    2 +-
 .../src/components/UnsavedChangesModal/index.tsx   |    2 +-
 .../components/WarningIconWithTooltip/index.tsx    |    2 +-
 .../superset-ui-core/src/components/constants.ts   |    2 +-
 .../superset-ui-core/src/components/index.ts       |    1 +
 .../src/query/extractQueryFields.ts                |    2 +-
 .../src/query/getClientErrorObject.ts              |    2 +-
 .../superset-ui-core/src/query/types/Column.ts     |    2 +-
 .../superset-ui-core/src/query/types/Query.ts      |    2 +-
 .../src/query/types/QueryResponse.ts               |    2 +-
 .../packages/superset-ui-core/src/spec/index.tsx   |    2 +-
 .../src/style/stories/Theme.stories.tsx            |    2 +-
 .../src/types/react-syntax-highlighter.d.ts        |    7 -
 .../superset-ui-core/src/utils/featureFlags.ts     |    2 +-
 .../src/utils/rankedSearchCompare.test.ts          |   20 +
 .../packages/superset-ui-core/src/utils/tooltip.ts |    2 +-
 .../List/List.test.tsx => utils/withLabel.test.ts} |   33 +-
 .../src/validator/legacyValidateInteger.ts         |    2 +-
 .../src/validator/legacyValidateNumber.ts          |    2 +-
 .../src/validator/validateInteger.ts               |    2 +-
 .../src/validator/validateMapboxStylesUrl.ts       |    2 +-
 .../src/validator/validateMaxValue.ts              |    2 +-
 .../src/validator/validateNonEmpty.ts              |    2 +-
 .../src/validator/validateNumber.ts                |    2 +-
 .../src/validator/validateServerPagination.ts      |    2 +-
 .../validator/validateTimeComparisonRangeValues.ts |    2 +-
 .../test/chart/clients/ChartClient.test.ts         |    2 +-
 .../test/chart/components/MockChartPlugins.tsx     |    2 +-
 .../test/chart/components/SuperChartCore.test.tsx  |    2 +-
 .../test/chart/models/ChartPlugin.test.tsx         |    2 +-
 .../test/chart/models/ChartProps.test.ts           |    2 +-
 .../Icons/AsyncIcon.integration.test.tsx           |    2 +-
 .../test/connection/SupersetClient.test.ts         |    6 +
 .../test/connection/SupersetClientClass.test.ts    |   33 +
 .../test/currency-format/CurrencyFormatter.test.ts |   78 +
 .../test/currency-format/utils.test.ts             |  193 ++
 .../packages/superset-ui-core/test/fixtures.ts     |    2 +-
 .../test/query/extractQueryFields.test.ts          |    2 +-
 .../test/query/types/Column.test.ts                |   14 +
 .../test/query/types/Dashboard.test.ts             |   33 +
 .../test/utils/featureFlag.test.ts                 |    4 +-
 .../superset-ui-core/test/validator/setup.ts       |    2 +-
 .../playwright/helpers/api/dashboard.ts            |  170 ++
 .../playwright/helpers/fixtures/testAssets.ts      |   24 +-
 .../playwright/pages/DashboardListPage.ts          |  139 ++
 .../experimental/dashboard/dashboard-list.spec.ts  |  403 ++++
 .../dashboard/dashboard-test-helpers.ts            |   74 +
 .../legacy-plugin-chart-calendar/src/Calendar.ts   |    3 +-
 .../src/ReactCalendar.tsx                          |    2 +-
 .../src/controlPanel.ts                            |    2 +-
 .../legacy-plugin-chart-calendar/src/index.ts      |    2 +-
 .../src/vendor/cal-heatmap.ts                      |    2 +-
 .../legacy-plugin-chart-chord/src/ReactChord.tsx   |    2 +-
 .../legacy-plugin-chart-chord/src/controlPanel.ts  |    2 +-
 .../plugins/legacy-plugin-chart-chord/src/index.ts |    2 +-
 .../src/ReactCountryMap.tsx                        |    2 +-
 .../src/controlPanel.ts                            |    2 +-
 .../legacy-plugin-chart-country-map/src/index.ts   |    2 +-
 .../src/stories/CountryMap.stories.tsx             |    2 +-
 .../src/HorizonChart.tsx                           |    2 +-
 .../src/controlPanel.ts                            |    2 +-
 .../legacy-plugin-chart-horizon/src/index.ts       |    2 +-
 .../src/controlPanel.ts                            |    2 +-
 .../legacy-plugin-chart-map-box/src/index.ts       |    2 +-
 .../src/stories/MapBox.stories.tsx                 |    2 +-
 .../src/stories/data.ts                            |    2 +-
 .../src/PairedTTest.tsx                            |    2 +-
 .../src/controlPanel.ts                            |    2 +-
 .../legacy-plugin-chart-paired-t-test/src/index.ts |    2 +-
 .../src/ReactParallelCoordinates.tsx               |    2 +-
 .../src/controlPanel.ts                            |    2 +-
 .../src/index.ts                                   |    2 +-
 .../src/ReactPartition.tsx                         |    2 +-
 .../src/controlPanel.tsx                           |    2 +-
 .../legacy-plugin-chart-partition/src/index.ts     |    2 +-
 .../legacy-plugin-chart-rose/src/ReactRose.tsx     |    2 +-
 .../legacy-plugin-chart-rose/src/controlPanel.tsx  |    2 +-
 .../plugins/legacy-plugin-chart-rose/src/index.ts  |    2 +-
 .../src/ReactWorldMap.tsx                          |    2 +-
 .../src/controlPanel.ts                            |    2 +-
 .../legacy-plugin-chart-world-map/src/index.ts     |    2 +-
 .../src/DeckGLContainer.tsx                        |    2 +-
 .../src/Multi/Multi.test.tsx                       |    2 +-
 .../legacy-preset-chart-deckgl/src/Multi/Multi.tsx |    2 +-
 .../src/Multi/controlPanel.ts                      |    2 +-
 .../legacy-preset-chart-deckgl/src/Multi/index.ts  |    2 +-
 .../src/components/Legend.tsx                      |    2 +-
 .../src/components/Tooltip.tsx                     |    2 +-
 .../src/layers/Arc/controlPanel.ts                 |    2 +-
 .../src/layers/Arc/index.ts                        |    2 +-
 .../src/layers/Contour/Contour.tsx                 |    2 +-
 .../src/layers/Contour/controlPanel.ts             |    2 +-
 .../src/layers/Contour/index.ts                    |    2 +-
 .../src/layers/Geojson/controlPanel.ts             |    2 +-
 .../src/layers/Geojson/index.ts                    |    2 +-
 .../src/layers/Grid/controlPanel.ts                |    2 +-
 .../src/layers/Grid/index.ts                       |    2 +-
 .../src/layers/Heatmap/Heatmap.tsx                 |    2 +-
 .../src/layers/Heatmap/controlPanel.ts             |    2 +-
 .../src/layers/Heatmap/index.ts                    |    2 +-
 .../src/layers/Hex/controlPanel.ts                 |    2 +-
 .../src/layers/Hex/index.ts                        |    2 +-
 .../src/layers/Path/controlPanel.ts                |    2 +-
 .../src/layers/Path/index.ts                       |    2 +-
 .../src/layers/Path/stories/Path.stories.tsx       |    2 +-
 .../src/layers/Polygon/Polygon.test.tsx            |    2 +-
 .../src/layers/Polygon/Polygon.tsx                 |    2 +-
 .../src/layers/Polygon/controlPanel.ts             |    2 +-
 .../src/layers/Polygon/index.ts                    |    2 +-
 .../src/layers/Scatter/Scatter.tsx                 |    2 +-
 .../src/layers/Scatter/controlPanel.ts             |    2 +-
 .../src/layers/Scatter/index.ts                    |    2 +-
 .../src/layers/Screengrid/Screengrid.tsx           |    4 +-
 .../src/layers/Screengrid/controlPanel.ts          |    2 +-
 .../src/layers/Screengrid/index.ts                 |    2 +-
 .../src/layers/spatialUtils.test.ts                |    2 +-
 .../src/utilities/HandlebarsRenderer.tsx           |    4 +-
 .../src/utilities/Shared_DeckGL.tsx                |    2 +-
 .../src/utilities/TooltipTemplateControl.tsx       |    4 +-
 .../src/utilities/TooltipTemplateEditor.tsx        |    2 +-
 .../src/utilities/sharedDndControls.tsx            |    2 +-
 .../src/utilities/tooltipUtils.tsx                 |    2 +-
 .../src/Bubble/controlPanel.ts                     |    2 +-
 .../legacy-preset-chart-nvd3/src/Bubble/index.ts   |    2 +-
 .../src/Bullet/controlPanel.ts                     |    2 +-
 .../legacy-preset-chart-nvd3/src/Bullet/index.ts   |    2 +-
 .../src/Compare/controlPanel.ts                    |    2 +-
 .../legacy-preset-chart-nvd3/src/Compare/index.ts  |    2 +-
 .../legacy-preset-chart-nvd3/src/NVD3Controls.tsx  |    2 +-
 .../legacy-preset-chart-nvd3/src/NVD3Vis.ts        |    2 +-
 .../legacy-preset-chart-nvd3/src/ReactNVD3.tsx     |    2 +-
 .../src/TimePivot/controlPanel.ts                  |    2 +-
 .../src/TimePivot/index.ts                         |    2 +-
 .../src/vendor/superset/AnnotationTypes.ts         |    2 +-
 .../src/AgGridTable/components/CustomHeader.tsx    |    2 +-
 .../src/AgGridTable/components/Pagination.tsx      |    2 +-
 .../components/TimeComparisonVisibility.tsx        |    2 +-
 .../src/AgGridTable/index.tsx                      |    2 +-
 .../src/AgGridTableChart.tsx                       |    4 +-
 .../src/controlPanel.tsx                           |    4 +-
 .../plugin-chart-ag-grid-table/src/index.ts        |    2 +-
 .../src/renderers/NumericCellRenderer.tsx          |    6 +-
 .../src/renderers/TextCellRenderer.tsx             |    2 +-
 .../plugin-chart-ag-grid-table/src/stories/data.ts |    2 +-
 .../src/styles/index.tsx                           |    2 +-
 .../src/transformProps.ts                          |    4 +-
 .../src/utils/formatValue.ts                       |    2 +-
 .../src/utils/useColDefs.ts                        |    2 +-
 .../src/utils/useTableTheme.ts                     |    2 +-
 .../test/controlPanel.test.tsx                     |    2 +-
 .../test/utils/useColDefs.test.ts                  |    2 +-
 .../src/CartodiagramPlugin.tsx                     |    2 +-
 .../src/components/ChartLayer.tsx                  |    2 +-
 .../src/components/ChartWrapper.tsx                |    2 +-
 .../src/plugin/controlPanel.ts                     |    2 +-
 .../plugin-chart-cartodiagram/src/plugin/index.ts  |    2 +-
 .../plugins/plugin-chart-cartodiagram/src/types.ts |    2 +-
 .../src/util/chartUtil.tsx                         |    2 +-
 .../src/util/controlPanelUtil.tsx                  |    2 +-
 .../test/plugin/transformProps.test.ts             |    2 +-
 .../plugins/plugin-chart-echarts/package.json      |    4 +-
 .../BigNumber/BigNumberPeriodOverPeriod/PopKPI.tsx |    4 +-
 .../BigNumberPeriodOverPeriod/controlPanel.ts      |    4 +-
 .../BigNumber/BigNumberPeriodOverPeriod/index.ts   |    2 +-
 .../src/BigNumber/BigNumberTotal/controlPanel.ts   |    4 +-
 .../src/BigNumber/BigNumberTotal/index.ts          |    2 +-
 .../BigNumberTotal/transformProps.test.ts          |    2 +-
 .../src/BigNumber/BigNumberTotal/transformProps.ts |    2 +-
 .../src/BigNumber/BigNumberViz.tsx                 |    4 +-
 .../BigNumberWithTrendline/buildQuery.test.ts      |    4 +-
 .../BigNumber/BigNumberWithTrendline/buildQuery.ts |    2 +-
 .../BigNumberWithTrendline/controlPanel.tsx        |    2 +-
 .../src/BigNumber/BigNumberWithTrendline/index.ts  |    2 +-
 .../BigNumberWithTrendline/transformProps.test.ts  |    2 +-
 .../BigNumberWithTrendline/transformProps.ts       |    4 +-
 .../src/BigNumber/sharedControls.ts                |    2 +-
 .../src/BoxPlot/controlPanel.ts                    |    2 +-
 .../plugin-chart-echarts/src/BoxPlot/index.ts      |    2 +-
 .../src/Bubble/controlPanel.tsx                    |    2 +-
 .../plugin-chart-echarts/src/Bubble/index.ts       |    2 +-
 .../src/Funnel/controlPanel.tsx                    |    2 +-
 .../plugin-chart-echarts/src/Funnel/index.ts       |    2 +-
 .../src/Gantt/EchartsGantt.tsx                     |    2 +-
 .../src/Gantt/controlPanel.tsx                     |    4 +-
 .../plugin-chart-echarts/src/Gantt/index.ts        |    2 +-
 .../src/Gantt/transformProps.ts                    |    4 +-
 .../plugin-chart-echarts/src/Gauge/constants.ts    |    2 +-
 .../src/Gauge/controlPanel.tsx                     |    2 +-
 .../plugin-chart-echarts/src/Gauge/index.ts        |    2 +-
 .../src/Graph/controlPanel.tsx                     |    2 +-
 .../plugin-chart-echarts/src/Graph/index.ts        |    2 +-
 .../src/Heatmap/controlPanel.tsx                   |    2 +-
 .../plugin-chart-echarts/src/Heatmap/index.ts      |    2 +-
 .../src/Heatmap/transformProps.ts                  |    4 +-
 .../src/Histogram/controlPanel.tsx                 |    4 +-
 .../plugin-chart-echarts/src/Histogram/index.ts    |    2 +-
 .../src/MixedTimeseries/buildQuery.ts              |    2 +-
 .../src/MixedTimeseries/controlPanel.tsx           |    3 +-
 .../src/MixedTimeseries/index.ts                   |    2 +-
 .../src/MixedTimeseries/transformProps.ts          |   22 +-
 .../plugin-chart-echarts/src/Pie/controlPanel.tsx  |    2 +-
 .../plugins/plugin-chart-echarts/src/Pie/index.ts  |    2 +-
 .../plugin-chart-echarts/src/Pie/transformProps.ts |    2 +-
 .../src/Radar/controlPanel.tsx                     |    4 +-
 .../plugin-chart-echarts/src/Radar/index.ts        |    2 +-
 .../src/Sankey/controlPanel.tsx                    |    2 +-
 .../plugin-chart-echarts/src/Sankey/index.ts       |    2 +-
 .../src/Sunburst/controlPanel.tsx                  |    2 +-
 .../plugin-chart-echarts/src/Sunburst/index.ts     |    2 +-
 .../src/Sunburst/transformProps.ts                 |    2 +-
 .../src/Timeseries/Area/controlPanel.tsx           |    3 +-
 .../src/Timeseries/Area/index.ts                   |    2 +-
 .../src/Timeseries/Regular/Bar/controlPanel.tsx    |    5 +-
 .../src/Timeseries/Regular/Bar/index.ts            |    2 +-
 .../src/Timeseries/Regular/Line/controlPanel.tsx   |    3 +-
 .../src/Timeseries/Regular/Line/index.ts           |    2 +-
 .../Timeseries/Regular/Scatter/controlPanel.tsx    |    2 +-
 .../src/Timeseries/Regular/Scatter/index.ts        |    2 +-
 .../Timeseries/Regular/SmoothLine/controlPanel.tsx |    3 +-
 .../src/Timeseries/Regular/SmoothLine/index.ts     |    2 +-
 .../src/Timeseries/Step/controlPanel.tsx           |    2 +-
 .../src/Timeseries/Step/index.ts                   |    2 +-
 .../src/Timeseries/buildQuery.ts                   |    6 +-
 .../src/Timeseries/constants.ts                    |    2 +-
 .../plugin-chart-echarts/src/Timeseries/index.ts   |    2 +-
 .../src/Timeseries/transformProps.ts               |  152 +-
 .../src/Timeseries/transformers.ts                 |   51 +-
 .../plugin-chart-echarts/src/Timeseries/types.ts   |    1 +
 .../plugin-chart-echarts/src/Tree/controlPanel.tsx |    2 +-
 .../plugins/plugin-chart-echarts/src/Tree/index.ts |    2 +-
 .../src/Treemap/controlPanel.tsx                   |    2 +-
 .../plugin-chart-echarts/src/Treemap/index.ts      |    2 +-
 .../src/Waterfall/constants.ts                     |    2 +-
 .../src/Waterfall/controlPanel.tsx                 |    2 +-
 .../plugin-chart-echarts/src/Waterfall/index.ts    |    2 +-
 .../src/Waterfall/transformProps.ts                |    2 +-
 .../plugin-chart-echarts/src/components/Echart.tsx |   12 +-
 .../src/components/ExtraControls.tsx               |    2 +-
 .../plugins/plugin-chart-echarts/src/constants.ts  |    2 +-
 .../plugins/plugin-chart-echarts/src/controls.tsx  |   30 +-
 .../plugins/plugin-chart-echarts/src/index.ts      |    3 +
 .../src/utils/eChartOptionsSchema.ts               |  827 +++++++
 .../plugin-chart-echarts/src/utils/formatters.ts   |   91 +-
 .../src/utils/mergeCustomEChartOptions.test.ts     |  163 ++
 .../src/utils/mergeCustomEChartOptions.ts          |   79 +
 .../src/utils/safeEChartOptionsParser.test.ts      |  525 +++++
 .../src/utils/safeEChartOptionsParser.ts           |  477 ++++
 .../plugin-chart-echarts/src/utils/series.ts       |    4 +-
 .../src/utils/themeOverrides.test.ts               |  623 ++++--
 .../src/utils/themeOverrides.ts                    |   89 +
 .../test/BigNumber/transformProps.test.ts          |    2 +-
 .../test/BoxPlot/transformProps.test.ts            |    2 +-
 .../test/Bubble/transformProps.test.ts             |    2 +-
 .../test/Funnel/transformProps.test.ts             |    2 +-
 .../test/Gantt/transformProps.test.ts              |    2 +-
 .../test/Gauge/transformProps.test.ts              |    2 +-
 .../test/Graph/transformProps.test.ts              |    2 +-
 .../test/Heatmap/transformProps.test.ts            |    2 +-
 .../test/MixedTimeseries/transformProps.test.ts    |    2 +-
 .../test/Pie/transformProps.test.ts                |    2 +-
 .../test/Radar/transformProps.test.ts              |    2 +-
 .../test/Timeseries/Bar/transformProps.test.ts     |  285 ++-
 .../test/Timeseries/Scatter/transformProps.test.ts |   12 +-
 .../test/Timeseries/transformProps.test.ts         |    6 +-
 .../test/Timeseries/transformers.test.ts           |    4 +-
 .../test/Tree/transformProps.test.ts               |    2 +-
 .../test/Treemap/transformProps.test.ts            |    2 +-
 .../test/Waterfall/transformProps.test.ts          |    2 +-
 .../plugins/plugin-chart-echarts/test/helpers.ts   |    2 +-
 .../test/utils/formatters.test.ts                  |  174 +-
 .../plugin-chart-echarts/test/utils/series.test.ts |    4 +-
 .../test/utils/transformers.test.ts                |    2 +-
 .../plugin-chart-handlebars/src/Handlebars.tsx     |    2 +-
 .../src/components/Handlebars/HandlebarsViewer.tsx |    4 +-
 .../src/plugin/controlPanel.tsx                    |    2 +-
 .../src/plugin/controls/columns.tsx                |    2 +-
 .../src/plugin/controls/handlebarTemplate.tsx      |    4 +-
 .../src/plugin/controls/includeTime.ts             |    2 +-
 .../src/plugin/controls/metrics.tsx                |    2 +-
 .../src/plugin/controls/orderBy.tsx                |    2 +-
 .../src/plugin/controls/queryMode.tsx              |    2 +-
 .../src/plugin/controls/shared.ts                  |    2 +-
 .../src/plugin/controls/style.tsx                  |    4 +-
 .../plugin-chart-handlebars/src/plugin/index.ts    |    2 +-
 .../test/plugin/transformProps.test.ts             |    2 +-
 .../src/PivotTableChart.tsx                        |    4 +-
 .../src/plugin/controlPanel.tsx                    |    2 +-
 .../plugin-chart-pivot-table/src/plugin/index.ts   |    2 +-
 .../src/plugin/transformProps.ts                   |    2 +-
 .../src/react-pivottable/Styles.ts                 |    2 +-
 .../src/react-pivottable/TableRenderers.tsx        |    2 +-
 .../src/react-pivottable/utilities.ts              |    2 +-
 .../test/plugin/transformProps.test.ts             |    2 +-
 .../plugin-chart-table/src/DataTable/DataTable.tsx |    2 +-
 .../src/DataTable/components/GlobalFilter.tsx      |    2 +-
 .../DataTable/components/SearchSelectDropdown.tsx  |    2 +-
 .../src/DataTable/components/SelectPageSize.tsx    |    4 +-
 .../src/DataTable/hooks/useSticky.tsx              |    2 +-
 .../plugins/plugin-chart-table/src/Styles.tsx      |    2 +-
 .../plugins/plugin-chart-table/src/TableChart.tsx  |    7 +-
 .../plugins/plugin-chart-table/src/consts.ts       |    2 +-
 .../plugin-chart-table/src/controlPanel.tsx        |    4 +-
 .../plugins/plugin-chart-table/src/index.ts        |    2 +-
 .../plugin-chart-table/src/stories/testData.ts     |    2 +-
 .../plugin-chart-table/src/transformProps.ts       |    4 +-
 .../plugin-chart-table/src/utils/formatValue.ts    |    2 +-
 .../plugin-chart-table/test/TableChart.test.tsx    |    2 +-
 .../plugin-chart-table/test/controlPanel.test.tsx  |    2 +-
 .../plugins/plugin-chart-table/test/testData.ts    |    4 +-
 .../plugin-chart-table/test/testHelpers.tsx        |    2 +-
 .../test/utils/formatValue.test.ts                 |    2 +-
 .../plugins/plugin-chart-word-cloud/package.json   |    2 +-
 .../src/chart/WordCloud.tsx                        |    2 +-
 .../src/plugin/controlPanel.tsx                    |    2 +-
 .../ColorSchemeControl/ColorSchemeLabel.tsx        |    2 +-
 .../plugin/controls/ColorSchemeControl/index.tsx   |    4 +-
 .../src/plugin/controls/RotationControl.tsx        |    2 +-
 .../plugin-chart-word-cloud/src/plugin/index.ts    |    2 +-
 .../scripts/eslint-metrics-uploader.js             |  144 --
 .../scripts/oxlint-metrics-uploader.js             |    7 +-
 superset-frontend/spec/helpers/ProviderWrapper.tsx |    2 +-
 superset-frontend/spec/helpers/shim.tsx            |    2 +-
 superset-frontend/spec/helpers/testing-library.tsx |    7 +-
 .../src/SqlLab/SqlLabGlobalStyles.tsx              |    2 +-
 superset-frontend/src/SqlLab/actions/sqlLab.ts     |    2 +-
 .../src/SqlLab/components/App/index.tsx            |    4 +-
 .../SqlLab/components/AppLayout/AppLayout.test.tsx |   79 +-
 .../src/SqlLab/components/AppLayout/index.tsx      |   11 +-
 .../src/SqlLab/components/ColumnElement/index.tsx  |    4 +-
 .../EditorAutoSync/EditorAutoSync.test.tsx         |    6 +-
 .../src/SqlLab/components/EditorAutoSync/index.tsx |    2 +-
 .../src/SqlLab/components/EditorWrapper/index.tsx  |    2 +-
 .../components/EditorWrapper/useAnnotations.ts     |    2 +-
 .../SqlLab/components/EditorWrapper/useKeywords.ts |    2 +-
 .../components/EstimateQueryCostButton/index.tsx   |    5 +-
 .../components/ExploreCtasResultsButton/index.tsx  |    2 +-
 .../components/ExploreResultsButton/index.tsx      |    2 +-
 .../src/SqlLab/components/HighlightedSql/index.tsx |    2 +-
 .../components/KeyboardShortcutButton/index.tsx    |    4 +-
 .../src/SqlLab/components/QueryHistory/index.tsx   |    4 +-
 .../SqlLab/components/QueryLimitSelect/index.tsx   |    2 +-
 .../SqlLab/components/QueryStateLabel/index.tsx    |    2 +-
 .../src/SqlLab/components/QueryStatusBar/index.tsx |    3 +-
 .../src/SqlLab/components/QueryTable/index.tsx     |    4 +-
 .../src/SqlLab/components/QueryTable/styles.ts     |    2 +-
 .../src/SqlLab/components/ResultSet/index.tsx      |    7 +-
 .../components/RunQueryActionButton/index.tsx      |    4 +-
 .../components/SaveDatasetActionButton/index.tsx   |    2 +-
 .../SqlLab/components/SaveDatasetModal/index.tsx   |    4 +-
 .../src/SqlLab/components/SaveQuery/index.tsx      |    4 +-
 .../components/ScheduleQueryButton/index.tsx       |    4 +-
 .../SqlLab/components/ShareSqlLabQuery/index.tsx   |    4 +-
 .../src/SqlLab/components/SouthPane/Results.tsx    |    5 +-
 .../src/SqlLab/components/SouthPane/index.tsx      |   24 +-
 .../src/SqlLab/components/SqlEditor/index.tsx      |    5 +-
 .../SqlLab/components/SqlEditorLeftBar/index.tsx   |    4 +-
 .../SqlLab/components/SqlEditorTabHeader/index.tsx |    9 +-
 .../SqlLab/components/SqlEditorTopBar/index.tsx    |    2 +-
 .../SqlLab/components/StatusBar/StatusBar.test.tsx |   14 +-
 .../src/SqlLab/components/StatusBar/index.tsx      |   11 +-
 .../SqlLab/components/TabbedSqlEditors/index.tsx   |    4 +-
 .../src/SqlLab/components/TableElement/index.tsx   |    4 +-
 .../TableExploreTree/TreeNodeRenderer.tsx          |    3 +-
 .../SqlLab/components/TableExploreTree/index.tsx   |    3 +-
 .../components/TableExploreTree/useTreeData.ts     |    2 +-
 .../src/SqlLab/components/TablePreview/index.tsx   |    5 +-
 .../components/TemplateParamsEditor/index.tsx      |    4 +-
 superset-frontend/src/SqlLab/constants.ts          |    2 +-
 superset-frontend/src/SqlLab/fixtures.ts           |    2 +-
 .../src/SqlLab/reducers/getInitialState.ts         |    2 +-
 superset-frontend/src/SqlLab/reducers/sqlLab.ts    |    2 +-
 .../src/SqlLab/utils/newQueryTabName.ts            |    2 +-
 .../DeckglLayerVisibilityCustomizationPlugin.tsx   |    4 +-
 .../components/DeckglLayerVisibility/index.ts      |    2 +-
 .../DynamicGroupBy/DynamicGroupByPlugin.tsx        |    2 +-
 .../components/DynamicGroupBy/controlPanel.ts      |    2 +-
 .../components/DynamicGroupBy/index.ts             |    2 +-
 .../TimeColumn/TimeColumnFilterPlugin.tsx          |    4 +-
 .../components/TimeColumn/controlPanel.ts          |    2 +-
 .../components/TimeColumn/index.ts                 |    2 +-
 .../components/TimeGrain/TimeGrainFilterPlugin.tsx |    2 +-
 .../components/TimeGrain/controlPanel.ts           |    2 +-
 .../components/TimeGrain/index.ts                  |    2 +-
 .../src/chartCustomizations/components/common.ts   |    2 +-
 .../src/components/AlteredSliceTag/index.tsx       |    2 +-
 .../src/components/AuditInfo/index.tsx             |    2 +-
 superset-frontend/src/components/Chart/Chart.tsx   |    7 +-
 .../Chart/ChartContextMenu/ChartContextMenu.tsx    |    4 +-
 .../src/components/Chart/ChartRenderer.tsx         |    4 +-
 .../components/Chart/DisabledMenuItemTooltip.tsx   |    2 +-
 .../src/components/Chart/DrillBy/DrillByChart.tsx  |    2 +-
 .../src/components/Chart/DrillBy/DrillByModal.tsx  |    5 +-
 .../components/Chart/DrillBy/DrillBySubmenu.tsx    |    4 +-
 .../Chart/DrillBy/useDisplayModeToggle.tsx         |    4 +-
 .../Chart/DrillBy/useResultsTableView.tsx          |    3 +-
 .../Chart/DrillDetail/DrillDetailModal.tsx         |    4 +-
 .../Chart/DrillDetail/DrillDetailPane.tsx          |    6 +-
 .../Chart/DrillDetail/DrillDetailTableControls.tsx |    4 +-
 .../src/components/Chart/DrillDetail/types.ts      |    2 +-
 .../components/Chart/MenuItemWithTruncation.tsx    |    2 +-
 .../src/components/Chart/chartAction.ts            |    2 +-
 .../src/components/Chart/chartReducer.ts           |    2 +-
 .../Chart/useDrillDetailMenuItems/index.tsx        |    4 +-
 .../src/components/CopyToClipboard/index.tsx       |    4 +-
 .../src/components/CrudThemeProvider.tsx           |    2 +-
 .../src/components/DatabaseSelector/index.tsx      |    4 +-
 .../src/components/DatabaseSelector/styles.ts      |    2 +-
 .../Datasource/ChangeDatasourceModal/index.tsx     |    5 +-
 .../Datasource/DatasourceModal/index.tsx           |    5 +-
 .../Datasource/FoldersEditor/TreeItem.styles.ts    |    2 +-
 .../Datasource/FoldersEditor/TreeItem.tsx          |    5 +-
 .../components/DragOverlayContent.tsx              |    2 +-
 .../components/FoldersToolbarComponent.tsx         |    2 +-
 .../FoldersEditor/components/ResetConfirmModal.tsx |    2 +-
 .../Datasource/FoldersEditor/folderOperations.ts   |    2 +-
 .../Datasource/FoldersEditor/folderValidation.ts   |    2 +-
 .../FoldersEditor/hooks/useDragHandlers.ts         |    2 +-
 .../FoldersEditor/hooks/useItemHeights.ts          |    2 +-
 .../components/Datasource/FoldersEditor/styles.tsx |    2 +-
 .../components/CollectionTable/index.tsx           |    4 +-
 .../DatasourceEditor/DatasourceEditor.tsx          |   10 +-
 .../components/DashboardLinksExternal/index.tsx    |    2 +-
 .../components/DatasetUsageTab/index.tsx           |    4 +-
 .../tests/DatasourceEditorCurrency.test.tsx        |    2 +-
 .../Datasource/components/Field/index.tsx          |    2 +-
 .../Datasource/components/Fieldset/index.tsx       |    2 +-
 .../src/components/Datasource/utils/index.ts       |    2 +-
 .../src/components/Datasource/utils/utils.test.tsx |    2 +-
 .../src/components/DynamicPlugins/index.tsx        |    2 +-
 .../src/components/ErrorBoundary/index.tsx         |    2 +-
 .../ErrorMessage/BasicErrorAlert.test.tsx          |    2 +-
 .../components/ErrorMessage/BasicErrorAlert.tsx    |    6 +-
 .../ErrorMessage/DatabaseErrorMessage.tsx          |    4 +-
 .../ErrorMessage/DatasetNotFoundErrorMessage.tsx   |    2 +-
 .../src/components/ErrorMessage/ErrorAlert.tsx     |    5 +-
 .../ErrorMessage/ErrorMessageWithStackTrace.tsx    |    2 +-
 .../ErrorMessage/FrontendNetworkErrorMessage.tsx   |    2 +-
 .../ErrorMessage/InvalidSQLErrorMessage.tsx        |    2 +-
 .../src/components/ErrorMessage/IssueCode.tsx      |    4 +-
 .../ErrorMessage/MarshmallowErrorMessage.tsx       |    2 +-
 .../ErrorMessage/OAuth2RedirectMessage.tsx         |    2 +-
 .../ErrorMessage/ParameterErrorMessage.tsx         |    4 +-
 .../ErrorMessage/TimeoutErrorMessage.tsx           |    4 +-
 .../src/components/FilterableTable/utils.tsx       |    2 +-
 .../src/components/GridTable/Header.tsx            |    4 +-
 .../src/components/GridTable/HeaderMenu.tsx        |    4 +-
 .../src/components/GridTable/index.tsx             |    2 +-
 .../src/components/ImportModal/ErrorAlert.tsx      |    5 +-
 .../components/ImportModal/ImportErrorAlert.tsx    |    2 +-
 .../src/components/ImportModal/index.tsx           |    4 +-
 .../src/components/ImportModal/styles.ts           |    2 +-
 .../src/components/JsonModal/index.tsx             |    2 +-
 .../src/components/LastQueriedLabel/index.tsx      |    4 +-
 .../src/components/ListView/ActionsBar.tsx         |    2 +-
 .../src/components/ListView/CardCollection.tsx     |    2 +-
 .../src/components/ListView/CardSortSelect.tsx     |    4 +-
 .../src/components/ListView/CrossLinks.tsx         |    2 +-
 .../src/components/ListView/CrossLinksTooltip.tsx  |    4 +-
 .../src/components/ListView/Filters/Base.ts        |    2 +-
 .../src/components/ListView/Filters/DateRange.tsx  |    2 +-
 .../components/ListView/Filters/NumericalRange.tsx |    4 +-
 .../src/components/ListView/Filters/Search.tsx     |    4 +-
 .../src/components/ListView/Filters/Select.tsx     |    2 +-
 .../src/components/ListView/Filters/index.tsx      |    2 +-
 .../src/components/ListView/ListView.tsx           |    5 +-
 .../src/components/MessageToasts/Toast.tsx         |    9 +-
 .../components/MessageToasts/ToastPresenter.tsx    |    2 +-
 .../components/Modal/CollapsibleModalSection.tsx   |    2 +-
 .../src/components/Modal/ModalFormField.tsx        |    2 +-
 .../src/components/Modal/StandardModal.tsx         |    4 +-
 .../src/components/Modal/useModalValidation.tsx    |    4 +-
 .../src/components/ModalTitleWithIcon/index.tsx    |    2 +-
 .../src/components/PanelToolbar/index.tsx          |   42 +-
 .../src/components/ResizableSidebar/index.tsx      |    2 +-
 .../src/components/RowCountLabel/index.tsx         |    2 +-
 .../components/SQLEditorWithValidation/index.tsx   |    4 +-
 .../StreamingExportModal/StreamingExportModal.tsx  |    4 +-
 .../src/components/TableSelector/index.tsx         |    4 +-
 superset-frontend/src/components/Tag/index.tsx     |    2 +-
 superset-frontend/src/components/Tag/utils.tsx     |    2 +-
 .../src/components/TagsList/index.tsx              |    2 +-
 .../ViewListExtension/ViewListExtension.test.tsx   |  228 +-
 .../src/components/ViewListExtension/index.tsx     |   24 +-
 superset-frontend/src/core/commands/index.ts       |   44 +-
 .../src/core/editors/AceEditorProvider.test.tsx    |    2 +-
 .../src/core/editors/AceEditorProvider.tsx         |    7 +
 superset-frontend/src/core/editors/EditorHost.tsx  |   10 +-
 .../src/core/editors/EditorProviders.test.ts       |   88 +-
 .../src/core/editors/EditorProviders.ts            |   37 +-
 superset-frontend/src/core/editors/index.ts        |   69 +-
 superset-frontend/src/core/extensions/index.ts     |    6 +-
 superset-frontend/src/core/index.ts                |   16 +-
 superset-frontend/src/core/menus/index.test.ts     |  124 ++
 superset-frontend/src/core/menus/index.ts          |   83 +
 superset-frontend/src/core/models.ts               |    6 +-
 superset-frontend/src/core/sqlLab/models.ts        |    5 +-
 superset-frontend/src/core/utils.ts                |    2 +-
 superset-frontend/src/core/views/index.test.ts     |  112 +
 superset-frontend/src/core/views/index.ts          |   83 +
 .../dashboard/actions/chartCustomizationActions.ts |    2 +-
 .../src/dashboard/actions/dashboardInfo.ts         |    2 +-
 .../src/dashboard/actions/dashboardLayout.ts       |    2 +-
 .../src/dashboard/actions/dashboardState.ts        |    4 +-
 .../src/dashboard/actions/sliceEntities.ts         |    2 +-
 .../components/AddSliceCard/AddSliceCard.tsx       |    4 +-
 .../src/dashboard/components/AnchorLink/index.tsx  |    2 +-
 .../components/AutoRefreshIndicator/index.tsx      |    3 +-
 .../AutoRefreshStatus/StatusIndicatorDot.tsx       |    2 +-
 .../AutoRefreshStatus/StatusTooltipContent.tsx     |    2 +-
 .../components/BuilderComponentPane/index.tsx      |    4 +-
 .../components/ColorSchemeControlWrapper.tsx       |    2 +-
 .../src/dashboard/components/ColorSchemeSelect.tsx |    4 +-
 .../components/CustomizationsBadge/index.tsx       |    4 +-
 .../src/dashboard/components/Dashboard.tsx         |    2 +-
 .../DashboardBuilder/DashboardBuilder.tsx          |   22 +-
 .../DashboardBuilder/DashboardWrapper.tsx          |    2 +-
 .../src/dashboard/components/DashboardGrid.tsx     |    3 +-
 .../dashboard/components/EmbeddedModal/index.tsx   |    5 +-
 .../components/FiltersBadge/DetailsPanel/index.tsx |    4 +-
 .../FiltersBadge/FilterIndicator/index.tsx         |    2 +-
 .../dashboard/components/FiltersBadge/Styles.tsx   |    2 +-
 .../dashboard/components/FiltersBadge/index.tsx    |    4 +-
 .../src/dashboard/components/Header/index.tsx      |    3 +-
 .../components/Header/useDashboardMetadataBar.tsx  |    2 +-
 .../Header/useHeaderActionsDropdownMenu.tsx        |    2 +-
 .../src/dashboard/components/IconButton.tsx        |    2 +-
 .../src/dashboard/components/MissingChart.tsx      |    2 +-
 .../OverwriteConfirm/OverwriteConfirmModal.tsx     |    4 +-
 .../PropertiesModal/PropertiesModal.test.tsx       |    2 +-
 .../dashboard/components/PropertiesModal/index.tsx |    2 +-
 .../PropertiesModal/sections/AccessSection.tsx     |    2 +-
 .../PropertiesModal/sections/AdvancedSection.tsx   |    4 +-
 .../PropertiesModal/sections/BasicInfoSection.tsx  |    2 +-
 .../sections/CertificationSection.tsx              |    2 +-
 .../PropertiesModal/sections/RefreshSection.tsx    |    2 +-
 .../PropertiesModal/sections/StylingSection.tsx    |    5 +-
 .../dashboard/components/PublishedStatus/index.tsx |    2 +-
 .../dashboard/components/RefreshButton/index.tsx   |    3 +-
 .../RefreshFrequency/RefreshFrequencySelect.tsx    |    4 +-
 .../dashboard/components/RefreshIntervalModal.tsx  |    4 +-
 .../src/dashboard/components/SaveModal.tsx         |    4 +-
 .../src/dashboard/components/SliceAdder.tsx        |    4 +-
 .../src/dashboard/components/SliceHeader/index.tsx |    9 +-
 .../ViewResultsModalTrigger.tsx                    |    4 +-
 .../components/SliceHeaderControls/index.tsx       |    4 +-
 .../components/URLShortLinkButton/index.tsx        |    4 +-
 .../src/dashboard/components/dnd/DragDroppable.tsx |   11 +-
 .../src/dashboard/components/dnd/DragHandle.tsx    |    2 +-
 .../components/filterscope/FilterScope.test.tsx    |    2 +-
 .../components/filterscope/FilterScopeModal.tsx    |    2 +-
 .../components/filterscope/FilterScopeSelector.tsx |    3 +-
 .../filterscope/renderFilterScopeTreeNodes.tsx     |    2 +-
 .../dashboard/components/filterscope/treeIcons.tsx |    2 +-
 .../components/gridComponents/Chart/Chart.test.tsx |   30 +
 .../components/gridComponents/Chart/Chart.tsx      |    4 +-
 .../gridComponents/ChartHolder/ChartHolder.tsx     |    2 +-
 .../components/gridComponents/Column/Column.tsx    |    5 +-
 .../components/gridComponents/Divider/Divider.tsx  |    2 +-
 .../DynamicComponent/DynamicComponent.tsx          |    2 +-
 .../components/gridComponents/Header/Header.tsx    |    2 +-
 .../gridComponents/Markdown/Markdown.test.tsx      |   26 +-
 .../gridComponents/Markdown/Markdown.tsx           |    3 +-
 .../components/gridComponents/Row/Row.tsx          |   29 +-
 .../components/gridComponents/Tab/Tab.tsx          |    3 +-
 .../components/gridComponents/Tabs/Tabs.tsx        |    3 +-
 .../gridComponents/TabsRenderer/TabsRenderer.tsx   |    2 +-
 .../gridComponents/new/DraggableNewComponent.tsx   |    2 +-
 .../components/gridComponents/new/NewColumn.tsx    |    2 +-
 .../components/gridComponents/new/NewDivider.tsx   |    2 +-
 .../components/gridComponents/new/NewHeader.tsx    |    2 +-
 .../components/gridComponents/new/NewMarkdown.tsx  |    2 +-
 .../components/gridComponents/new/NewRow.tsx       |    2 +-
 .../components/gridComponents/new/NewTabs.tsx      |    2 +-
 .../components/menu/BackgroundStyleDropdown.tsx    |    4 +-
 .../components/menu/DownloadMenuItems/index.tsx    |    3 +-
 .../src/dashboard/components/menu/HoverMenu.tsx    |    2 +-
 .../components/menu/MarkdownModeDropdown.tsx       |    2 +-
 .../components/menu/ShareMenuItems/index.tsx       |    3 +-
 .../dashboard/components/menu/WithPopoverMenu.tsx  |   17 +-
 .../nativeFilters/ConfigModal/ModalFooter.tsx      |    5 +-
 .../nativeFilters/ConfigModal/SharedStyles.tsx     |    2 +-
 .../FilterBar/ActionButtons/index.tsx              |    4 +-
 .../FilterBar/CrossFilters/CrossFilter.tsx         |    2 +-
 .../FilterBar/CrossFilters/CrossFilterTag.tsx      |    2 +-
 .../FilterBar/CrossFilters/CrossFilterTitle.tsx    |    4 +-
 .../ScopingModal/ChartsScopingListPanel.tsx        |    4 +-
 .../CrossFilters/ScopingModal/ScopingModal.tsx     |    2 +-
 .../ScopingModal/ScopingModalContent.tsx           |    2 +-
 .../CrossFilters/ScopingModal/ScopingTreePanel.tsx |    5 +-
 .../FilterBar/CrossFilters/VerticalCollapse.tsx    |    4 +-
 .../nativeFilters/FilterBar/CrossFilters/styles.ts |    2 +-
 .../CustomizationsOutOfScopeCollapsible/index.tsx  |    4 +-
 .../FilterBar/FilterBarSettings/index.tsx          |    4 +-
 .../FilterControls/FilterControlShared.tsx         |    2 +-
 .../FilterBar/FilterControls/FilterControls.tsx    |    9 +-
 .../FilterControls/FilterDivider.stories.tsx       |    2 +-
 .../FilterBar/FilterControls/FilterDivider.tsx     |    2 +-
 .../FilterBar/FilterControls/FilterValue.tsx       |    4 +-
 .../FilterBar/FilterControls/GroupByFilterCard.tsx |    9 +-
 .../FilterBar/FiltersDropdownContent/index.tsx     |    2 +-
 .../FiltersOutOfScopeCollapsible/index.tsx         |    4 +-
 .../nativeFilters/FilterBar/Header/index.tsx       |    4 +-
 .../nativeFilters/FilterBar/Horizontal.tsx         |    4 +-
 .../nativeFilters/FilterBar/Vertical.tsx           |    4 +-
 .../components/nativeFilters/FilterBar/index.tsx   |    2 +-
 .../nativeFilters/FilterBar/keyValue.tsx           |    2 +-
 .../nativeFilters/FilterCard/DependenciesRow.tsx   |    4 +-
 .../nativeFilters/FilterCard/NameRow.tsx           |    2 +-
 .../nativeFilters/FilterCard/ScopeRow.tsx          |    4 +-
 .../components/nativeFilters/FilterCard/Styles.ts  |    2 +-
 .../nativeFilters/FilterCard/TypeRow.tsx           |    2 +-
 .../nativeFilters/FilterCard/useFilterScope.ts     |    2 +-
 .../ConfigModalContent/ConfigModalContent.tsx      |    2 +-
 .../ConfigModalSidebar/ConfigModalSidebar.tsx      |  240 +-
 .../FiltersConfigModal/DividerConfigForm.tsx       |    4 +-
 .../FiltersConfigModal/DraggableFilter.test.tsx    |  109 +-
 .../FiltersConfigModal/DraggableFilter.tsx         |  124 +-
 .../FiltersConfigModal/FilterConfigPane.test.tsx   |   26 +-
 .../FiltersConfigModal/FilterConfigurePane.tsx     |    2 +-
 .../FiltersConfigModal/FilterTitleContainer.tsx    |  106 +-
 .../FiltersConfigModal/FilterTitlePane.tsx         |    4 +-
 .../FiltersConfigForm/CollapsibleControl.tsx       |    2 +-
 .../FiltersConfigForm/ColumnSelect.tsx             |    2 +-
 .../FiltersConfigForm/DatasetSelect.tsx            |    2 +-
 .../FiltersConfigForm/DefaultValue.tsx             |    2 +-
 .../FiltersConfigForm/DependencyList.tsx           |    4 +-
 .../FiltersConfigForm/FilterScope/FilterScope.tsx  |    2 +-
 .../FiltersConfigForm/FilterScope/ScopingTree.tsx  |    2 +-
 .../FiltersConfigForm/FilterScope/state.ts         |    2 +-
 .../FiltersConfigForm/FilterScope/utils.ts         |    4 +-
 .../FiltersConfigForm/FiltersConfigForm.tsx        |    6 +-
 .../FiltersConfigForm/RemovedFilter.tsx            |    4 +-
 .../FiltersConfigForm/constants.ts                 |    2 +-
 .../FiltersConfigForm/getControlItemsMap.tsx       |    4 +-
 .../FiltersConfigModal/FiltersConfigForm/state.ts  |    2 +-
 .../FiltersConfigForm/utils.test.ts                |    2 +-
 .../FiltersConfigModal/FiltersConfigForm/utils.ts  |    2 +-
 .../FiltersConfigModal/FiltersConfigModal.test.tsx |  180 +-
 .../FiltersConfigModal/FiltersConfigModal.tsx      |   17 +-
 .../Footer/CancelConfirmationAlert.tsx             |    4 +-
 .../FiltersConfigModal/Footer/Footer.tsx           |    2 +-
 .../FiltersConfigModal/ItemTitleContainer.tsx      |   71 +-
 .../FiltersConfigModal/ItemTitlePane.tsx           |    2 +-
 .../FiltersConfigModal/NewItemDropdown.tsx         |    4 +-
 .../hooks/useFilterOperations.ts                   |    2 +-
 .../FiltersConfigModal/hooks/useModalSaveLogic.ts  |    2 +-
 .../nativeFilters/FiltersConfigModal/utils.ts      |    2 +-
 .../dashboard/components/nativeFilters/utils.ts    |    2 +-
 .../components/resizable/ResizableContainer.tsx    |    2 +-
 .../src/dashboard/containers/DashboardPage.tsx     |    4 +-
 .../src/dashboard/hooks/useDownloadScreenshot.ts   |    4 +-
 .../src/dashboard/reducers/sliceEntities.ts        |    2 +-
 superset-frontend/src/dashboard/styles.ts          |    2 +-
 superset-frontend/src/dashboard/types.ts           |    2 +-
 .../src/dashboard/util/backgroundStyleOptions.ts   |    2 +-
 .../src/dashboard/util/getFilterFieldNodesTree.ts  |    2 +-
 .../src/dashboard/util/getFilterScopeNodesTree.ts  |    2 +-
 .../src/dashboard/util/getSliceHeaderTooltip.tsx   |    2 +-
 .../src/dashboard/util/headerStyleOptions.ts       |    2 +-
 .../src/dashboard/util/newComponentFactory.ts      |    2 +-
 .../dashboard/util/updateComponentParentsList.ts   |    2 +-
 .../util/useFilterFocusHighlightStyles.ts          |    2 +-
 .../src/embedded/EmbeddedContextProviders.tsx      |    2 +-
 superset-frontend/src/embedded/index.tsx           |    9 +-
 superset-frontend/src/embedded/utils.ts            |    2 +-
 .../src/explore/actions/exploreActions.ts          |    2 +-
 .../src/explore/actions/saveModalActions.ts        |    2 +-
 .../src/explore/components/ChartPills.tsx          |    2 +-
 .../src/explore/components/Control.tsx             |    2 +-
 .../src/explore/components/ControlHeader.tsx       |    4 +-
 .../components/ControlPanelsContainer.test.tsx     |    2 +-
 .../explore/components/ControlPanelsContainer.tsx  |    9 +-
 .../explore/components/DataTableControl/index.tsx  |    8 +-
 .../DataTableControl/useTableColumns.test.ts       |    2 +-
 .../components/DataTablesPane/DataTablesPane.tsx   |    4 +-
 .../components/DataTableControls.tsx               |    4 +-
 .../components/ResultsPaneOnDashboard.tsx          |    4 +-
 .../DataTablesPane/components/SamplesPane.tsx      |    6 +-
 .../components/SingleQueryResultPane.tsx           |    2 +-
 .../DataTablesPane/components/useResultsPane.tsx   |    4 +-
 .../src/explore/components/DataTablesPane/types.ts |    2 +-
 .../DatasourcePanelDragOption/index.tsx            |    2 +-
 .../DatasourcePanel/DatasourcePanelItem.tsx        |    4 +-
 .../components/DatasourcePanel/fixtures.tsx        |    2 +-
 .../explore/components/DatasourcePanel/index.tsx   |    5 +-
 .../DatasourcePanel/transformDatasourceFolders.ts  |    2 +-
 .../src/explore/components/EmbedCodeContent.tsx    |    3 +-
 .../src/explore/components/ExploreAlert.tsx        |    2 +-
 .../components/ExploreChartHeader/index.tsx        |    5 +-
 .../ExploreChartHeader/useExploreMetadataBar.tsx   |    4 +-
 .../explore/components/ExploreChartPanel/index.tsx |    5 +-
 .../explore/components/ExploreContainer/index.tsx  |    2 +-
 .../explore/components/ExploreContentPopover.tsx   |    2 +-
 .../components/ExploreViewContainer/index.tsx      |    5 +-
 .../components/ExportToCSVDropdown/index.tsx       |    4 +-
 .../explore/components/PropertiesModal/index.tsx   |    2 +-
 .../explore/components/RunQueryButton/index.tsx    |    4 +-
 .../src/explore/components/SaveModal.tsx           |    7 +-
 .../AnnotationLayerControl/AnnotationLayer.tsx     |    4 +-
 .../AnnotationLayerControl/AnnotationTypes.ts      |    2 +-
 .../controls/AnnotationLayerControl/index.tsx      |    4 +-
 .../explore/components/controls/BoundsControl.tsx  |    4 +-
 .../components/controls/CheckboxControl.tsx        |    2 +-
 .../controls/CollectionControl/index.tsx           |    4 +-
 .../ColorBreakpointOption.tsx                      |    2 +-
 .../ColorBreakpointPopoverControl.tsx              |    4 +-
 .../controls/ColorBreakpointsControl/index.tsx     |    4 +-
 .../ColorSchemeControl/ColorSchemeLabel.tsx        |    2 +-
 .../controls/ColorSchemeControl/index.tsx          |    4 +-
 .../ColumnConfigControl/ColumnConfigControl.tsx    |    6 +-
 .../ColumnConfigControl/ColumnConfigItem.tsx       |    2 +-
 .../ColumnConfigControl/ColumnConfigPopover.tsx    |    2 +-
 .../ControlForm/ControlFormItem.tsx                |    2 +-
 .../ColumnConfigControl/ControlForm/index.tsx      |    2 +-
 .../controls/ColumnConfigControl/constants.tsx     |    4 +-
 .../controls/ColumnConfigControl/types.ts          |    2 +-
 .../components/controls/ComparisonRangeLabel.tsx   |    4 +-
 .../ConditionalFormattingControl.tsx               |    4 +-
 .../FormattingPopoverContent.test.tsx              |    2 +-
 .../FormattingPopoverContent.tsx                   |    6 +-
 .../ConditionalFormattingControl/constants.ts      |    2 +-
 .../controls/ConditionalFormattingControl/types.ts |    2 +-
 .../controls/ContourControl/ContourOption.tsx      |    4 +-
 .../ContourControl/ContourPopoverControl.tsx       |    4 +-
 .../components/controls/ContourControl/index.tsx   |    4 +-
 .../controls/CurrencyControl/CurrencyControl.tsx   |    4 +-
 .../components/controls/CustomListItem/index.tsx   |    2 +-
 .../DatasourceControl/DatasourceControl.test.tsx   |  268 +--
 .../controls/DatasourceControl/index.tsx           |    4 +-
 .../controls/DateFilterControl/DateFilterLabel.tsx |    9 +-
 .../DateFilterControl/components/AdvancedFrame.tsx |    2 +-
 .../DateFilterControl/components/CalendarFrame.tsx |    2 +-
 .../DateFilterControl/components/CommonFrame.tsx   |    2 +-
 .../components/CurrentCalendarFrame.tsx            |    2 +-
 .../DateFilterControl/components/CustomFrame.tsx   |    2 +-
 .../components/DateFunctionTooltip.tsx             |    4 +-
 .../DateFilterControl/components/DateLabel.tsx     |    4 +-
 .../controls/DateFilterControl/utils/constants.ts  |    2 +-
 .../DndColumnSelectControl/ColumnSelectPopover.tsx |    5 +-
 .../ColumnSelectPopoverTrigger.tsx                 |    2 +-
 .../DndAdhocFilterOption.tsx                       |    2 +-
 .../DndColumnMetricSelect.tsx                      |    4 +-
 .../DndColumnSelectControl/DndColumnSelect.tsx     |    4 +-
 .../DndColumnSelectPopoverTitle.tsx                |    4 +-
 .../DndFilterSelect.test.tsx                       |    2 +-
 .../DndColumnSelectControl/DndFilterSelect.tsx     |    3 +-
 .../DndColumnSelectControl/DndMetricSelect.tsx     |    6 +-
 .../DndColumnSelectControl/DndSelectLabel.tsx      |    2 +-
 .../controls/DndColumnSelectControl/Option.tsx     |    4 +-
 .../DndColumnSelectControl/OptionWrapper.tsx       |    2 +-
 .../DndColumnSelectControl/useResizeButton.tsx     |    2 +-
 .../DndColumnSelectControl/utils/optionSelector.ts |    2 +-
 .../FilterControl/AdhocFilterControl/index.tsx     |    6 +-
 .../FilterControl/AdhocFilterEditPopover/index.tsx |    6 +-
 .../index.tsx                                      |    4 +-
 .../useAdvancedDataTypes.ts                        |    2 +-
 .../AdhocFilterEditPopoverSqlTabContent.test.tsx   |   84 +-
 .../AdhocFilterEditPopoverSqlTabContent/index.tsx  |   12 +-
 .../utils/useDatePickerInAdhocFilter.tsx           |    2 +-
 .../controls/FixedOrMetricControl/index.tsx        |    2 +-
 .../components/controls/JSEditorControl.test.tsx   |  125 ++
 .../components/controls/JSEditorControl.tsx        |  105 +
 .../controls/LayerConfigsControl/FlatLayerTree.tsx |    4 +-
 .../LayerConfigsControl/LayerConfigsControl.tsx    |    4 +-
 .../LayerConfigsPopoverContent.tsx                 |    4 +-
 .../controls/MapViewControl/ExtentTag.tsx          |    2 +-
 .../controls/MapViewControl/MapViewControl.tsx     |    4 +-
 .../MapViewControl/MapViewPopoverContent.tsx       |    4 +-
 .../controls/MatrixifyDimensionControl.tsx         |    2 +-
 .../MetricControl/AdhocMetricEditPopover/index.tsx |   25 +-
 .../MetricControl/AdhocMetricEditPopoverTitle.tsx  |    4 +-
 .../MetricControl/AdhocMetricPopoverTrigger.tsx    |    2 +-
 .../controls/MetricControl/MetricsControl.tsx      |    2 +-
 .../components/controls/NumberControl/index.tsx    |    2 +-
 .../components/controls/OptionControls/index.tsx   |    4 +-
 .../controls/SelectAsyncControl/index.tsx          |    2 +-
 .../explore/components/controls/SelectControl.tsx  |    4 +-
 .../explore/components/controls/SpatialControl.tsx |    2 +-
 .../components/controls/TextAreaControl.tsx        |    4 +-
 .../controls/TimeSeriesColumnControl/index.tsx     |    4 +-
 .../src/explore/components/controls/ViewQuery.tsx  |    4 +-
 .../explore/components/controls/ViewQueryModal.tsx |    5 +-
 .../components/controls/ViewQueryModalFooter.tsx   |    2 +-
 .../components/controls/ViewportControl.tsx        |    2 +-
 .../controls/VizTypeControl/FastVizSwitcher.tsx    |    4 +-
 .../components/controls/VizTypeControl/VizTile.tsx |    4 +-
 .../controls/VizTypeControl/VizTypeGallery.tsx     |    4 +-
 .../controls/VizTypeControl/constants.tsx          |    2 +-
 .../components/controls/VizTypeControl/index.tsx   |    4 +-
 .../ZoomConfigControl/ZoomConfigControl.tsx        |    4 +-
 .../ZoomConfigControl/ZoomConfigsChart.tsx         |    2 +-
 .../src/explore/components/controls/index.ts       |    2 +
 .../components/controls/withAsyncVerification.tsx  |    2 +-
 .../src/explore/components/optionRenderers.tsx     |    2 +-
 .../DashboardsSubMenu.tsx                          |    4 +-
 .../useExploreAdditionalActionsMenu/index.tsx      |    3 +-
 superset-frontend/src/explore/constants.ts         |    2 +-
 .../src/explore/controlPanels/Separator.ts         |    2 +-
 .../src/explore/controlPanels/sections.tsx         |    2 +-
 .../src/explore/controlUtils/controlUtils.test.tsx |    2 +-
 .../src/explore/controlUtils/getColumnKeywords.tsx |    2 +-
 superset-frontend/src/explore/controls.tsx         |    2 +-
 superset-frontend/src/explore/fixtures.tsx         |    2 +-
 .../src/extensions/ExtensionPlaceholder.tsx        |    2 +-
 .../src/extensions/ExtensionsContext.test.tsx      |  150 --
 .../src/extensions/ExtensionsContext.tsx           |   93 -
 .../src/extensions/ExtensionsContextUtils.test.ts  |   74 -
 .../src/extensions/ExtensionsContextUtils.ts       |   32 -
 .../src/extensions/ExtensionsList.test.tsx         |   17 -
 .../src/extensions/ExtensionsList.tsx              |   31 +-
 .../src/extensions/ExtensionsLoader.test.ts        |  113 +
 .../src/extensions/ExtensionsLoader.ts             |  161 ++
 .../src/extensions/ExtensionsManager.test.ts       |  572 -----
 .../src/extensions/ExtensionsManager.ts            |  355 ---
 .../src/extensions/ExtensionsStartup.test.tsx      |   74 +-
 .../src/extensions/ExtensionsStartup.tsx           |   56 +-
 .../src/features/alerts/AlertReportModal.test.tsx  |  463 +++-
 .../src/features/alerts/AlertReportModal.tsx       |   49 +-
 .../features/alerts/buildErrorTooltipMessage.tsx   |    2 +-
 .../alerts/components/AlertReportCronScheduler.tsx |    4 +-
 .../features/alerts/components/AlertStatusIcon.tsx |    4 +-
 .../alerts/components/NotificationMethod.tsx       |    4 +-
 .../features/alerts/components/RecipientIcon.tsx   |    2 +-
 superset-frontend/src/features/alerts/types.ts     |    7 +
 .../src/features/allEntities/AllEntitiesTable.tsx  |    4 +-
 .../annotationLayers/AnnotationLayerModal.tsx      |    4 +-
 .../src/features/annotations/AnnotationModal.tsx   |    4 +-
 .../src/features/charts/ChartCard.tsx              |    4 +-
 .../src/features/cssTemplates/CssTemplateModal.tsx |    4 +-
 .../src/features/dashboards/DashboardCard.tsx      |    2 +-
 .../DatabaseConnectionForm/CommonParameters.tsx    |    4 +-
 .../DatabaseConnectionForm/EncryptedField.tsx      |    4 +-
 .../DatabaseConnectionForm/OAuth2ClientField.tsx   |    2 +-
 .../DatabaseConnectionForm/TableCatalog.tsx        |    4 +-
 .../DatabaseConnectionForm/ValidatedInputField.tsx |    2 +-
 .../DatabaseModal/DatabaseConnectionForm/index.tsx |    2 +-
 .../databases/DatabaseModal/ExtraOptions.test.tsx  |    2 +-
 .../databases/DatabaseModal/ExtraOptions.tsx       |    4 +-
 .../databases/DatabaseModal/ModalHeader.tsx        |   10 +-
 .../databases/DatabaseModal/SSHTunnelForm.tsx      |    4 +-
 .../databases/DatabaseModal/SSHTunnelSwitch.tsx    |    4 +-
 .../databases/DatabaseModal/SqlAlchemyForm.tsx     |    4 +-
 .../src/features/databases/DatabaseModal/index.tsx |    5 +-
 .../src/features/databases/DatabaseModal/styles.ts |    2 +-
 .../databases/UploadDataModel/ColumnsPreview.tsx   |    4 +-
 .../features/databases/UploadDataModel/index.tsx   |    4 +-
 .../features/databases/UploadDataModel/styles.ts   |    2 +-
 .../AddDataset/DatasetPanel/DatasetPanel.tsx       |    5 +-
 .../AddDataset/DatasetPanel/MessageContent.tsx     |    4 +-
 .../datasets/AddDataset/DatasetPanel/index.tsx     |    4 +-
 .../datasets/AddDataset/EditDataset/index.tsx      |    4 +-
 .../features/datasets/AddDataset/Footer/index.tsx  |    4 +-
 .../features/datasets/AddDataset/Header/index.tsx  |    2 +-
 .../datasets/AddDataset/LeftPanel/index.tsx        |    4 +-
 .../datasets/AddDataset/RightPanel/index.tsx       |    2 +-
 .../src/features/datasets/DatasetLayout/index.tsx  |    2 +-
 .../features/datasets/DatasetSelectLabel/index.tsx |    4 +-
 .../datasets/DuplicateDatasetModal.test.tsx        |    2 +-
 .../features/datasets/DuplicateDatasetModal.tsx    |    2 +-
 .../src/features/datasets/constants.ts             |    2 +-
 .../src/features/datasets/hooks/useDatasetLists.ts |    4 +-
 .../datasets/hooks/useGetDatasetRelatedCounts.ts   |    4 +-
 .../DatasetMetadataBar.skipped-stories.tsx         |    2 +-
 .../datasets/metadataBar/useDatasetMetadataBar.tsx |    4 +-
 superset-frontend/src/features/datasets/styles.ts  |    2 +-
 .../src/features/groups/GroupListModal.tsx         |    2 +-
 superset-frontend/src/features/groups/utils.ts     |    2 +-
 .../src/features/home/ActivityTable.tsx            |    4 +-
 superset-frontend/src/features/home/ChartTable.tsx |    2 +-
 .../src/features/home/DashboardTable.tsx           |    2 +-
 superset-frontend/src/features/home/EmptyState.tsx |    4 +-
 .../src/features/home/LanguagePicker.tsx           |    4 +-
 superset-frontend/src/features/home/Menu.test.tsx  |  115 +-
 superset-frontend/src/features/home/Menu.tsx       |    2 +-
 superset-frontend/src/features/home/RightMenu.tsx  |    9 +-
 .../src/features/home/SavedQueries.tsx             |    4 +-
 superset-frontend/src/features/home/SubMenu.tsx    |    9 +-
 .../src/features/home/commonMenuData.ts            |    2 +-
 .../src/features/owners/OwnerSelectLabel/index.tsx |    2 +-
 .../src/features/queries/QueryPreviewModal.tsx     |    4 +-
 .../features/queries/SavedQueryPreviewModal.tsx    |    4 +-
 .../src/features/queries/SyntaxHighlighterCopy.tsx |    4 +-
 .../ReportModal/HeaderReportDropdown/index.tsx     |    4 +-
 .../src/features/reports/ReportModal/actions.ts    |    2 +-
 .../src/features/reports/ReportModal/index.tsx     |    5 +-
 .../src/features/reports/ReportModal/styles.tsx    |    2 +-
 .../src/features/rls/RowLevelSecurityModal.tsx     |    4 +-
 superset-frontend/src/features/rls/constants.ts    |    2 +-
 .../src/features/roles/RoleFormItems.tsx           |   53 +-
 .../src/features/roles/RoleListAddModal.test.tsx   |   45 +-
 .../src/features/roles/RoleListAddModal.tsx        |   23 +-
 .../src/features/roles/RoleListDuplicateModal.tsx  |    2 +-
 .../src/features/roles/RoleListEditModal.test.tsx  |  328 ++-
 .../src/features/roles/RoleListEditModal.tsx       |  179 +-
 superset-frontend/src/features/roles/types.ts      |   12 +-
 superset-frontend/src/features/roles/utils.test.ts |  547 +++++
 superset-frontend/src/features/roles/utils.ts      |  165 ++
 .../src/features/tags/BulkTagModal.tsx             |    4 +-
 superset-frontend/src/features/tags/TagCard.tsx    |    2 +-
 superset-frontend/src/features/tags/TagModal.tsx   |    4 +-
 .../src/features/tasks/TaskPayloadPopover.tsx      |    2 +-
 .../src/features/tasks/TaskStackTracePopover.tsx   |    4 +-
 .../src/features/tasks/TaskStatusIcon.tsx          |    3 +-
 .../src/features/themes/ThemeModal.tsx             |    5 +-
 .../src/features/userInfo/UserInfoModal.tsx        |    2 +-
 .../src/features/users/UserListModal.tsx           |    2 +-
 superset-frontend/src/features/users/utils.ts      |    2 +-
 .../components/Range/RangeFilterPlugin.stories.tsx |    2 +-
 .../components/Range/RangeFilterPlugin.test.tsx    |    2 +-
 .../filters/components/Range/RangeFilterPlugin.tsx |    4 +-
 .../src/filters/components/Range/buildQuery.ts     |    2 +-
 .../src/filters/components/Range/controlPanel.ts   |    2 +-
 .../src/filters/components/Range/index.ts          |    2 +-
 .../components/Select/SelectFilterPlugin.tsx       |    8 +-
 .../filters/components/Select/buildQuery.test.ts   |    2 +-
 .../src/filters/components/Select/buildQuery.ts    |    2 +-
 .../src/filters/components/Select/controlPanel.ts  |    2 +-
 .../src/filters/components/Select/index.ts         |    2 +-
 .../filters/components/Select/transformProps.ts    |    2 +-
 .../src/filters/components/Select/types.ts         |    2 +-
 .../filters/components/Time/TimeFilterPlugin.tsx   |    2 +-
 .../src/filters/components/Time/controlPanel.ts    |    2 +-
 .../src/filters/components/Time/index.ts           |    2 +-
 .../TimeColumn/TimeColumnFilterPlugin.tsx          |    4 +-
 .../filters/components/TimeColumn/controlPanel.ts  |    2 +-
 .../src/filters/components/TimeColumn/index.ts     |    2 +-
 .../components/TimeGrain/TimeGrainFilterPlugin.tsx |    4 +-
 .../filters/components/TimeGrain/controlPanel.ts   |    2 +-
 .../src/filters/components/TimeGrain/index.ts      |    2 +-
 superset-frontend/src/filters/components/common.ts |    2 +-
 superset-frontend/src/filters/utils.test.ts        |    2 +-
 superset-frontend/src/filters/utils.ts             |    2 +-
 .../src/hooks/apiResources/datasets.ts             |    2 +-
 .../hooks/useConfirmModal/useConfirmModal.test.tsx |    2 +-
 superset-frontend/src/hooks/useJsonTreeTheme.ts    |    2 +-
 .../src/hooks/useThemeMenuItems.test.tsx           |    2 +-
 superset-frontend/src/hooks/useThemeMenuItems.tsx  |    4 +-
 .../src/hooks/useUnsavedChangesPrompt/index.ts     |    2 +-
 superset-frontend/src/middleware/asyncEvent.ts     |    2 +-
 superset-frontend/src/pages/ActionLog/index.tsx    |    4 +-
 .../src/pages/AlertReportList/index.tsx            |    4 +-
 superset-frontend/src/pages/AllEntities/index.tsx  |    4 +-
 .../src/pages/AnnotationLayerList/index.tsx        |    2 +-
 .../src/pages/AnnotationList/index.tsx             |    4 +-
 superset-frontend/src/pages/Chart/index.tsx        |    2 +-
 .../src/pages/ChartCreation/ChartCreation.test.tsx |    2 +-
 .../src/pages/ChartCreation/index.tsx              |    4 +-
 superset-frontend/src/pages/ChartList/index.tsx    |    5 +-
 .../src/pages/CssTemplateList/index.tsx            |    2 +-
 .../DashboardList/DashboardList.behavior.test.tsx  |  394 ++++
 .../DashboardList/DashboardList.cardview.test.tsx  |  417 ++++
 .../DashboardList/DashboardList.listview.test.tsx  |  402 ++++
 .../DashboardList.permissions.test.tsx             |  340 +++
 .../src/pages/DashboardList/DashboardList.test.tsx |  391 ++--
 .../DashboardList/DashboardList.testHelpers.tsx    |  360 +++
 .../src/pages/DashboardList/index.tsx              |    4 +-
 superset-frontend/src/pages/DatabaseList/index.tsx |    4 +-
 superset-frontend/src/pages/DatasetList/index.tsx  |    4 +-
 .../src/pages/ExecutionLogList/index.tsx           |    4 +-
 .../src/pages/FileHandler/index.test.tsx           |   22 +-
 superset-frontend/src/pages/FileHandler/index.tsx  |    2 +-
 superset-frontend/src/pages/GroupsList/index.tsx   |    2 +-
 superset-frontend/src/pages/Home/index.tsx         |    4 +-
 superset-frontend/src/pages/Login/index.tsx        |    4 +-
 .../src/pages/QueryHistoryList/index.tsx           |    4 +-
 .../src/pages/RedirectWarning/index.tsx            |  175 ++
 .../src/pages/RedirectWarning/utils.test.ts        |  124 ++
 .../src/pages/RedirectWarning/utils.ts             |   96 +
 superset-frontend/src/pages/Register/index.tsx     |    4 +-
 .../src/pages/RolesList/RolesList.test.tsx         |   27 +-
 superset-frontend/src/pages/RolesList/index.tsx    |   75 +-
 .../src/pages/RowLevelSecurityList/index.tsx       |    2 +-
 .../src/pages/SavedQueryList/index.tsx             |    4 +-
 superset-frontend/src/pages/SqlLab/index.tsx       |    2 +-
 superset-frontend/src/pages/Tags/index.tsx         |    2 +-
 superset-frontend/src/pages/TaskList/index.tsx     |    3 +-
 superset-frontend/src/pages/ThemeList/index.tsx    |    5 +-
 superset-frontend/src/pages/UserInfo/index.tsx     |    4 +-
 .../src/pages/UserRegistrations/index.tsx          |    2 +-
 superset-frontend/src/pages/UsersList/index.tsx    |    2 +-
 superset-frontend/src/preamble.ts                  |    4 +-
 superset-frontend/src/setup/setupClient.ts         |    2 +-
 superset-frontend/src/theme/ThemeController.ts     |    4 +-
 superset-frontend/src/theme/ThemeProvider.tsx      |    2 +-
 .../src/theme/hooks/useThemeValidation.ts          |    2 +-
 .../src/theme/tests/ThemeController.test.ts        |    2 +-
 .../src/theme/tests/ThemeProvider.test.tsx         |    2 +-
 .../theme/utils/themeStructureValidation.test.ts   |    2 +-
 .../src/theme/utils/themeStructureValidation.ts    |    2 +-
 superset-frontend/src/types/bootstrapTypes.ts      |    9 +-
 superset-frontend/src/utils/downloadAsImage.tsx    |    4 +-
 superset-frontend/src/utils/downloadAsPdf.ts       |    4 +-
 superset-frontend/src/utils/export.test.ts         |    4 +-
 superset-frontend/src/utils/export.ts              |    2 +-
 superset-frontend/src/utils/fetchOptions.ts        |    2 +-
 .../utils/getChartRequiredFieldsMissingMessage.ts  |    2 +-
 superset-frontend/src/utils/pathUtils.test.ts      |   71 +
 superset-frontend/src/utils/pathUtils.ts           |   37 +-
 superset-frontend/src/views/App.tsx                |   47 +-
 superset-frontend/src/views/CRUD/hooks.ts          |    2 +-
 superset-frontend/src/views/CRUD/utils.tsx         |    5 +-
 .../src/views/RootContextProviders.tsx             |   17 +-
 superset-frontend/src/views/index.tsx              |    2 +-
 superset-frontend/src/views/menu.tsx               |    3 +-
 superset-frontend/src/views/routes.tsx             |   11 +
 .../src/visualizations/TimeTable/TimeTable.tsx     |    4 +-
 .../components/SparklineCell/SparklineCell.tsx     |    2 +-
 .../TimeTable/config/controlPanel/controlPanel.ts  |    2 +-
 .../config/transformProps/transformProps.test.ts   |    2 +-
 .../src/visualizations/TimeTable/constants.ts      |    2 +-
 .../src/visualizations/TimeTable/index.ts          |    2 +-
 .../ExampleComponent/ExampleComponent.tsx          |    2 +-
 superset-frontend/webpack.config.js                |    7 +-
 superset-websocket/package-lock.json               |   72 +-
 superset-websocket/package.json                    |    8 +-
 superset-websocket/utils/client-ws-app/.nvmrc      |    2 +-
 superset/charts/schemas.py                         |   12 +-
 superset/commands/database/export.py               |    9 +
 superset/commands/database/importers/v1/utils.py   |   26 +-
 superset/commands/distributed_lock/acquire.py      |    2 +-
 superset/commands/distributed_lock/base.py         |    6 +-
 superset/commands/distributed_lock/release.py      |    2 +-
 superset/commands/importers/v1/__init__.py         |    4 +
 superset/commands/importers/v1/assets.py           |    4 +
 superset/commands/importers/v1/utils.py            |   19 +
 superset/commands/tasks/cancel.py                  |    2 +-
 superset/commands/tasks/internal_update.py         |    2 +-
 superset/commands/tasks/prune.py                   |    2 +-
 superset/commands/tasks/submit.py                  |    2 +-
 superset/commands/tasks/update.py                  |    2 +-
 superset/config.py                                 |   22 +-
 superset/connectors/sqla/models.py                 |    2 +-
 superset/core/api/core_api_injection.py            |  159 +-
 superset/core/mcp/core_mcp_injection.py            |   74 +-
 superset/daos/base.py                              |    4 +-
 superset/daos/tag.py                               |    7 +
 superset/daos/tasks.py                             |    2 +-
 superset/dashboards/api.py                         |   34 +-
 superset/databases/api.py                          |   14 +
 superset/databases/schemas.py                      |   62 +
 superset/db_engine_specs/base.py                   |    6 +
 superset/db_engine_specs/databend.py               |   21 +-
 superset/distributed_lock/__init__.py              |    2 +-
 superset/extensions/context.py                     |   90 +
 superset/extensions/contributions.py               |   94 +
 superset/extensions/utils.py                       |    7 +-
 superset/importexport/api.py                       |   13 +
 superset/initialization/__init__.py                |   18 +-
 superset/key_value/models.py                       |    2 +-
 superset/mcp_service/CLAUDE.md                     |   16 +-
 superset/mcp_service/app.py                        |   40 +-
 superset/mcp_service/chart/chart_utils.py          |  289 ++-
 .../chart/prompts/create_chart_guided.py           |    2 +-
 superset/mcp_service/chart/schemas.py              |  188 +-
 superset/mcp_service/chart/tool/generate_chart.py  |  196 +-
 superset/mcp_service/chart/tool/get_chart_data.py  |    2 +-
 superset/mcp_service/chart/tool/get_chart_info.py  |    2 +-
 .../mcp_service/chart/tool/get_chart_preview.py    |    2 +-
 superset/mcp_service/chart/tool/list_charts.py     |    2 +-
 superset/mcp_service/chart/tool/update_chart.py    |    2 +-
 .../mcp_service/chart/tool/update_chart_preview.py |    2 +-
 .../chart/validation/schema_validator.py           |  169 +-
 .../tool/add_chart_to_existing_dashboard.py        |    2 +-
 .../dashboard/tool/generate_dashboard.py           |    2 +-
 .../dashboard/tool/get_dashboard_info.py           |    2 +-
 .../mcp_service/dashboard/tool/list_dashboards.py  |    2 +-
 .../mcp_service/dataset/tool/get_dataset_info.py   |    2 +-
 superset/mcp_service/dataset/tool/list_datasets.py |    2 +-
 .../explore/tool/generate_explore_link.py          |    2 +-
 superset/mcp_service/server.py                     |   27 +
 superset/mcp_service/sql_lab/tool/execute_sql.py   |    9 +-
 .../sql_lab/tool/open_sql_lab_with_context.py      |    2 +-
 superset/mcp_service/system/prompts/quickstart.py  |    2 +-
 superset/mcp_service/system/schemas.py             |    7 +
 .../mcp_service/system/tool/get_instance_info.py   |   13 +-
 superset/mcp_service/system/tool/get_schema.py     |    2 +-
 superset/mcp_service/system/tool/health_check.py   |    2 +-
 superset/models/core.py                            |    9 +-
 superset/models/dashboard.py                       |    2 +-
 superset/models/helpers.py                         |    2 +-
 superset/models/slice.py                           |    2 +-
 superset/models/sql_lab.py                         |    5 +-
 superset/models/task_subscribers.py                |    2 +-
 superset/models/tasks.py                           |    4 +-
 superset/reports/notifications/email.py            |    5 +
 superset/sql/execution/executor.py                 |   24 +-
 superset/tags/models.py                            |    2 +-
 superset/tasks/constants.py                        |    2 +-
 superset/tasks/context.py                          |    2 +-
 superset/tasks/decorators.py                       |   17 +-
 superset/tasks/locks.py                            |    4 +-
 superset/tasks/manager.py                          |   10 +-
 superset/tasks/scheduler.py                        |    2 +-
 superset/tasks/utils.py                            |    2 +-
 superset/templates/superset/spa.html               |    5 +
 superset/utils/cache_manager.py                    |   34 +-
 superset/utils/json.py                             |   43 +
 superset/utils/link_redirect.py                    |  149 ++
 superset/utils/logging_configurator.py             |    7 +
 superset/utils/oauth2.py                           |    4 +
 superset/utils/pandas_postprocessing/geography.py  |    6 +-
 superset/utils/pandas_postprocessing/resample.py   |    2 +-
 superset/utils/webdriver.py                        |   34 +-
 superset/views/redirect.py                         |   76 +
 superset/viz.py                                    |   36 +-
 tests/integration_tests/databases/api_tests.py     |   91 +
 tests/integration_tests/fixtures/importexport.py   |   26 +
 tests/integration_tests/security_tests.py          |    1 +
 tests/integration_tests/tasks/api_tests.py         |    4 +-
 .../tasks/commands/test_cancel.py                  |    2 +-
 .../tasks/commands/test_internal_update.py         |    2 +-
 .../integration_tests/tasks/commands/test_prune.py |    2 +-
 .../tasks/commands/test_submit.py                  |    2 +-
 .../tasks/commands/test_update.py                  |    2 +-
 .../integration_tests/tasks/test_event_handlers.py |    2 +-
 .../tasks/test_subscription_visibility.py          |    2 +-
 .../integration_tests/tasks/test_sync_join_wait.py |    6 +-
 tests/integration_tests/tasks/test_throttling.py   |    2 +-
 tests/integration_tests/tasks/test_timeout.py      |    2 +-
 .../integration_tests/views/test_redirect_view.py  |   66 +
 tests/unit_tests/dao/base_dao_test.py              |    2 +-
 tests/unit_tests/daos/test_tasks.py                |    2 +-
 tests/unit_tests/databases/api_test.py             |   70 +
 .../databases/commands/importers/v1/import_test.py |  123 ++
 tests/unit_tests/databases/schema_tests.py         |  106 +
 tests/unit_tests/db_engine_specs/test_base.py      |   91 +
 tests/unit_tests/extension_tests.py                |   21 +-
 tests/unit_tests/extensions/test_types.py          |   84 +-
 tests/unit_tests/importexport/api_test.py          |   52 +
 .../mcp_service/chart/test_new_chart_types.py      |  929 ++++++++
 .../mcp_service/chart/tool/test_generate_chart.py  |   74 +
 .../mcp_service/sql_lab/tool/test_execute_sql.py   |    2 +-
 .../system/tool/test_get_current_user.py           |    5 +
 tests/unit_tests/mcp_service/test_mcp_server.py    |   34 +
 tests/unit_tests/sql/execution/test_executor.py    |   19 +-
 tests/unit_tests/tags/commands/update_test.py      |   60 +
 tests/unit_tests/tasks/test_decorators.py          |    2 +-
 tests/unit_tests/tasks/test_handlers.py            |    6 +-
 tests/unit_tests/tasks/test_manager.py             |   34 +-
 tests/unit_tests/tasks/test_timeout.py             |   34 +-
 tests/unit_tests/tasks/test_utils.py               |    2 +-
 tests/unit_tests/utils/json_tests.py               |  139 ++
 tests/unit_tests/utils/oauth2_tests.py             |   56 +
 tests/unit_tests/utils/test_link_redirect.py       |  143 ++
 1416 files changed, 23388 insertions(+), 9895 deletions(-)

diff --cc superset-frontend/src/features/alerts/AlertReportModal.test.tsx
index 1bf64bcf8a4,b025a27c018..a29a6d1322b
--- a/superset-frontend/src/features/alerts/AlertReportModal.test.tsx
+++ b/superset-frontend/src/features/alerts/AlertReportModal.test.tsx
@@@ -913,760 -867,502 +921,1211 @@@ test('dashboard with no tabs disables t
    userEvent.click(screen.getByTestId('contents-panel'));
    await screen.findByText(/test dashboard/i);
  
 -  const filterDropdown = screen.getByRole('combobox', {
 -    name: /select filter/i,
 -  });
 -  expect(filterDropdown).toBeInTheDocument();
 +  const tabSelector = document.querySelector('.ant-select-disabled');
 +  expect(tabSelector).toBeInTheDocument();
 +});
  
 -  userEvent.click(filterDropdown);
 +test('dashboard with no tabs and no filters hides filter add link', async () 
=> {
 +  fetchMock.removeRoute(tabsEndpoint);
 +  fetchMock.get(tabsEndpoint, noTabsResponse, { name: tabsEndpoint });
  
 -  const filterOption = await waitFor(() => {
 -    const virtualList = document.querySelector('.rc-virtual-list');
 -    return within(virtualList as HTMLElement).getByText('Test Filter 1');
 +  render(<AlertReportModal {...generateMockedProps(true, true)} />, {
 +    useRedux: true,
    });
  
 -  userEvent.click(filterOption);
 +  userEvent.click(screen.getByTestId('contents-panel'));
 +  await screen.findByText(/test dashboard/i);
  
 +  // Wait for tabs fetch to complete
    await waitFor(() => {
 -    const selectionItem = document.querySelector(
 -      '.ant-select-selection-item[title="Test Filter 1"]',
 -    );
 -    expect(selectionItem).toBeInTheDocument();
 +    expect(
 +      fetchMock.callHistory.calls(tabsEndpoint).length,
 +    ).toBeGreaterThan(0);
    });
  
 -  const selectContainer = filterDropdown.closest('.ant-select');
 +  // Tab selector should be disabled (no tabs)
 +  const disabledSelects = document.querySelectorAll('.ant-select-disabled');
 +  expect(disabledSelects.length).toBeGreaterThanOrEqual(1);
  
 -  const clearIcon = selectContainer?.querySelector(
 -    '.ant-select-clear [aria-label="close-circle"]',
 -  );
 -  expect(clearIcon).toBeInTheDocument();
 -  userEvent.click(clearIcon as Element);
 +  // Filter Select should also be disabled (no filter options available)
 +  expect(disabledSelects.length).toBeGreaterThanOrEqual(2);
 +
 +  // "Apply another dashboard filter" link should NOT appear
 +  // because noTabsResponse has empty native_filters ({})
 +  expect(
 +    screen.queryByText(/apply another dashboard filter/i),
 +  ).not.toBeInTheDocument();
 +});
  
 +test('dashboard switching resets tab and filter selections', async () => {
 +  // Return dashboard options so user can switch
 +  const dashboardOptions = {
 +    result: [
 +      { text: 'Test Dashboard', value: 1 },
 +      { text: 'Other Dashboard', value: 99 },
 +    ],
 +    count: 2,
 +  };
 +  fetchMock.removeRoute(dashboardEndpoint);
 +  fetchMock.get(dashboardEndpoint, dashboardOptions);
 +  fetchMock.removeRoute(reportDashboardEndpoint);
 +  fetchMock.get(reportDashboardEndpoint, dashboardOptions);
 +
 +  // Dashboard 1 has tabs and filters
 +  fetchMock.removeRoute(tabsEndpoint);
 +  fetchMock.get(tabsEndpoint, tabsWithFilters, { name: tabsEndpoint });
 +
 +  // Dashboard 99 has no tabs
 +  const tabs99 = 'glob:*/api/v1/dashboard/99/tabs';
 +  fetchMock.get(tabs99, noTabsResponse, { name: tabs99 });
 +
 +  render(<AlertReportModal {...generateMockedProps(true, true)} />, {
 +    useRedux: true,
 +  });
 +
 +  userEvent.click(screen.getByTestId('contents-panel'));
 +  await screen.findByText(/test dashboard/i);
 +
 +  // Wait for tabs to load from dashboard 1
    await waitFor(() => {
 -    const selectionItem = document.querySelector(
 -      '.ant-select-selection-item[title="Test Filter 1"]',
 -    );
 -    expect(selectionItem).not.toBeInTheDocument();
 +    expect(screen.getAllByText(/select tab/i)).toHaveLength(1);
    });
  
 -  userEvent.click(filterDropdown);
 +  // Verify filters are available
    await waitFor(() => {
 -    const virtualList = document.querySelector('.rc-virtual-list');
      expect(
 -      within(virtualList as HTMLElement).getByText('Test Filter 1'),
 +      screen.getByRole('combobox', { name: /select filter/i }),
      ).toBeInTheDocument();
    });
 +
 +  // Switch to "Other Dashboard"
 +  const dashboardSelect = screen.getByRole('combobox', {
 +    name: /dashboard/i,
 +  });
 +  userEvent.clear(dashboardSelect);
 +  userEvent.type(dashboardSelect, 'Other Dashboard{enter}');
 +
 +  // Tab selector should reset: "Other Dashboard" has no tabs, so disabled 
with placeholder
 +  await waitFor(() => {
 +    expect(screen.getByText(/select a tab/i)).toBeInTheDocument();
 +  });
 +
 +  // Filter row should reset to empty (no filter selected)
 +  await waitFor(() => {
 +    const filterSelects = screen.getAllByRole('combobox', {
 +      name: /select filter/i,
 +    });
 +    // Filter select should have no selected value (placeholder state)
 +    filterSelects.forEach(select => {
 +      const container = select.closest('.ant-select');
 +      expect(
 +        container?.querySelector('.ant-select-selection-item'),
 +      ).not.toBeInTheDocument();
 +    });
 +  });
 +
 +  // Restore dashboard endpoints
 +  fetchMock.removeRoute(dashboardEndpoint);
 +  fetchMock.get(dashboardEndpoint, { result: [] });
 +  fetchMock.removeRoute(reportDashboardEndpoint);
 +  fetchMock.get(reportDashboardEndpoint, { result: [] });
 +  fetchMock.removeRoute(tabs99);
  });
  
 -const setupAnchorMocks = (
 -  nativeFilters: Record<string, unknown>,
 -  anchor = 'TAB-abc',
 -  tabsOverride?: {
 -    all_tabs: Record<string, string>;
 -    tab_tree: { title: string; value: string }[];
 -  },
 -) => {
 -  const payloadWithAnchor = {
 -    ...generateMockPayload(true),
 -    extra: { dashboard: { anchor } },
 -  };
 +test('different dashboard populates its own tabs and filters', async () => {
 +  // Set up a report (id:99) that uses dashboard 99 instead of dashboard 1.
 +  // This tests that the component correctly loads tabs and filters for a
 +  // different dashboard (the "dashboard B has its own data" case).
 +  const FETCH_REPORT_DASH99_ENDPOINT = 'glob:*/api/v1/report/99';
 +  fetchMock.get(FETCH_REPORT_DASH99_ENDPOINT, {
 +    result: {
 +      ...generateMockPayload(true),
 +      id: 99,
 +      type: 'Report',
 +      dashboard: { id: 99, dashboard_title: 'Other Dashboard' },
 +    },
 +  });
  
 -  const defaultTabs = {
 -    all_tabs: { [anchor]: `Tab ${anchor}` },
 -    tab_tree: [{ title: `Tab ${anchor}`, value: anchor }],
 +  // Dashboard 99 has its own tabs (Tab Alpha, Tab Beta) and a Region Filter
 +  const tabs99Endpoint = 'glob:*/api/v1/dashboard/99/tabs';
 +  const dash99Tabs = {
 +    result: {
 +      all_tabs: { TAB_A: 'Tab Alpha', TAB_B: 'Tab Beta' },
 +      tab_tree: [
 +        { title: 'Tab Alpha', value: 'TAB_A' },
 +        { title: 'Tab Beta', value: 'TAB_B' },
 +      ],
 +      native_filters: {
 +        all: [
 +          {
 +            id: 'NATIVE_FILTER-R1',
 +            name: 'Region Filter',
 +            filterType: 'filter_select',
 +            targets: [{ column: { name: 'region' }, datasetId: 3 }],
 +            adhoc_filters: [],
 +          },
 +        ],
 +        TAB_A: [
 +          {
 +            id: 'NATIVE_FILTER-R1',
 +            name: 'Region Filter',
 +            filterType: 'filter_select',
 +            targets: [{ column: { name: 'region' }, datasetId: 3 }],
 +            adhoc_filters: [],
 +          },
 +        ],
 +        TAB_B: [],
 +      },
 +    },
    };
 -  const tabs = tabsOverride ?? defaultTabs;
 +  fetchMock.get(tabs99Endpoint, dash99Tabs, { name: 'tabs-99' });
  
 -  // Clear call history so waitFor assertions don't match calls from prior 
tests.
 -  fetchMock.callHistory.clear();
 +  const props = generateMockedProps(true, true);
 +  const dash99Props = { ...props, alert: { ...validAlert, id: 99 } };
  
 -  // Only replace the named routes that need anchor-specific overrides;
 -  // unnamed related-endpoint routes (owners, database, etc.) stay intact.
 -  fetchMock.removeRoute(FETCH_DASHBOARD_ENDPOINT);
 -  fetchMock.removeRoute(FETCH_CHART_ENDPOINT);
 -  fetchMock.removeRoute(tabsEndpoint);
 +  render(<AlertReportModal {...dash99Props} />, { useRedux: true });
  
 -  fetchMock.get(
 -    FETCH_DASHBOARD_ENDPOINT,
 -    { result: payloadWithAnchor },
 -    { name: FETCH_DASHBOARD_ENDPOINT },
 -  );
 -  fetchMock.get(
 -    FETCH_CHART_ENDPOINT,
 -    { result: generateMockPayload(false) },
 -    { name: FETCH_CHART_ENDPOINT },
 -  );
 -  fetchMock.get(
 -    tabsEndpoint,
 -    {
 -      result: {
 -        ...tabs,
 -        native_filters: nativeFilters,
 -      },
 +  userEvent.click(screen.getByTestId('contents-panel'));
 +  await screen.findByText(/other dashboard/i);
 +
 +  // Wait for dashboard 99 tabs to load
 +  await waitFor(
 +    () => {
 +      expect(
 +        fetchMock.callHistory.calls('tabs-99').length,
 +      ).toBeGreaterThan(0);
      },
 -    { name: tabsEndpoint },
 +    { timeout: 5000 },
    );
 -};
  
 -const restoreAnchorMocks = () => {
 -  fetchMock.removeRoute(FETCH_DASHBOARD_ENDPOINT);
 -  fetchMock.get(
 -    FETCH_DASHBOARD_ENDPOINT,
 -    { result: generateMockPayload(true) },
 -    { name: FETCH_DASHBOARD_ENDPOINT },
 -  );
 -  fetchMock.removeRoute(FETCH_CHART_ENDPOINT);
 -  fetchMock.get(
 -    FETCH_CHART_ENDPOINT,
 -    { result: generateMockPayload(false) },
 -    { name: FETCH_CHART_ENDPOINT },
 -  );
 -  fetchMock.removeRoute(tabsEndpoint);
 -  fetchMock.get(
 -    tabsEndpoint,
 -    { result: { all_tabs: {}, tab_tree: [] } },
 -    { name: tabsEndpoint },
 +  // Tab selector should be enabled (dashboard 99 has tabs)
 +  await waitFor(() => {
 +    const treeSelect = document.querySelector('.ant-tree-select');
 +    expect(treeSelect).toBeInTheDocument();
 +    expect(treeSelect).not.toHaveClass('ant-select-disabled');
 +  });
 +
 +  // Filter dropdown should show dashboard 99's "Region Filter"
 +  const filterSelect = await waitFor(() =>
 +    screen.getByRole('combobox', { name: /select filter/i }),
    );
 -};
 +  userEvent.click(filterSelect);
  
 -test('no error toast when anchor tab has no scoped native filters', async () 
=> {
 -  setupAnchorMocks({
 -    all: [
 -      {
 -        id: 'NATIVE_FILTER-1',
 -        name: 'Filter 1',
 -        filterType: 'filter_select',
 -        targets: [{ column: { name: 'col' } }],
 -        adhoc_filters: [],
 -      },
 -    ],
 +  await waitFor(() => {
 +    const virtualLists = document.querySelectorAll('.rc-virtual-list');
 +    const lastVirtualList = virtualLists[virtualLists.length - 1];
 +    expect(
 +      within(lastVirtualList as HTMLElement).getByText('Region Filter'),
 +    ).toBeInTheDocument();
    });
  
 -  const store = createStore({}, reducerIndex);
 +  // Dashboard 1's filters (Country/City) should NOT appear
 +  const virtualLists = document.querySelectorAll('.rc-virtual-list');
 +  const lastVirtualList = virtualLists[virtualLists.length - 1];
 +  expect(
 +    within(lastVirtualList as HTMLElement).queryByText('Country Filter'),
 +  ).not.toBeInTheDocument();
  
 -  try {
 -    render(<AlertReportModal {...generateMockedProps(true, true)} />, {
 -      store,
 -    });
 +  // Cleanup
 +  fetchMock.removeRoute(FETCH_REPORT_DASH99_ENDPOINT);
 +  fetchMock.removeRoute('tabs-99');
 +});
  
 -    userEvent.click(screen.getByTestId('contents-panel'));
 +test('dashboard tabs fetch failure shows error toast', async () => {
 +  fetchMock.removeRoute(tabsEndpoint);
 +  fetchMock.get(tabsEndpoint, 500, { name: tabsEndpoint });
 +
 +  const store = createStore({}, reducerIndex);
 +
 +  render(<AlertReportModal {...generateMockedProps(true, true)} />, {
 +    useRedux: true,
 +    store,
 +  });
 +
 +  userEvent.click(screen.getByTestId('contents-panel'));
 +  await screen.findByText(/test dashboard/i);
 +
 +  // Tab selector should remain disabled (no tabs loaded)
 +  const tabSelector = document.querySelector('.ant-select-disabled');
 +  expect(tabSelector).toBeInTheDocument();
 +
 +  // Verify the tabs request was attempted
 +  const tabsCalls = fetchMock.callHistory.calls(tabsEndpoint);
 +  expect(tabsCalls.length).toBeGreaterThan(0);
 +
 +  // Verify danger toast was dispatched for the fetch failure
 +  await waitFor(() => {
 +    const toasts = (store.getState() as any).messageToasts;
 +    expect(toasts.length).toBeGreaterThan(0);
 +    expect(
 +      toasts.some((t: { text: string }) =>
 +        t.text.includes('error retrieving dashboard tabs'),
 +      ),
 +    ).toBe(true);
 +  });
 +});
 +
 +test('switching content type to chart hides tab and filter sections', async 
() => {
 +  fetchMock.removeRoute(tabsEndpoint);
 +  fetchMock.get(tabsEndpoint, tabsWithFilters, { name: tabsEndpoint });
 +
 +  render(<AlertReportModal {...generateMockedProps(true, true)} />, {
 +    useRedux: true,
 +  });
 +
 +  userEvent.click(screen.getByTestId('contents-panel'));
 +  await screen.findByText(/test dashboard/i);
 +
 +  // Tab selector and filter dropdowns should be visible for dashboard
 +  expect(screen.getAllByText(/select tab/i)).toHaveLength(1);
 +  expect(
 +    screen.getByRole('combobox', { name: /select filter/i }),
 +  ).toBeInTheDocument();
 +
 +  // Switch to chart
 +  const contentTypeSelector = screen.getByRole('combobox', {
 +    name: /select content type/i,
 +  });
 +  await comboboxSelect(contentTypeSelector, 'Chart', () =>
 +    screen.getByRole('combobox', { name: /chart/i }),
 +  );
 +
 +  // Tab and filter sections should be hidden
 +  expect(screen.queryByText(/select tab/i)).not.toBeInTheDocument();
 +  expect(
 +    screen.queryByRole('combobox', { name: /select filter/i }),
 +  ).not.toBeInTheDocument();
 +});
 +
 +test('adding and removing dashboard filter rows', async () => {
 +  fetchMock.removeRoute(tabsEndpoint);
 +  fetchMock.get(tabsEndpoint, tabsWithFilters, { name: tabsEndpoint });
 +
 +  render(<AlertReportModal {...generateMockedProps(true, true)} />, {
 +    useRedux: true,
 +  });
 +
 +  userEvent.click(screen.getByTestId('contents-panel'));
 +  await screen.findByText(/test dashboard/i);
 +
 +  // Wait for filter options to load
 +  await waitFor(() => {
 +    expect(
 +      screen.getByRole('combobox', { name: /select filter/i }),
 +    ).toBeInTheDocument();
 +  });
 +
 +  // Should start with 1 filter row
 +  const initialFilterSelects = screen.getAllByRole('combobox', {
 +    name: /select filter/i,
 +  });
 +  expect(initialFilterSelects).toHaveLength(1);
 +
 +  // Click "Apply another dashboard filter"
 +  const addFilterButton = screen.getByText(/apply another dashboard filter/i);
 +  userEvent.click(addFilterButton);
 +
 +  // Should now have 2 filter rows
 +  await waitFor(() => {
 +    expect(
 +      screen.getAllByRole('combobox', { name: /select filter/i }),
 +    ).toHaveLength(2);
 +  });
 +
 +  // Remove the second filter row by clicking its delete icon
 +  const deleteIcons = document.querySelectorAll('.filters-trashcan');
 +  expect(deleteIcons.length).toBeGreaterThanOrEqual(2);
 +  fireEvent.click(deleteIcons[deleteIcons.length - 1]);
 +
 +  // Should be back to 1 filter row
 +  await waitFor(() => {
 +    expect(
 +      screen.getAllByRole('combobox', { name: /select filter/i }),
 +    ).toHaveLength(1);
 +  });
 +});
 +
 +test('alert shows condition section, report does not', () => {
 +  // Alert has 5 sections
 +  const { unmount } = render(
 +    <AlertReportModal {...generateMockedProps(false)} />,
 +    { useRedux: true },
 +  );
 +  expect(screen.getAllByRole('tab')).toHaveLength(5);
 +  expect(screen.getByTestId('alert-condition-panel')).toBeInTheDocument();
 +  unmount();
 +
 +  // Report has 4 sections, no condition panel
 +  render(<AlertReportModal {...generateMockedProps(true)} />, {
 +    useRedux: true,
 +  });
 +  expect(screen.getAllByRole('tab')).toHaveLength(4);
 +  
expect(screen.queryByTestId('alert-condition-panel')).not.toBeInTheDocument();
 +});
 +
 +test('submit includes conditionNotNull without threshold in alert payload', 
async () => {
 +  // Mock payload returns id:1, so updateResource PUTs to /api/v1/report/1
 +  fetchMock.put(
 +    'glob:*/api/v1/report/1',
 +    { id: 1, result: {} },
 +    { name: 'put-condition' },
 +  );
 +
 +  render(<AlertReportModal {...generateMockedProps(false, true, false)} />, {
 +    useRedux: true,
 +  });
 +
 +  // Wait for resource to load and all validation to pass
 +  await waitFor(() => {
 +    expect(
 +      screen.queryAllByRole('img', { name: /check-circle/i }),
 +    ).toHaveLength(5);
 +  });
 +
 +  // Open condition panel and select "not null"
 +  userEvent.click(screen.getByTestId('alert-condition-panel'));
 +  await screen.findByText(/smaller than/i);
 +  const condition = screen.getByRole('combobox', { name: /condition/i });
 +  await comboboxSelect(condition, 'not null', () =>
 +    screen.getAllByText(/not null/i)[0],
 +  );
 +
 +  expect(screen.getByRole('spinbutton')).toBeDisabled();
 +
 +  // Wait for Save to be enabled and click
 +  await waitFor(() => {
 +    expect(
 +      screen.getByRole('button', { name: /save/i }),
 +    ).toBeEnabled();
 +  });
 +  await waitFor(() =>
 +    userEvent.click(screen.getByRole('button', { name: /save/i })),
 +  );
 +
 +  // Verify the PUT payload
 +  await waitFor(() => {
 +    const calls = fetchMock.callHistory.calls('put-condition');
 +    expect(calls.length).toBeGreaterThan(0);
 +  });
 +
 +  const calls = fetchMock.callHistory.calls('put-condition');
 +  const body = JSON.parse(calls[calls.length - 1].options.body as string);
 +  expect(body.validator_type).toBe('not null');
 +  expect(body.validator_config_json).toEqual({});
 +
 +  fetchMock.removeRoute('put-condition');
 +});
 +
 +test('edit mode submit uses PUT and excludes read-only fields', async () => {
 +  // Mock payload returns id:1, so updateResource PUTs to /api/v1/report/1
 +  fetchMock.put(
 +    'glob:*/api/v1/report/1',
 +    { id: 1, result: {} },
 +    { name: 'put-edit' },
 +  );
 +
 +  render(<AlertReportModal {...generateMockedProps(false, true, false)} />, {
 +    useRedux: true,
 +  });
 +
 +  // Wait for resource to load and all validation to pass
 +  await waitFor(() => {
 +    expect(
 +      screen.queryAllByRole('img', { name: /check-circle/i }),
 +    ).toHaveLength(5);
 +  });
 +
 +  await waitFor(() => {
 +    expect(
 +      screen.getByRole('button', { name: /save/i }),
 +    ).toBeEnabled();
 +  });
 +  await waitFor(() =>
 +    userEvent.click(screen.getByRole('button', { name: /save/i })),
 +  );
 +
 +  await waitFor(() => {
 +    const calls = fetchMock.callHistory.calls('put-edit');
 +    expect(calls.length).toBeGreaterThan(0);
 +  });
 +
 +  const calls = fetchMock.callHistory.calls('put-edit');
 +  const body = JSON.parse(calls[calls.length - 1].options.body as string);
 +
 +  // Edit mode strips these read-only fields
 +  expect(body).not.toHaveProperty('id');
 +  expect(body).not.toHaveProperty('created_by');
 +  expect(body).not.toHaveProperty('last_eval_dttm');
 +  expect(body).not.toHaveProperty('last_state');
 +  expect(body).not.toHaveProperty('last_value');
 +  expect(body).not.toHaveProperty('last_value_row_json');
 +
 +  // Core fields remain
 +  expect(body.type).toBe('Alert');
 +  expect(body.name).toBe('Test Alert');
 +
 +  // Recipients from the loaded resource should be in payload
 +  expect(body.recipients).toBeDefined();
 +  expect(body.recipients.length).toBeGreaterThan(0);
 +  expect(body.recipients[0].type).toBe('Email');
 +
 +  fetchMock.removeRoute('put-edit');
 +});
 +
 +test('create mode submits POST and calls onAdd with response', async () => {
 +  fetchMock.post(
 +    'glob:*/api/v1/report/',
 +    { id: 100, result: {} },
 +    { name: 'create-post' },
 +  );
 +
 +  const props = generateMockedProps(true); // isReport, create mode (no alert)
 +  const onAdd = jest.fn();
 +  const createProps = { ...props, onAdd };
 +
 +  render(<AlertReportModal {...createProps} />, { useRedux: true });
 +
 +  expect(screen.getByText('Add report')).toBeInTheDocument();
 +
 +  // Fill name
 +  const nameInput = screen.getByPlaceholderText(/enter report name/i);
 +  userEvent.type(nameInput, 'My New Report');
 +
 +  // Open contents panel — content type defaults to Dashboard
 +  userEvent.click(screen.getByTestId('contents-panel'));
 +  await screen.findByRole('combobox', { name: /select content type/i });
 +
 +  // Switch content type to Chart (default is Dashboard)
 +  const contentTypeSelect = screen.getByRole('combobox', {
 +    name: /select content type/i,
 +  });
 +  userEvent.click(contentTypeSelect);
 +  const chartOption = await screen.findByText('Chart');
 +  userEvent.click(chartOption);
 +
 +  // Select a chart from the chart combobox
 +  const chartSelect = await screen.findByRole('combobox', {
 +    name: /chart/i,
 +  });
 +  userEvent.type(chartSelect, 'table');
 +  const tableChart = await screen.findByText('table chart');
 +  userEvent.click(tableChart);
 +
 +  // Open notification panel and type recipient email
 +  userEvent.click(screen.getByTestId('notification-method-panel'));
 +  const recipientInput = await screen.findByTestId('recipients');
 +  userEvent.type(recipientInput, '[email protected]');
 +
 +  // Wait for Add button to be enabled (use exact name to avoid matching
 +  // "Add CC Recipients" and "Add BCC Recipients" buttons)
 +  await waitFor(
 +    () => {
 +      expect(
 +        screen.getByRole('button', { name: 'Add' }),
 +      ).toBeEnabled();
 +    },
 +    { timeout: 5000 },
 +  );
 +
 +  // Click Add
 +  await waitFor(() =>
 +    userEvent.click(screen.getByRole('button', { name: 'Add' })),
 +  );
 +
 +  // Verify POST was called (not PUT)
 +  await waitFor(() => {
 +    const calls = fetchMock.callHistory.calls('create-post');
 +    expect(calls.length).toBeGreaterThan(0);
 +  });
 +
 +  const calls = fetchMock.callHistory.calls('create-post');
 +  const body = JSON.parse(calls[0].options.body as string);
 +
 +  expect(body.type).toBe('Report');
 +  expect(body.name).toBe('My New Report');
 +  expect(body.chart).toBe(1);
 +  // Chart content type means dashboard is null (mutually exclusive)
 +  expect(body.dashboard).toBeNull();
 +  expect(body.recipients).toBeDefined();
 +  expect(body.recipients[0].type).toBe('Email');
 +  expect(body.recipients[0].recipient_config_json.target).toBe(
 +    '[email protected]',
 +  );
 +
 +  // Verify onAdd was called with the response id
 +  await waitFor(() => {
 +    expect(onAdd).toHaveBeenCalledWith(100);
 +  });
 +
 +  fetchMock.removeRoute('create-post');
 +});
 +
 +test('create mode defaults to dashboard content type with chart null', async 
() => {
 +  // Coverage strategy: the create-mode POST pathway is tested via the chart
 +  // POST test above. The dashboard content payload (dashboard=value, 
chart=null)
 +  // is tested via the edit-mode PUT test below. This test verifies that 
create
 +  // mode reports default to Dashboard content type, completing the coverage:
 +  //   create POST method ← chart POST test
 +  //   dashboard payload shape ← edit-mode dashboard PUT test
 +  //   default content type = Dashboard ← THIS test
 +
 +  const props = generateMockedProps(true); // isReport, create mode
 +  render(<AlertReportModal {...props} />, { useRedux: true });
 +
 +  // Open contents panel
 +  userEvent.click(screen.getByTestId('contents-panel'));
 +  const contentTypeSelect = await screen.findByRole('combobox', {
 +    name: /select content type/i,
 +  });
 +
 +  // Default content type should be "Dashboard" (not "Chart")
 +  const selectedItem = contentTypeSelect
 +    .closest('.ant-select')
 +    ?.querySelector('.ant-select-selection-item');
 +  expect(selectedItem).toBeInTheDocument();
 +  expect(selectedItem?.textContent).toBe('Dashboard');
 +
 +  // Dashboard selector should be rendered (not chart selector)
 +  expect(
 +    screen.getByRole('combobox', { name: /dashboard/i }),
 +  ).toBeInTheDocument();
 +  expect(
 +    screen.queryByRole('combobox', { name: /chart/i }),
 +  ).not.toBeInTheDocument();
 +});
 +
 +test('dashboard content type submits dashboard id and null chart', async () 
=> {
 +  // Use a custom alert prop with dashboard content from the start,
 +  // matching the fetched resource shape (FETCH_DASHBOARD_ENDPOINT).
 +  const dashboardAlert: AlertObject = {
 +    ...validAlert,
 +    id: 1,
 +    dashboard_id: 1,
 +    chart_id: 0,
 +    dashboard: {
 +      id: 1,
 +      value: 1,
 +      label: 'Test Dashboard',
 +      dashboard_title: 'Test Dashboard',
 +    } as any,
 +    chart: undefined as any,
 +  };
 +
 +  fetchMock.put(
 +    'glob:*/api/v1/report/1',
 +    { id: 1, result: {} },
 +    { name: 'put-dashboard-payload' },
 +  );
 +
 +  const props = generateMockedProps(false, false);
 +  const editProps = { ...props, alert: dashboardAlert };
 +
 +  render(<AlertReportModal {...editProps} />, {
 +    useRedux: true,
 +  });
 +
 +  // Wait for resource to load and all validation to pass
 +  await waitFor(
 +    () => {
 +      expect(
 +        screen.queryAllByRole('img', { name: /check-circle/i }),
 +      ).toHaveLength(5);
 +    },
 +    { timeout: 5000 },
 +  );
 +
 +  await waitFor(() => {
 +    expect(
 +      screen.getByRole('button', { name: /save/i }),
 +    ).toBeEnabled();
 +  });
 +  await waitFor(() =>
 +    userEvent.click(screen.getByRole('button', { name: /save/i })),
 +  );
 +
 +  await waitFor(() => {
 +    const calls = fetchMock.callHistory.calls('put-dashboard-payload');
 +    expect(calls.length).toBeGreaterThan(0);
 +  });
 +
 +  const calls = fetchMock.callHistory.calls('put-dashboard-payload');
 +  const body = JSON.parse(calls[calls.length - 1].options.body as string);
 +
 +  // Dashboard payload: dashboard field is the numeric ID, chart is null
 +  expect(body.dashboard).toBe(1);
 +  expect(body.chart).toBeNull();
 +  expect(body.name).toBe('Test Alert');
 +  expect(body.recipients).toBeDefined();
 +
 +  fetchMock.removeRoute('put-dashboard-payload');
 +});
 +
 +// --------------- Existing filter reappear test ------------------
 +
 +test('filter reappears in dropdown after clearing with X icon', async () => {
 +  const chartDataEndpoint = 'glob:*/api/v1/chart/data*';
 +
 +  fetchMock.removeRoute(tabsEndpoint);
 +  fetchMock.get(
 +    tabsEndpoint,
 +    {
 +      result: {
 +        all_tabs: { tab1: 'Tab 1' },
 +        tab_tree: [{ title: 'Tab 1', value: 'tab1' }],
 +        native_filters: {
 +          all: [
 +            {
 +              id: 'NATIVE_FILTER-test1',
 +              name: 'Test Filter 1',
 +              filterType: 'filter_select',
 +              targets: [{ column: { name: 'test_column_1' } }],
 +              adhoc_filters: [],
 +            },
 +          ],
 +          tab1: [
 +            {
 +              id: 'NATIVE_FILTER-test2',
 +              name: 'Test Filter 2',
 +              filterType: 'filter_select',
 +              targets: [{ column: { name: 'test_column_2' } }],
 +              adhoc_filters: [],
 +            },
 +          ],
 +        },
 +      },
 +    },
 +    { name: tabsEndpoint },
 +  );
 +
 +  fetchMock.post(
 +    chartDataEndpoint,
 +    { result: [{ data: [] }] },
 +    {
 +      name: 'clear-icon-chart-data',
 +    },
 +  );
 +
 +  render(<AlertReportModal {...generateMockedProps(true, true)} />, {
 +    useRedux: true,
 +  });
 +
 +  userEvent.click(screen.getByTestId('contents-panel'));
 +  await screen.findByText(/test dashboard/i);
 +
 +  const filterDropdown = screen.getByRole('combobox', {
 +    name: /select filter/i,
 +  });
 +  expect(filterDropdown).toBeInTheDocument();
 +
 +  // Value selector should be disabled before any filter is selected
 +  const valueSelect = screen.getByRole('combobox', { name: /select value/i });
 +  
expect(valueSelect.closest('.ant-select')).toHaveClass('ant-select-disabled');
 +
 +  userEvent.click(filterDropdown);
 +
 +  const filterOption = await waitFor(() => {
 +    const virtualList = document.querySelector('.rc-virtual-list');
 +    return within(virtualList as HTMLElement).getByText('Test Filter 1');
 +  });
 +
 +  userEvent.click(filterOption);
 +
 +  await waitFor(() => {
 +    const selectionItem = document.querySelector(
 +      '.ant-select-selection-item[title="Test Filter 1"]',
 +    );
 +    expect(selectionItem).toBeInTheDocument();
 +  });
 +
 +  // After selecting a filter, getChartDataRequest resolves and value 
selector becomes enabled
 +  await waitFor(() => {
 +    expect(valueSelect.closest('.ant-select')).not.toHaveClass(
 +      'ant-select-disabled',
 +    );
 +  });
 +
 +  const selectContainer = filterDropdown.closest('.ant-select');
 +
 +  const clearIcon = selectContainer?.querySelector(
 +    '.ant-select-clear [aria-label="close-circle"]',
 +  );
 +  expect(clearIcon).toBeInTheDocument();
 +  userEvent.click(clearIcon as Element);
 +
 +  await waitFor(() => {
 +    const selectionItem = document.querySelector(
 +      '.ant-select-selection-item[title="Test Filter 1"]',
 +    );
 +    expect(selectionItem).not.toBeInTheDocument();
 +  });
 +
 +  // After clearing, value selector should be disabled again 
(optionFilterValues reset)
 +  await waitFor(() => {
 +    expect(valueSelect.closest('.ant-select')).toHaveClass(
 +      'ant-select-disabled',
 +    );
 +  });
 +
 +  userEvent.click(filterDropdown);
 +  await waitFor(() => {
 +    const virtualList = document.querySelector('.rc-virtual-list');
 +    expect(
 +      within(virtualList as HTMLElement).getByText('Test Filter 1'),
 +    ).toBeInTheDocument();
 +  });
 +});
 +
++const setupAnchorMocks = (
++  nativeFilters: Record<string, unknown>,
++  anchor = 'TAB-abc',
++  tabsOverride?: {
++    all_tabs: Record<string, string>;
++    tab_tree: { title: string; value: string }[];
++  },
++) => {
++  const payloadWithAnchor = {
++    ...generateMockPayload(true),
++    extra: { dashboard: { anchor } },
++  };
++
++  const defaultTabs = {
++    all_tabs: { [anchor]: `Tab ${anchor}` },
++    tab_tree: [{ title: `Tab ${anchor}`, value: anchor }],
++  };
++  const tabs = tabsOverride ?? defaultTabs;
++
++  // Clear call history so waitFor assertions don't match calls from prior 
tests.
++  fetchMock.callHistory.clear();
++
++  // Only replace the named routes that need anchor-specific overrides;
++  // unnamed related-endpoint routes (owners, database, etc.) stay intact.
++  fetchMock.removeRoute(FETCH_DASHBOARD_ENDPOINT);
++  fetchMock.removeRoute(FETCH_CHART_ENDPOINT);
++  fetchMock.removeRoute(tabsEndpoint);
++
++  fetchMock.get(
++    FETCH_DASHBOARD_ENDPOINT,
++    { result: payloadWithAnchor },
++    { name: FETCH_DASHBOARD_ENDPOINT },
++  );
++  fetchMock.get(
++    FETCH_CHART_ENDPOINT,
++    { result: generateMockPayload(false) },
++    { name: FETCH_CHART_ENDPOINT },
++  );
++  fetchMock.get(
++    tabsEndpoint,
++    {
++      result: {
++        ...tabs,
++        native_filters: nativeFilters,
++      },
++    },
++    { name: tabsEndpoint },
++  );
++};
++
++const restoreAnchorMocks = () => {
++  fetchMock.removeRoute(FETCH_DASHBOARD_ENDPOINT);
++  fetchMock.get(
++    FETCH_DASHBOARD_ENDPOINT,
++    { result: generateMockPayload(true) },
++    { name: FETCH_DASHBOARD_ENDPOINT },
++  );
++  fetchMock.removeRoute(FETCH_CHART_ENDPOINT);
++  fetchMock.get(
++    FETCH_CHART_ENDPOINT,
++    { result: generateMockPayload(false) },
++    { name: FETCH_CHART_ENDPOINT },
++  );
++  fetchMock.removeRoute(tabsEndpoint);
++  fetchMock.get(
++    tabsEndpoint,
++    { result: { all_tabs: {}, tab_tree: [] } },
++    { name: tabsEndpoint },
++  );
++};
++
++test('no error toast when anchor tab has no scoped native filters', async () 
=> {
++  setupAnchorMocks({
++    all: [
++      {
++        id: 'NATIVE_FILTER-1',
++        name: 'Filter 1',
++        filterType: 'filter_select',
++        targets: [{ column: { name: 'col' } }],
++        adhoc_filters: [],
++      },
++    ],
++  });
++
++  const store = createStore({}, reducerIndex);
++
++  try {
++    render(<AlertReportModal {...generateMockedProps(true, true)} />, {
++      store,
++    });
++
++    userEvent.click(screen.getByTestId('contents-panel'));
+     await screen.findByText(/test dashboard/i);
+ 
+     await waitFor(() => {
+       expect(
+         fetchMock.callHistory
+           .calls()
+           .some(c => c.url.includes('/dashboard/1/tabs')),
+       ).toBe(true);
+     });
+ 
+     const toasts = (store.getState() as Record<string, unknown>)
+       .messageToasts as { text: string }[];
+     expect(
+       toasts.some(
+         (toast: { text: string }) =>
+           toast.text === 'There was an error retrieving dashboard tabs.',
+       ),
+     ).toBe(false);
+   } finally {
+     restoreAnchorMocks();
+   }
+ });
+ 
+ test('no error toast when anchor tab set and dashboard has zero native 
filters', async () => {
+   setupAnchorMocks({});
+ 
+   const store = createStore({}, reducerIndex);
+ 
+   try {
+     render(<AlertReportModal {...generateMockedProps(true, true)} />, {
+       store,
+     });
+ 
+     userEvent.click(screen.getByTestId('contents-panel'));
+     await screen.findByText(/test dashboard/i);
+ 
+     await waitFor(() => {
+       expect(
+         fetchMock.callHistory
+           .calls()
+           .some(c => c.url.includes('/dashboard/1/tabs')),
+       ).toBe(true);
+     });
+ 
+     const toasts = (store.getState() as Record<string, unknown>)
+       .messageToasts as { text: string }[];
+     expect(
+       toasts.some(
+         (toast: { text: string }) =>
+           toast.text === 'There was an error retrieving dashboard tabs.',
+       ),
+     ).toBe(false);
+   } finally {
+     restoreAnchorMocks();
+   }
+ });
+ 
+ test('stale JSON array anchor is cleared without crash or toast', async () => 
{
+   const staleAnchor = JSON.stringify(['TAB-abc', 'TAB-missing']);
+   setupAnchorMocks(
+     {
+       all: [
+         {
+           id: 'NATIVE_FILTER-1',
+           name: 'Filter 1',
+           filterType: 'filter_select',
+           targets: [{ column: { name: 'col' } }],
+           adhoc_filters: [],
+         },
+       ],
+     },
+     staleAnchor,
+     {
+       all_tabs: { 'TAB-abc': 'Tab ABC' },
+       tab_tree: [{ title: 'Tab ABC', value: 'TAB-abc' }],
+     },
+   );
+ 
+   const store = createStore({}, reducerIndex);
+ 
+   try {
+     render(<AlertReportModal {...generateMockedProps(true, true)} />, {
+       store,
+     });
+ 
+     userEvent.click(screen.getByTestId('contents-panel'));
+     await screen.findByText(/test dashboard/i);
+ 
+     // Wait for the tabs useEffect to process the stale anchor
+     await waitFor(() => {
+       expect(
+         fetchMock.callHistory
+           .calls()
+           .some(c => c.url.includes('/dashboard/1/tabs')),
+       ).toBe(true);
+     });
+ 
+     // No error toast dispatched (the .then() handler ran without crashing)
+     const toasts = (store.getState() as Record<string, unknown>)
+       .messageToasts as { text: string }[];
+     expect(
+       toasts.some(
+         (toast: { text: string }) =>
+           toast.text === 'There was an error retrieving dashboard tabs.',
+       ),
+     ).toBe(false);
+ 
+     // Verify anchor was cleared at the payload level: trigger save and
+     // inspect the PUT body to confirm extra.dashboard.anchor is undefined
+     const updateEndpoint = 'glob:*/api/v1/report/1';
+     fetchMock.put(
+       updateEndpoint,
+       { id: 1, result: {} },
+       { name: 'put-report-1' },
+     );
+ 
+     const saveButton = screen.getByRole('button', { name: /save/i });
+     expect(saveButton).not.toBeDisabled();
+     userEvent.click(saveButton);
+ 
+     await waitFor(() => {
+       const putCalls = fetchMock.callHistory
+         .calls()
+         .filter(
+           c => c.url.includes('/api/v1/report/') && c.options?.method === 
'put',
+         );
+       expect(putCalls).toHaveLength(1);
+     });
+ 
+     const putCall = fetchMock.callHistory
+       .calls()
+       .find(
+         c => c.url.includes('/api/v1/report/') && c.options?.method === 'put',
+       );
+     const body = JSON.parse(putCall!.options?.body as string);
+     expect(body.extra.dashboard.anchor).toBeUndefined();
+   } finally {
+     fetchMock.removeRoute('put-report-1');
+     restoreAnchorMocks();
+   }
+ });
+ 
+ test('tabs API failure shows danger toast via Redux store', async () => {
+   fetchMock.removeRoute(tabsEndpoint);
+   fetchMock.get(tabsEndpoint, 500, { name: tabsEndpoint });
+ 
+   const store = createStore({}, reducerIndex);
+ 
+   try {
+     render(<AlertReportModal {...generateMockedProps(true, true)} />, {
+       store,
+     });
+ 
+     userEvent.click(screen.getByTestId('contents-panel'));
+ 
+     await waitFor(() => {
+       const toasts = (store.getState() as Record<string, unknown>)
+         .messageToasts as { text: string }[];
+       expect(
+         toasts.some(
+           (toast: { text: string }) =>
+             toast.text === 'There was an error retrieving dashboard tabs.',
+         ),
+       ).toBe(true);
+     });
+   } finally {
+     fetchMock.removeRoute(tabsEndpoint);
+     fetchMock.get(
+       tabsEndpoint,
+       { result: { all_tabs: {}, tab_tree: [] } },
+       { name: tabsEndpoint },
+     );
+   }
+ });
+ 
+ test('null all_tabs does not crash or show error toast', async () => {
+   setupAnchorMocks({
+     all: [
+       {
+         id: 'NATIVE_FILTER-1',
+         name: 'Filter 1',
+         filterType: 'filter_select',
+         targets: [{ column: { name: 'col' } }],
+         adhoc_filters: [],
+       },
+     ],
+   });
+ 
+   // Override tabs endpoint with null all_tabs
+   fetchMock.removeRoute(tabsEndpoint);
+   fetchMock.get(
+     tabsEndpoint,
+     {
+       result: {
+         all_tabs: null,
+         tab_tree: [{ title: 'Tab ABC', value: 'TAB-abc' }],
+         native_filters: {
+           all: [
+             {
+               id: 'NATIVE_FILTER-1',
+               name: 'Filter 1',
+               filterType: 'filter_select',
+               targets: [{ column: { name: 'col' } }],
+               adhoc_filters: [],
+             },
+           ],
+         },
+       },
+     },
+     { name: tabsEndpoint },
+   );
+ 
+   const store = createStore({}, reducerIndex);
+ 
+   try {
+     render(<AlertReportModal {...generateMockedProps(true, true)} />, {
+       store,
+     });
+ 
+     userEvent.click(screen.getByTestId('contents-panel'));
+     await screen.findByText(/test dashboard/i);
+ 
+     // Wait for tabs useEffect to complete
+     await waitFor(() => {
+       expect(
+         fetchMock.callHistory
+           .calls()
+           .some(c => c.url.includes('/dashboard/1/tabs')),
+       ).toBe(true);
+     });
+ 
+     // No error toast dispatched
+     const toasts = (store.getState() as Record<string, unknown>)
+       .messageToasts as { text: string }[];
+     expect(
+       toasts.some(
+         (toast: { text: string }) =>
+           toast.text === 'There was an error retrieving dashboard tabs.',
+       ),
+     ).toBe(false);
+ 
+     // Component remains interactive
+     expect(
+       screen.getByRole('combobox', { name: /select filter/i }),
+     ).toBeInTheDocument();
+   } finally {
+     restoreAnchorMocks();
+   }
+ });
+ 
+ test('missing native_filters in tabs response does not crash or show error 
toast', async () => {
+   setupAnchorMocks({});
+ 
+   // Override tabs endpoint with no native_filters key
+   fetchMock.removeRoute(tabsEndpoint);
+   fetchMock.get(
+     tabsEndpoint,
+     {
+       result: {
+         all_tabs: { 'TAB-abc': 'Tab ABC' },
+         tab_tree: [{ title: 'Tab ABC', value: 'TAB-abc' }],
+       },
+     },
+     { name: tabsEndpoint },
+   );
+ 
+   const store = createStore({}, reducerIndex);
+ 
+   try {
+     render(<AlertReportModal {...generateMockedProps(true, true)} />, {
+       store,
+     });
+ 
+     userEvent.click(screen.getByTestId('contents-panel'));
+     await screen.findByText(/test dashboard/i);
+ 
+     // Wait for tabs useEffect to complete
+     await waitFor(() => {
+       expect(
+         fetchMock.callHistory
+           .calls()
+           .some(c => c.url.includes('/dashboard/1/tabs')),
+       ).toBe(true);
+     });
+ 
+     // No error toast dispatched
+     const toasts = (store.getState() as Record<string, unknown>)
+       .messageToasts as { text: string }[];
+     expect(
+       toasts.some(
+         (toast: { text: string }) =>
+           toast.text === 'There was an error retrieving dashboard tabs.',
+       ),
+     ).toBe(false);
+   } finally {
+     restoreAnchorMocks();
+   }
+ });
+ 
+ test('anchor tab with scoped filters loads filter options correctly', async 
() => {
+   // Use JSON-parseable non-array anchor to exercise the scoped filter
+   // code path at line 1108 (JSON.parse('42') → 42, not an array)
+   setupAnchorMocks(
+     {
+       all: [
+         {
+           id: 'NATIVE_FILTER-1',
+           name: 'Global Filter',
+           filterType: 'filter_select',
+           targets: [{ column: { name: 'col' } }],
+           adhoc_filters: [],
+         },
+       ],
+       '42': [
+         {
+           id: 'NATIVE_FILTER-2',
+           name: 'Tab Scoped Filter',
+           filterType: 'filter_select',
+           targets: [{ column: { name: 'col2' } }],
+           adhoc_filters: [],
+         },
+       ],
+     },
+     '42',
+   );
+ 
+   const store = createStore({}, reducerIndex);
+ 
+   try {
+     render(<AlertReportModal {...generateMockedProps(true, true)} />, {
+       store,
+     });
+ 
+     userEvent.click(screen.getByTestId('contents-panel'));
+     await screen.findByText(/test dashboard/i);
+ 
+     const filterDropdown = screen.getByRole('combobox', {
+       name: /select filter/i,
+     });
+     userEvent.click(filterDropdown);
+ 
+     const filterOption = await screen.findByRole('option', {
+       name: /Tab Scoped Filter/,
+     });
+     expect(filterOption).toBeInTheDocument();
+ 
+     const toasts = (store.getState() as Record<string, unknown>)
+       .messageToasts as { text: string }[];
+     expect(
+       toasts.some(
+         (toast: { text: string }) =>
+           toast.text === 'There was an error retrieving dashboard tabs.',
+       ),
+     ).toBe(false);
+   } finally {
+     restoreAnchorMocks();
+   }
+ });
+ 
  test('edit mode shows friendly filter names instead of raw IDs', async () => {
    const props = generateMockedProps(true, true);
    const editProps = {

Reply via email to