From d9a3c3e1dd23eca113a799bb6a2fa4abddd4a76b Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Fri, 19 Jan 2024 09:54:53 -0300 Subject: [PATCH 01/39] refactor: Removes the Filter Box code (#26328) Co-authored-by: John Bodley --- UPDATING.md | 1 + .../miscellaneous/native-filter-migration.mdx | 94 ---- .../e2e/dashboard/_skip.filter.test.ts | 82 --- .../cypress/e2e/dashboard/tabs.test.ts | 4 +- .../cypress/e2e/explore/filter_box.test.js | 38 -- .../cypress/e2e/explore/link.test.ts | 4 +- .../cypress/support/directories.ts | 2 +- superset-frontend/package-lock.json | 54 +- superset-frontend/package.json | 4 +- .../superset-ui-chart-controls/src/types.ts | 1 - .../src/chart/models/ChartProps.ts | 4 - .../test/query/extractTimegrain.test.ts | 2 +- .../AceEditorWrapper.test.tsx | 3 - .../EstimateQueryCostButton.test.tsx | 3 - .../QueryLimitSelect.test.tsx | 3 - .../RunQueryActionButton.test.tsx | 3 - .../SqlEditorTabHeader.test.tsx | 3 - .../TemplateParamsEditor.test.tsx | 3 - .../AsyncSelect/AsyncSelect.test.jsx | 150 ------ .../src/components/AsyncSelect/index.jsx | 104 ---- .../DeprecatedSelect.stories.tsx | 143 ------ .../DeprecatedSelect/DeprecatedSelect.tsx | 324 ------------ .../DeprecatedSelect/NativeSelect.tsx | 61 --- .../DeprecatedSelect/OnPasteSelect.jsx | 104 ---- .../DeprecatedSelect/OnPasteSelect.test.jsx | 216 -------- .../WindowedSelect/WindowedMenuList.tsx | 158 ------ .../DeprecatedSelect/WindowedSelect/index.tsx | 29 -- .../WindowedSelect/windowed.tsx | 84 --- .../src/components/DeprecatedSelect/index.ts | 23 - .../components/DeprecatedSelect/styles.tsx | 406 --------------- .../src/components/DeprecatedSelect/utils.ts | 57 --- .../src/components/ListView/utils.ts | 19 - .../src/components/Select/AsyncSelect.tsx | 2 - .../src/components/Select/Select.tsx | 2 - .../src/dashboard/actions/dashboardFilters.js | 20 - .../src/dashboard/actions/dashboardState.js | 19 +- .../dashboard/actions/dashboardState.test.js | 12 - .../src/dashboard/actions/hydrate.js | 69 --- .../src/dashboard/actions/sliceEntities.ts | 16 +- .../DashboardBuilder.test.tsx | 6 - .../components/FilterBoxMigrationModal.tsx | 95 ---- .../SliceHeaderControls.test.tsx | 6 - .../components/SliceHeaderControls/index.tsx | 5 +- .../filterscope/FilterScopeSelector.jsx | 11 +- .../components/gridComponents/Chart.jsx | 19 +- .../FilterScope/utils.test.ts | 57 --- .../FiltersConfigForm/FilterScope/utils.ts | 7 +- .../components/nativeFilters/selectors.ts | 4 +- .../src/dashboard/containers/Dashboard.ts | 3 +- .../dashboard/reducers/dashboardFilters.js | 44 +- .../reducers/dashboardFilters.test.js | 45 +- .../dashboard/util/activeDashboardFilters.js | 22 +- .../dashboard/util/getFilterScopeNodesTree.js | 7 +- .../util/getFilterValuesByFilterId.js | 38 -- .../dashboard/util/getRevertedFilterScope.ts | 19 +- .../getSelectedChartIdForFilterScopeTree.js | 2 - .../util/logging/childChartsDidLoad.js | 9 +- .../useFilterFocusHighlightStyles.test.tsx | 63 --- .../util/useFilterFocusHighlightStyles.ts | 4 +- .../components/ExploreChartPanel/index.jsx | 46 +- .../src/explore/components/SaveModal.tsx | 55 +- .../FilterBoxItemControl.test.jsx | 108 ---- .../FilterBoxItemControl.test.tsx | 61 --- .../controls/FilterBoxItemControl/index.jsx | 295 ----------- .../VizTypeControl/VizTypeGallery.tsx | 1 - .../controls/VizTypeControl/index.tsx | 9 - .../src/explore/components/controls/index.js | 2 - .../src/pages/ChartCreation/index.tsx | 9 - .../src/utils/localStorageHelpers.ts | 2 - superset-frontend/src/utils/urlUtils.ts | 2 +- .../visualizations/FilterBox/FilterBox.jsx | 480 ------------------ .../FilterBox/FilterBox.test.jsx | 87 ---- .../FilterBox/FilterBoxChartPlugin.js | 52 -- .../visualizations/FilterBox/controlPanel.jsx | 103 ---- .../FilterBox/images/example1.jpg | Bin 10921 -> 0 bytes .../FilterBox/images/example2.jpg | Bin 16969 -> 0 bytes .../FilterBox/images/thumbnail.png | Bin 8550 -> 0 bytes .../FilterBox/images/thumbnailLarge.png | Bin 49653 -> 0 bytes .../FilterBox/transformProps.ts | 74 --- .../src/visualizations/FilterBox/types.ts | 29 -- .../src/visualizations/presets/MainPreset.js | 2 - superset-frontend/webpack.config.js | 1 - superset/cli/native_filters.py | 398 --------------- .../commands/chart/importers/v1/__init__.py | 4 + superset/commands/dashboard/importers/v0.py | 26 +- .../dashboard/importers/v1/__init__.py | 16 +- superset/commands/importers/v1/assets.py | 11 + superset/migrations/shared/native_filters.py | 338 ++++++++++++ ..._migrate_filter_boxes_to_native_filters.py | 85 ++++ superset/utils/core.py | 2 +- .../dashboard_filter_scopes_converter.py | 251 --------- superset/viz.py | 79 --- tests/integration_tests/commands_test.py | 7 +- .../dashboards/commands_tests.py | 7 +- .../integration_tests/import_export_tests.py | 22 +- tests/integration_tests/utils_tests.py | 24 +- tests/integration_tests/viz_tests.py | 67 --- 97 files changed, 577 insertions(+), 4970 deletions(-) delete mode 100644 docs/docs/miscellaneous/native-filter-migration.mdx delete mode 100644 superset-frontend/cypress-base/cypress/e2e/dashboard/_skip.filter.test.ts delete mode 100644 superset-frontend/cypress-base/cypress/e2e/explore/filter_box.test.js delete mode 100644 superset-frontend/src/components/AsyncSelect/AsyncSelect.test.jsx delete mode 100644 superset-frontend/src/components/AsyncSelect/index.jsx delete mode 100644 superset-frontend/src/components/DeprecatedSelect/DeprecatedSelect.stories.tsx delete mode 100644 superset-frontend/src/components/DeprecatedSelect/DeprecatedSelect.tsx delete mode 100644 superset-frontend/src/components/DeprecatedSelect/NativeSelect.tsx delete mode 100644 superset-frontend/src/components/DeprecatedSelect/OnPasteSelect.jsx delete mode 100644 superset-frontend/src/components/DeprecatedSelect/OnPasteSelect.test.jsx delete mode 100644 superset-frontend/src/components/DeprecatedSelect/WindowedSelect/WindowedMenuList.tsx delete mode 100644 superset-frontend/src/components/DeprecatedSelect/WindowedSelect/index.tsx delete mode 100644 superset-frontend/src/components/DeprecatedSelect/WindowedSelect/windowed.tsx delete mode 100644 superset-frontend/src/components/DeprecatedSelect/index.ts delete mode 100644 superset-frontend/src/components/DeprecatedSelect/styles.tsx delete mode 100644 superset-frontend/src/components/DeprecatedSelect/utils.ts delete mode 100644 superset-frontend/src/dashboard/components/FilterBoxMigrationModal.tsx delete mode 100644 superset-frontend/src/dashboard/util/getFilterValuesByFilterId.js delete mode 100644 superset-frontend/src/explore/components/controls/FilterBoxItemControl/FilterBoxItemControl.test.jsx delete mode 100644 superset-frontend/src/explore/components/controls/FilterBoxItemControl/FilterBoxItemControl.test.tsx delete mode 100644 superset-frontend/src/explore/components/controls/FilterBoxItemControl/index.jsx delete mode 100644 superset-frontend/src/visualizations/FilterBox/FilterBox.jsx delete mode 100644 superset-frontend/src/visualizations/FilterBox/FilterBox.test.jsx delete mode 100644 superset-frontend/src/visualizations/FilterBox/FilterBoxChartPlugin.js delete mode 100644 superset-frontend/src/visualizations/FilterBox/controlPanel.jsx delete mode 100644 superset-frontend/src/visualizations/FilterBox/images/example1.jpg delete mode 100644 superset-frontend/src/visualizations/FilterBox/images/example2.jpg delete mode 100644 superset-frontend/src/visualizations/FilterBox/images/thumbnail.png delete mode 100644 superset-frontend/src/visualizations/FilterBox/images/thumbnailLarge.png delete mode 100644 superset-frontend/src/visualizations/FilterBox/transformProps.ts delete mode 100644 superset-frontend/src/visualizations/FilterBox/types.ts delete mode 100644 superset/cli/native_filters.py create mode 100644 superset/migrations/shared/native_filters.py create mode 100644 superset/migrations/versions/2024-01-18_15-20_214f580d09c9_migrate_filter_boxes_to_native_filters.py diff --git a/UPDATING.md b/UPDATING.md index 84893e9080d..cf4f846715a 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -28,6 +28,7 @@ assists people when migrating to a new version. ### Breaking Changes +- [26328](https://github.com/apache/superset/issues/26328): Removes the deprecated Filter Box code and it's associated dependencies `react-select` and `array-move`. It also removes the `DeprecatedSelect` and `AsyncSelect` components that were exclusively used by filter boxes. Existing filter boxes will be automatically migrated to native filters. - [26330](https://github.com/apache/superset/issues/26330): Removes the deprecated `DASHBOARD_FILTERS_EXPERIMENTAL` feature flag. The previous value of the feature flag was `False` and now the feature is permanently removed. - [26344](https://github.com/apache/superset/issues/26344): Removes the deprecated `ENABLE_EXPLORE_JSON_CSRF_PROTECTION` feature flag. The previous value of the feature flag was `False` and now the feature is permanently removed. - [26345](https://github.com/apache/superset/issues/26345): Removes the deprecated `ENABLE_TEMPLATE_REMOVE_FILTERS` feature flag. The previous value of the feature flag was `True` and now the feature is permanently enabled. diff --git a/docs/docs/miscellaneous/native-filter-migration.mdx b/docs/docs/miscellaneous/native-filter-migration.mdx deleted file mode 100644 index d8ffa8b3291..00000000000 --- a/docs/docs/miscellaneous/native-filter-migration.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Migrating from Legacy to Native Filters -sidebar_position: 5 -version: 1 ---- - -## - -The `superset native-filters` CLI command group—somewhat akin to an Alembic migration— -comprises of a number of sub-commands which allows administrators to upgrade/downgrade -existing dashboards which use the legacy filter-box charts—in combination with the -filter scopes/filter mapping—to use the native filter dashboard component. - -Even though both legacy and native filters can coexist the overall user experience (UX) -is substandard as the already convoluted filter space becomes overly complex. After -enabling the `DASHBOARD_NATIVE_FILTERS` it is strongly advised to run the migration ASAP to -ensure users are not exposed to the hybrid state. - -### Upgrading - -The - -``` -superset native-filters upgrade -``` - -command—which provides the option to target either specific dashboard(s) or all -dashboards—migrates the legacy filters to native filters. - -Specifically, the command performs the following: - -- Replaces every filter-box chart within the dashboard with a markdown element which -provides a link to the deprecated chart. This preserves the layout whilst simultaneously -providing context to help owners review/verify said change. -- Migrates the filter scopes/filter mappings to the native filter configuration. - -#### Quality Control - -Dashboard owners should: - -- Verify that the filter behavior is correct. -- Consolidate any conflicting/redundant filters—this previously may not have been -obvious given the embedded nature of the legacy filters and/or the non-optimal UX of the -legacy filter mapping (scopes and immunity). -- Rename the filters—which may not be uniquely named—to provide the necessary context -which previously was likely provided by both the location of the filter-box and the -corresponding filter-box title. - -Dashboard owners may: - -- Remove† the markdown elements from their dashboards and adjust the layout accordingly. - -† Note removing the markdown elements—which contain metadata relating to the replaced -chart—prevents the dashboard from being fully restored and thus this operation should -only be performed if it is evident that a downgrade is not necessary. - -### Downgrading - -Similarly the - -``` -superset native-filters downgrade -``` - -command reverses said migration, i.e., restores the dashboard to the previous state. - - -### Cleanup - -The ability to downgrade/reverse the migration requires temporary storage of the -dashboard metadata—relating to both positional composition and filter configuration. - -Once the upgrade has been verified it is recommended to run the - -``` -superset native-filters cleanup -``` - -command—which provides the option to target either specific dashboard(s) or all -dashboards. Note this operation is irreversible. - -Specifically, the command performs the following: - -- Removes the temporary dashboard metadata. -- Deletes the filter-box charts associated with the dashboard†. - -† Note the markdown elements will still remain however the link to the referenced filter-box -chart will no longer be valid. - -#### Quality Control - -Dashboard owners should: - -- Remove the markdown elements from their dashboards and adjust the layout accordingly. diff --git a/superset-frontend/cypress-base/cypress/e2e/dashboard/_skip.filter.test.ts b/superset-frontend/cypress-base/cypress/e2e/dashboard/_skip.filter.test.ts deleted file mode 100644 index 6ae5d1e5d6f..00000000000 --- a/superset-frontend/cypress-base/cypress/e2e/dashboard/_skip.filter.test.ts +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { - isLegacyResponse, - parsePostForm, - getChartAliasesBySpec, - waitForChartLoad, -} from 'cypress/utils'; -import { WORLD_HEALTH_DASHBOARD } from 'cypress/utils/urls'; -import { WORLD_HEALTH_CHARTS } from './utils'; - -describe.skip('Dashboard filter', () => { - before(() => { - cy.visit(WORLD_HEALTH_DASHBOARD); - }); - - it('should apply filter', () => { - WORLD_HEALTH_CHARTS.forEach(waitForChartLoad); - getChartAliasesBySpec( - WORLD_HEALTH_CHARTS.filter(({ viz }) => viz !== 'filter_box'), - ).then(nonFilterChartAliases => { - cy.get('.Select__placeholder:first').click(); - - // should show the filter indicator - cy.get('span[aria-label="filter"]:visible').should(nodes => { - expect(nodes.length).to.least(9); - }); - - cy.get('.Select__control:first input[type=text]').type('So', { - force: true, - delay: 100, - }); - - cy.get('.Select__menu').first().contains('South Asia').click(); - - // should still have all filter indicators - cy.get('span[aria-label="filter"]:visible').should(nodes => { - expect(nodes.length).to.least(9); - }); - - cy.get('.filter_box button').click({ force: true }); - cy.wait(nonFilterChartAliases).then(requests => { - requests.forEach(({ response, request }) => { - const responseBody = response?.body; - let requestFilter; - if (isLegacyResponse(responseBody)) { - const requestFormData = parsePostForm(request.body); - const requestParams = JSON.parse( - requestFormData.form_data as string, - ); - requestFilter = requestParams.extra_filters[0]; - } else { - requestFilter = request.body.queries[0].filters[0]; - } - expect(requestFilter).deep.eq({ - col: 'region', - op: 'IN', - val: ['South Asia'], - }); - }); - }); - }); - - // TODO add test with South Asia{enter} type action to select filter - }); -}); diff --git a/superset-frontend/cypress-base/cypress/e2e/dashboard/tabs.test.ts b/superset-frontend/cypress-base/cypress/e2e/dashboard/tabs.test.ts index ba442e600ae..208eb357534 100644 --- a/superset-frontend/cypress-base/cypress/e2e/dashboard/tabs.test.ts +++ b/superset-frontend/cypress-base/cypress/e2e/dashboard/tabs.test.ts @@ -101,7 +101,7 @@ describe('Dashboard tabs', () => { cy.get('.Select__control').first().should('be.visible').click(); cy.get('.Select__control input[type=text]').first().focus().type('South'); cy.get('.Select__option').contains('South Asia').click(); - cy.get('.filter_box button:not(:disabled)').contains('Apply').click(); + cy.get('.filter button:not(:disabled)').contains('Apply').click(); // send new query from same tab cy.wait(treemapAlias).then(({ request }) => { @@ -149,7 +149,7 @@ describe('Dashboard tabs', () => { cy.get('.ant-tabs-tab').contains('row tab 1').click(); cy.get('.Select__clear-indicator').click(); - cy.get('.filter_box button:not(:disabled)').contains('Apply').click(); + cy.get('.filter button:not(:disabled)').contains('Apply').click(); // trigger 1 new query waitForChartLoad(TREEMAP); diff --git a/superset-frontend/cypress-base/cypress/e2e/explore/filter_box.test.js b/superset-frontend/cypress-base/cypress/e2e/explore/filter_box.test.js deleted file mode 100644 index a4ca5ddcf2e..00000000000 --- a/superset-frontend/cypress-base/cypress/e2e/explore/filter_box.test.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { FORM_DATA_DEFAULTS } from './visualizations/shared.helper'; - -describe('Edit FilterBox Chart', () => { - const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'filter_box' }; - - function verify(formData) { - cy.visitChartByParams(formData); - cy.verifySliceSuccess({ waitAlias: '@getJson' }); - } - - beforeEach(() => { - cy.intercept('POST', '/superset/explore_json/**').as('getJson'); - }); - - it('should work with default date filter', () => { - verify(VIZ_DEFAULTS); - // Filter box should default to having a date filter with no filter selected - cy.get('div.filter_box').contains('No filter'); - }); -}); diff --git a/superset-frontend/cypress-base/cypress/e2e/explore/link.test.ts b/superset-frontend/cypress-base/cypress/e2e/explore/link.test.ts index 1e13c7d7ed3..3c7decd512c 100644 --- a/superset-frontend/cypress-base/cypress/e2e/explore/link.test.ts +++ b/superset-frontend/cypress-base/cypress/e2e/explore/link.test.ts @@ -78,7 +78,9 @@ describe('Test explore links', () => { cy.url().then(() => { cy.get('[data-test="query-save-button"]').click(); cy.get('[data-test="saveas-radio"]').check(); - cy.get('[data-test="new-chart-name"]').type(newChartName); + cy.get('[data-test="new-chart-name"]').type(newChartName, { + force: true, + }); cy.get('[data-test="btn-modal-save"]').click(); cy.verifySliceSuccess({ waitAlias: '@tableChartData' }); cy.visitChartByName(newChartName); diff --git a/superset-frontend/cypress-base/cypress/support/directories.ts b/superset-frontend/cypress-base/cypress/support/directories.ts index b0eb024d2f4..8dcf739d14a 100644 --- a/superset-frontend/cypress-base/cypress/support/directories.ts +++ b/superset-frontend/cypress-base/cypress/support/directories.ts @@ -657,7 +657,7 @@ export const dashboardView = { treeMapChartModal: { selectItem: '.Select_control', selectItemInput: '.Select__control input[type=text]', - applyButton: '.filter_box button:not(:disabled)', + applyButton: '.filter button:not(:disabled)', clearItemIcon: '.Select__clear-indicator', }, sliceThreeDots: '[aria-label="More Options"]', diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 6e9867ecb0a..7b8073e9860 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -59,7 +59,6 @@ "ace-builds": "^1.4.14", "ansi-regex": "^4.1.1", "antd": "4.10.3", - "array-move": "^2.2.1", "babel-plugin-typescript-to-proptypes": "^2.0.0", "bootstrap": "^3.4.1", "bootstrap-slider": "^10.0.0", @@ -124,7 +123,6 @@ "react-reverse-portal": "^2.1.1", "react-router-dom": "^5.3.4", "react-search-input": "^0.11.3", - "react-select": "^3.2.0", "react-sortable-hoc": "^2.0.0", "react-split": "^2.0.9", "react-syntax-highlighter": "^15.4.5", @@ -201,8 +199,8 @@ "@types/react-loadable": "^5.5.6", "@types/react-redux": "^7.1.10", "@types/react-router-dom": "^5.3.3", - "@types/react-select": "^3.0.19", "@types/react-table": "^7.0.19", + "@types/react-transition-group": "^4.4.10", "@types/react-ultimate-pagination": "^1.2.0", "@types/react-window": "^1.8.5", "@types/redux-localstorage": "^1.0.8", @@ -19787,17 +19785,6 @@ "@types/react-router": "*" } }, - "node_modules/@types/react-select": { - "version": "3.0.19", - "resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-3.0.19.tgz", - "integrity": "sha512-d+6qtfFXZeIOAABlVL1e50RZn8ctOABE4tFDxM6KW4lKuXgTTgLVrSik5AX9XjBjV7N80FtS6GTN/WeoXL9Jww==", - "dev": true, - "dependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "@types/react-transition-group": "*" - } - }, "node_modules/@types/react-syntax-highlighter": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.5.tgz", @@ -19823,9 +19810,9 @@ } }, "node_modules/@types/react-transition-group": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz", - "integrity": "sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w==", + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", "dev": true, "dependencies": { "@types/react": "*" @@ -22895,17 +22882,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-move": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/array-move/-/array-move-2.2.1.tgz", - "integrity": "sha512-qQpEHBnVT6HAFgEVUwRdHVd8TYJThrZIT5wSXpEUTPwBaYhPLclw12mEpyUvRWVdl1VwPOqnIy6LqTFN3cSeUQ==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/array-tree-filter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", @@ -79812,17 +79788,6 @@ "@types/react-router": "*" } }, - "@types/react-select": { - "version": "3.0.19", - "resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-3.0.19.tgz", - "integrity": "sha512-d+6qtfFXZeIOAABlVL1e50RZn8ctOABE4tFDxM6KW4lKuXgTTgLVrSik5AX9XjBjV7N80FtS6GTN/WeoXL9Jww==", - "dev": true, - "requires": { - "@types/react": "*", - "@types/react-dom": "*", - "@types/react-transition-group": "*" - } - }, "@types/react-syntax-highlighter": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.5.tgz", @@ -79848,9 +79813,9 @@ } }, "@types/react-transition-group": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz", - "integrity": "sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w==", + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", "dev": true, "requires": { "@types/react": "*" @@ -82292,11 +82257,6 @@ "is-string": "^1.0.7" } }, - "array-move": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/array-move/-/array-move-2.2.1.tgz", - "integrity": "sha512-qQpEHBnVT6HAFgEVUwRdHVd8TYJThrZIT5wSXpEUTPwBaYhPLclw12mEpyUvRWVdl1VwPOqnIy6LqTFN3cSeUQ==" - }, "array-tree-filter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index cc243754fc5..8abd9dd9554 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -125,7 +125,6 @@ "ace-builds": "^1.4.14", "ansi-regex": "^4.1.1", "antd": "4.10.3", - "array-move": "^2.2.1", "babel-plugin-typescript-to-proptypes": "^2.0.0", "bootstrap": "^3.4.1", "bootstrap-slider": "^10.0.0", @@ -190,7 +189,6 @@ "react-reverse-portal": "^2.1.1", "react-router-dom": "^5.3.4", "react-search-input": "^0.11.3", - "react-select": "^3.2.0", "react-sortable-hoc": "^2.0.0", "react-split": "^2.0.9", "react-syntax-highlighter": "^15.4.5", @@ -267,8 +265,8 @@ "@types/react-loadable": "^5.5.6", "@types/react-redux": "^7.1.10", "@types/react-router-dom": "^5.3.3", - "@types/react-select": "^3.0.19", "@types/react-table": "^7.0.19", + "@types/react-transition-group": "^4.4.10", "@types/react-ultimate-pagination": "^1.2.0", "@types/react-window": "^1.8.5", "@types/redux-localstorage": "^1.0.8", diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/types.ts b/superset-frontend/packages/superset-ui-chart-controls/src/types.ts index 9314f8d33f3..8aa475a7f9b 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/types.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/types.ts @@ -280,7 +280,6 @@ export type SelectControlType = | 'AdhocFilterControl' | 'FilterBoxItemControl'; -// via react-select/src/filters export interface FilterOption { label: string; value: string; diff --git a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts index 815a5df2f4e..829440133a3 100644 --- a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts +++ b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts @@ -76,10 +76,6 @@ export interface ChartPropsConfig { annotationData?: AnnotationData; /** Datasource metadata */ datasource?: SnakeCaseDatasource; - /** - * Formerly called "filters", which was misleading because it is actually - * initial values of the filter_box and table vis - */ initialValues?: DataRecordFilters; /** Main configuration of the chart */ formData?: RawFormData; diff --git a/superset-frontend/packages/superset-ui-core/test/query/extractTimegrain.test.ts b/superset-frontend/packages/superset-ui-core/test/query/extractTimegrain.test.ts index d063e11a8f7..384b09cabaf 100644 --- a/superset-frontend/packages/superset-ui-core/test/query/extractTimegrain.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/query/extractTimegrain.test.ts @@ -32,7 +32,7 @@ describe('extractTimegrain', () => { ).toEqual('P1D'); }); - it('should extract filter box time grain from form data', () => { + it('should extract filter time grain from form data', () => { expect( extractTimegrain({ ...baseFormData, diff --git a/superset-frontend/src/SqlLab/components/AceEditorWrapper/AceEditorWrapper.test.tsx b/superset-frontend/src/SqlLab/components/AceEditorWrapper/AceEditorWrapper.test.tsx index c69b92346db..27950a98b17 100644 --- a/superset-frontend/src/SqlLab/components/AceEditorWrapper/AceEditorWrapper.test.tsx +++ b/superset-frontend/src/SqlLab/components/AceEditorWrapper/AceEditorWrapper.test.tsx @@ -29,9 +29,6 @@ import { AsyncAceEditorProps } from 'src/components/AsyncAceEditor'; const middlewares = [thunk]; const mockStore = configureStore(middlewares); -jest.mock('src/components/DeprecatedSelect', () => () => ( -
-)); jest.mock('src/components/Select/Select', () => () => (
)); diff --git a/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/EstimateQueryCostButton.test.tsx b/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/EstimateQueryCostButton.test.tsx index 38dbbf65a05..7fe7680f17f 100644 --- a/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/EstimateQueryCostButton.test.tsx +++ b/superset-frontend/src/SqlLab/components/EstimateQueryCostButton/EstimateQueryCostButton.test.tsx @@ -34,9 +34,6 @@ import EstimateQueryCostButton, { const middlewares = [thunk]; const mockStore = configureStore(middlewares); -jest.mock('src/components/DeprecatedSelect', () => () => ( -
-)); jest.mock('src/components/Select/Select', () => () => (
)); diff --git a/superset-frontend/src/SqlLab/components/QueryLimitSelect/QueryLimitSelect.test.tsx b/superset-frontend/src/SqlLab/components/QueryLimitSelect/QueryLimitSelect.test.tsx index 68a014ba52a..69dcca42b5e 100644 --- a/superset-frontend/src/SqlLab/components/QueryLimitSelect/QueryLimitSelect.test.tsx +++ b/superset-frontend/src/SqlLab/components/QueryLimitSelect/QueryLimitSelect.test.tsx @@ -32,9 +32,6 @@ import QueryLimitSelect, { const middlewares = [thunk]; const mockStore = configureStore(middlewares); -jest.mock('src/components/DeprecatedSelect', () => () => ( -
-)); jest.mock('src/components/Select/Select', () => () => (
)); diff --git a/superset-frontend/src/SqlLab/components/RunQueryActionButton/RunQueryActionButton.test.tsx b/superset-frontend/src/SqlLab/components/RunQueryActionButton/RunQueryActionButton.test.tsx index 276f9b7d196..35494390882 100644 --- a/superset-frontend/src/SqlLab/components/RunQueryActionButton/RunQueryActionButton.test.tsx +++ b/superset-frontend/src/SqlLab/components/RunQueryActionButton/RunQueryActionButton.test.tsx @@ -30,9 +30,6 @@ import RunQueryActionButton, { const middlewares = [thunk]; const mockStore = configureStore(middlewares); -jest.mock('src/components/DeprecatedSelect', () => () => ( -
-)); jest.mock('src/components/Select/Select', () => () => (
)); diff --git a/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/SqlEditorTabHeader.test.tsx b/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/SqlEditorTabHeader.test.tsx index 6c231401c70..986dabc8148 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/SqlEditorTabHeader.test.tsx +++ b/superset-frontend/src/SqlLab/components/SqlEditorTabHeader/SqlEditorTabHeader.test.tsx @@ -42,9 +42,6 @@ import { } from 'src/SqlLab/actions/sqlLab'; import SqlEditorTabHeader from 'src/SqlLab/components/SqlEditorTabHeader'; -jest.mock('src/components/DeprecatedSelect', () => () => ( -
-)); jest.mock('src/components/Select/Select', () => () => (
)); diff --git a/superset-frontend/src/SqlLab/components/TemplateParamsEditor/TemplateParamsEditor.test.tsx b/superset-frontend/src/SqlLab/components/TemplateParamsEditor/TemplateParamsEditor.test.tsx index fdf8fd3b53f..3270ef1f525 100644 --- a/superset-frontend/src/SqlLab/components/TemplateParamsEditor/TemplateParamsEditor.test.tsx +++ b/superset-frontend/src/SqlLab/components/TemplateParamsEditor/TemplateParamsEditor.test.tsx @@ -33,9 +33,6 @@ import TemplateParamsEditor, { TemplateParamsEditorProps, } from 'src/SqlLab/components/TemplateParamsEditor'; -jest.mock('src/components/DeprecatedSelect', () => () => ( -
-)); jest.mock('src/components/Select/Select', () => () => (
)); diff --git a/superset-frontend/src/components/AsyncSelect/AsyncSelect.test.jsx b/superset-frontend/src/components/AsyncSelect/AsyncSelect.test.jsx deleted file mode 100644 index f3bce127133..00000000000 --- a/superset-frontend/src/components/AsyncSelect/AsyncSelect.test.jsx +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React from 'react'; -import { shallow } from 'enzyme'; -import fetchMock from 'fetch-mock'; -import Select from 'src/components/DeprecatedSelect'; -import AsyncSelect from 'src/components/AsyncSelect'; - -describe('AsyncSelect', () => { - afterAll(fetchMock.reset); - afterEach(fetchMock.resetHistory); - - const dataEndpoint = '/chart/api/read'; - const dataGlob = 'glob:*/chart/api/read'; - fetchMock.get(dataGlob, []); - fetchMock.resetHistory(); - - const mockedProps = { - dataEndpoint, - onChange: () => {}, - placeholder: 'Select...', - mutator: () => [ - { value: 1, label: 'main' }, - { value: 2, label: 'another' }, - ], - valueRenderer: opt => opt.label, - }; - - it('is valid element', () => { - expect(React.isValidElement()).toBe(true); - }); - - it('has one select', () => { - const wrapper = shallow(); - expect(wrapper.find(Select)).toExist(); - }); - - it('calls onChange on select change', () => { - const onChangeSpy = jest.fn(); - const wrapper = shallow( - , - ); - - wrapper.find(Select).simulate('change', { value: 1 }); - expect(onChangeSpy.mock.calls).toHaveLength(1); - }); - - describe('auto select', () => { - it('should not call onChange if autoSelect=false', () => - new Promise(done => { - expect.assertions(2); - - const onChangeSpy = jest.fn(); - shallow(); - - setTimeout(() => { - expect(fetchMock.calls(dataGlob)).toHaveLength(1); - expect(onChangeSpy.mock.calls).toHaveLength(0); - done(); - }); - })); - - it('should auto select the first option if autoSelect=true', () => - new Promise(done => { - expect.assertions(3); - - const onChangeSpy = jest.fn(); - const wrapper = shallow( - , - ); - - setTimeout(() => { - expect(fetchMock.calls(dataGlob)).toHaveLength(1); - expect(onChangeSpy.mock.calls).toHaveLength(1); - expect(onChangeSpy).toBeCalledWith( - wrapper.instance().state.options[0], - ); - done(); - }); - })); - - it('should not auto select when value prop is set and autoSelect=true', () => - new Promise(done => { - expect.assertions(3); - - const onChangeSpy = jest.fn(); - const wrapper = shallow( - , - ); - - setTimeout(() => { - expect(fetchMock.calls(dataGlob)).toHaveLength(1); - expect(onChangeSpy.mock.calls).toHaveLength(0); - expect(wrapper.find(Select)).toExist(); - done(); - }); - })); - - it('should call onAsyncError if there is an error fetching options', () => { - expect.assertions(3); - - const errorEndpoint = 'async/error/'; - const errorGlob = 'glob:*async/error/'; - fetchMock.get(errorGlob, { throws: 'error' }); - - const onAsyncError = jest.fn(); - const wrapper = shallow( - , - ); - - return wrapper - .instance() - .fetchOptions() - .then(() => { - // Fails then retries thrice whenever fetching options, which happens twice: - // once on component mount and once when calling `fetchOptions` again - expect(fetchMock.calls(errorGlob)).toHaveLength(8); - expect(onAsyncError.mock.calls).toHaveLength(2); - expect(onAsyncError).toBeCalledWith('error'); - - return Promise.resolve(); - }); - }); - }); -}); diff --git a/superset-frontend/src/components/AsyncSelect/index.jsx b/superset-frontend/src/components/AsyncSelect/index.jsx deleted file mode 100644 index 69799eadeae..00000000000 --- a/superset-frontend/src/components/AsyncSelect/index.jsx +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React from 'react'; -import PropTypes from 'prop-types'; -// TODO: refactor this with `import { AsyncSelect } from src/components/Select` -import { Select } from 'src/components/DeprecatedSelect'; -import { t, SupersetClient } from '@superset-ui/core'; -import { getClientErrorObject } from '../../utils/getClientErrorObject'; - -const propTypes = { - dataEndpoint: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - mutator: PropTypes.func.isRequired, - onAsyncError: PropTypes.func, - value: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.arrayOf(PropTypes.number), - ]), - valueRenderer: PropTypes.func, - placeholder: PropTypes.string, - autoSelect: PropTypes.bool, -}; - -const defaultProps = { - placeholder: t('Select ...'), - onAsyncError: () => {}, -}; - -class AsyncSelect extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - isLoading: false, - options: [], - }; - - this.onChange = this.onChange.bind(this); - } - - componentDidMount() { - this.fetchOptions(); - } - - onChange(option) { - this.props.onChange(option); - } - - fetchOptions() { - this.setState({ isLoading: true }); - const { mutator, dataEndpoint } = this.props; - - return SupersetClient.get({ endpoint: dataEndpoint }) - .then(({ json }) => { - const options = mutator ? mutator(json) : json; - - this.setState({ options, isLoading: false }); - - if (!this.props.value && this.props.autoSelect && options.length > 0) { - this.onChange(options[0]); - } - }) - .catch(response => - getClientErrorObject(response).then(error => { - this.props.onAsyncError(error.error || error.statusText || error); - this.setState({ isLoading: false }); - }), - ); - } - - render() { - return ( - {}} - options={OPTIONS} - placeholder="choose one" - width={600} - /> -
-

With no value

- {}} - options={OPTIONS} - placeholder="choose one or more values" - width={600} - value={[OPTIONS[0]]} - multi - /> - -); - -SelectGallery.args = { - value: '', - options: OPTIONS, -}; - -SelectGallery.story = { - parameters: { - knobs: { - disabled: true, - }, - }, -}; - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -export const InteractiveSelect = (args: any) => { - const [{ value, multi, clearable, placeholder }, updateArgs] = useArgs(); - const onSelect = (selection: {}) => { - const { value }: { value?: any } = selection || {}; - if (multi) { - updateArgs({ value: selection }); - return; - } - updateArgs({ value }); - }; - - return ( - - ); - } - // for CreaTable - if (SelectComponent === WindowedCreatableSelect) { - restProps.getNewOptionData = (inputValue: string, label: string) => ({ - label: label || inputValue, - [valueKey]: inputValue, - isNew: true, - }); - } - - // handle forcing dropdown overflow - // use only when setting overflow:visible isn't possible on the container element - if (forceOverflow) { - Object.assign(restProps, { - closeMenuOnScroll: (e: Event) => { - // ensure menu is open - const menuIsOpen = (stateManager as BasicSelect)?.state - ?.menuIsOpen; - const target = e.target as HTMLElement; - return ( - menuIsOpen && - target && - !target.classList?.contains('Select__menu-list') - ); - }, - menuPosition: 'fixed', - }); - } - - // Make sure always return StateManager for the refs. - // To get the real `Select` component, keep tap into `obj.select`: - // - for normal trigger.parentNode} {...props} /> -))` - display: block; -`; - -const StyledNativeGraySelect = styled(Select)` - &.ant-select-single { - .ant-select-selector { - height: 36px; - padding: 0 11px; - background-color: ${({ theme }) => theme.colors.grayscale.light3}; - border: none; - - .ant-select-selection-search-input { - height: 100%; - } - - .ant-select-selection-item, - .ant-select-selection-placeholder { - line-height: 35px; - color: ${({ theme }) => theme.colors.grayscale.dark1}; - } - } - } -`; - -export const NativeSelect = Object.assign(StyledNativeSelect, { - Option: Select.Option, -}); - -export const NativeGraySelect = Object.assign(StyledNativeGraySelect, { - Option: Select.Option, -}); diff --git a/superset-frontend/src/components/DeprecatedSelect/OnPasteSelect.jsx b/superset-frontend/src/components/DeprecatedSelect/OnPasteSelect.jsx deleted file mode 100644 index bffa5428a60..00000000000 --- a/superset-frontend/src/components/DeprecatedSelect/OnPasteSelect.jsx +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Select } from 'src/components/DeprecatedSelect'; - -export default class OnPasteSelect extends React.Component { - constructor(props) { - super(props); - this.onPaste = this.onPaste.bind(this); - } - - onPaste(evt) { - if (!this.props.isMulti) { - return; - } - evt.preventDefault(); - const clipboard = evt.clipboardData.getData('Text'); - if (!clipboard) { - return; - } - const regex = `[${this.props.separator}]+`; - const values = clipboard.split(new RegExp(regex)).map(v => v.trim()); - const validator = this.props.isValidNewOption; - const selected = this.props.value || []; - const existingOptions = {}; - const existing = {}; - this.props.options.forEach(v => { - existingOptions[v[this.props.valueKey]] = 1; - }); - let options = []; - selected.forEach(v => { - options.push({ [this.props.labelKey]: v, [this.props.valueKey]: v }); - existing[v] = 1; - }); - options = options.concat( - values - .filter(v => { - const notExists = !existing[v]; - existing[v] = 1; - return ( - notExists && - (validator ? validator({ [this.props.labelKey]: v }) : !!v) - ); - }) - .map(v => { - const opt = { [this.props.labelKey]: v, [this.props.valueKey]: v }; - if (!existingOptions[v]) { - this.props.options.unshift(opt); - } - return opt; - }), - ); - if (options.length) { - if (this.props.onChange) { - this.props.onChange(options); - } - } - } - - render() { - const { selectWrap: SelectComponent, ...restProps } = this.props; - return ; - } -} - -OnPasteSelect.propTypes = { - separator: PropTypes.array, - selectWrap: PropTypes.elementType, - selectRef: PropTypes.func, - onChange: PropTypes.func.isRequired, - valueKey: PropTypes.string, - labelKey: PropTypes.string, - options: PropTypes.array, - isMulti: PropTypes.bool, - value: PropTypes.any, - isValidNewOption: PropTypes.func, - noResultsText: PropTypes.string, - forceOverflow: PropTypes.bool, -}; -OnPasteSelect.defaultProps = { - separator: [',', '\n', '\t', ';'], - selectWrap: Select, - valueKey: 'value', - labelKey: 'label', - options: [], - isMulti: false, -}; diff --git a/superset-frontend/src/components/DeprecatedSelect/OnPasteSelect.test.jsx b/superset-frontend/src/components/DeprecatedSelect/OnPasteSelect.test.jsx deleted file mode 100644 index 95d01cc28b9..00000000000 --- a/superset-frontend/src/components/DeprecatedSelect/OnPasteSelect.test.jsx +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -/* eslint-disable no-unused-expressions */ -import React from 'react'; -import sinon from 'sinon'; -import { shallow } from 'enzyme'; -import { - Select, - OnPasteSelect, - CreatableSelect, -} from 'src/components/DeprecatedSelect'; - -const defaultProps = { - onChange: sinon.spy(), - isMulti: true, - isValidNewOption: sinon.spy(s => !!s.label), - value: [], - options: [ - { value: 'United States', label: 'United States' }, - { value: 'China', label: 'China' }, - { value: 'India', label: 'India' }, - { value: 'Canada', label: 'Canada' }, - { value: 'Russian Federation', label: 'Russian Federation' }, - { value: 'Japan', label: 'Japan' }, - { value: 'Mexico', label: 'Mexico' }, - ], -}; - -const defaultEvt = { - preventDefault: sinon.spy(), - clipboardData: { - getData: sinon.spy(() => ' United States, China, India, Canada, '), - }, -}; - -describe('OnPasteSelect', () => { - let wrapper; - let props; - let evt; - let expected; - beforeEach(() => { - props = { ...defaultProps }; - wrapper = shallow(); - evt = { ...defaultEvt }; - }); - - it('renders the supplied selectWrap component', () => { - const select = wrapper.findWhere(x => x.type() === Select); - expect(select).toHaveLength(1); - }); - - it('renders custom selectWrap components', () => { - props.selectWrap = CreatableSelect; - wrapper = shallow(); - expect(wrapper.findWhere(x => x.type() === CreatableSelect)).toHaveLength( - 1, - ); - }); - - describe('onPaste', () => { - it('calls onChange with pasted comma separated values', () => { - wrapper.instance().onPaste(evt); - expected = props.options.slice(0, 4); - expect(props.onChange.calledWith(expected)).toBe(true); - expect(evt.preventDefault.called).toBe(true); - expect(props.isValidNewOption.callCount).toBe(5); - }); - - it('calls onChange with pasted new line separated values', () => { - evt.clipboardData.getData = sinon.spy( - () => 'United States\nChina\nRussian Federation\nIndia', - ); - wrapper.instance().onPaste(evt); - expected = [ - props.options[0], - props.options[1], - props.options[4], - props.options[2], - ]; - expect(props.onChange.calledWith(expected)).toBe(true); - expect(evt.preventDefault.called).toBe(true); - expect(props.isValidNewOption.callCount).toBe(9); - }); - - it('calls onChange with pasted tab separated values', () => { - evt.clipboardData.getData = sinon.spy( - () => 'Russian Federation\tMexico\tIndia\tCanada', - ); - wrapper.instance().onPaste(evt); - expected = [ - props.options[4], - props.options[6], - props.options[2], - props.options[3], - ]; - expect(props.onChange.calledWith(expected)).toBe(true); - expect(evt.preventDefault.called).toBe(true); - expect(props.isValidNewOption.callCount).toBe(13); - }); - - it('calls onChange without duplicate values and adds new comma separated values', () => { - evt.clipboardData.getData = sinon.spy( - () => 'China, China, China, China, Mexico, Mexico, Chi na, Mexico, ', - ); - expected = [ - props.options[1], - props.options[6], - { label: 'Chi na', value: 'Chi na' }, - ]; - wrapper.instance().onPaste(evt); - expect(props.onChange.calledWith(expected)).toBe(true); - expect(evt.preventDefault.called).toBe(true); - expect(props.isValidNewOption.callCount).toBe(17); - expect(props.options[0].value).toBe(expected[2].value); - props.options.splice(0, 1); - }); - - it('calls onChange without duplicate values and parses new line separated values', () => { - evt.clipboardData.getData = sinon.spy( - () => 'United States\nCanada\nMexico\nUnited States\nCanada', - ); - expected = [props.options[0], props.options[3], props.options[6]]; - wrapper.instance().onPaste(evt); - expect(props.onChange.calledWith(expected)).toBe(true); - expect(evt.preventDefault.called).toBe(true); - expect(props.isValidNewOption.callCount).toBe(20); - }); - - it('calls onChange without duplicate values and parses tab separated values', () => { - evt.clipboardData.getData = sinon.spy( - () => 'China\tIndia\tChina\tRussian Federation\tJapan\tJapan', - ); - expected = [ - props.options[1], - props.options[2], - props.options[4], - props.options[5], - ]; - wrapper.instance().onPaste(evt); - expect(props.onChange.calledWith(expected)).toBe(true); - expect(evt.preventDefault.called).toBe(true); - expect(props.isValidNewOption.callCount).toBe(24); - }); - - it('calls onChange with currently selected values and new comma separated values', () => { - props.value = ['United States', 'Canada', 'Mexico']; - evt.clipboardData.getData = sinon.spy( - () => 'United States, Canada, Japan, India', - ); - wrapper = shallow(); - expected = [ - props.options[0], - props.options[3], - props.options[6], - props.options[5], - props.options[2], - ]; - wrapper.instance().onPaste(evt); - expect(props.onChange.calledWith(expected)).toBe(true); - expect(evt.preventDefault.called).toBe(true); - expect(props.isValidNewOption.callCount).toBe(26); - }); - - it('calls onChange with currently selected values and new "new line" separated values', () => { - props.value = ['China', 'India', 'Japan']; - evt.clipboardData.getData = sinon.spy(() => 'Mexico\nJapan\nIndia'); - wrapper = shallow(); - expected = [ - props.options[1], - props.options[2], - props.options[5], - props.options[6], - ]; - wrapper.instance().onPaste(evt); - expect(props.onChange.calledWith(expected)).toBe(true); - expect(evt.preventDefault.called).toBe(true); - expect(props.isValidNewOption.callCount).toBe(27); - }); - - it('calls onChange with currently selected values and new tab separated values', () => { - props.value = ['United States', 'Canada', 'Mexico', 'Russian Federation']; - evt.clipboardData.getData = sinon.spy( - () => 'United States\tCanada\tJapan\tIndia', - ); - wrapper = shallow(); - expected = [ - props.options[0], - props.options[3], - props.options[6], - props.options[4], - props.options[5], - props.options[2], - ]; - wrapper.instance().onPaste(evt); - expect(props.onChange.calledWith(expected)).toBe(true); - expect(evt.preventDefault.called).toBe(true); - expect(props.isValidNewOption.callCount).toBe(29); - }); - }); -}); diff --git a/superset-frontend/src/components/DeprecatedSelect/WindowedSelect/WindowedMenuList.tsx b/superset-frontend/src/components/DeprecatedSelect/WindowedSelect/WindowedMenuList.tsx deleted file mode 100644 index f29466b3398..00000000000 --- a/superset-frontend/src/components/DeprecatedSelect/WindowedSelect/WindowedMenuList.tsx +++ /dev/null @@ -1,158 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React, { - useRef, - useEffect, - Component, - FunctionComponent, - ReactElement, - RefObject, -} from 'react'; -import { - ListChildComponentProps, - FixedSizeList as WindowedList, -} from 'react-window'; -import { - OptionTypeBase, - OptionProps, - MenuListComponentProps, -} from 'react-select'; -import { ThemeConfig } from '../styles'; - -export type WindowedMenuListProps = { - selectProps: { - windowListRef?: RefObject; - optionHeight?: number; - }; -}; - -/** - * MenuListComponentProps should always have `children` elements, as guaranteed - * by https://github.com/JedWatson/react-select/blob/32ad5c040bdd96cd1ca71010c2558842d684629c/packages/react-select/src/Select.js#L1686-L1719 - * - * `children` may also be `Component>` if options are not - * provided (e.g., when async list is still loading, or no results), but that's - * not possible because this MenuList will only be rendered when - * optionsLength > windowThreshold. - * - * If may also be `Component>[]` but we are not supporting - * grouped options just yet. - */ - -type MenuListPropsChildren = - | Component>[] - | ReactElement[]; - -export type MenuListProps = - MenuListComponentProps & { - children: MenuListPropsChildren; - // theme is not present with built-in @types/react-select, but is actually - // available via CommonProps. - theme?: ThemeConfig; - className?: string; - } & WindowedMenuListProps; - -const DEFAULT_OPTION_HEIGHT = 30; - -/** - * Get the index of the last selected option. - */ -function getLastSelected(children: MenuListPropsChildren) { - return Array.isArray(children) - ? children.findIndex( - ({ props: { isFocused = false } = {} }) => isFocused, - ) || 0 - : -1; -} - -/** - * Calculate probable option height as set in theme configs - */ -function detectHeight({ spacing: { baseUnit, lineHeight } }: ThemeConfig) { - // Option item expects 2 * baseUnit for each of top and bottom padding. - return baseUnit * 4 + lineHeight; -} - -export default function WindowedMenuList({ - children, - ...props -}: MenuListProps) { - const { - maxHeight, - selectProps, - theme, - getStyles, - cx, - innerRef, - isMulti, - className, - } = props; - const { - // Expose react-window VariableSizeList instance and HTML elements - windowListRef: windowListRef_, - windowListInnerRef, - } = selectProps; - const defaultWindowListRef = useRef(null); - const windowListRef = windowListRef_ || defaultWindowListRef; - - // try get default option height from theme configs - let { optionHeight } = selectProps; - if (!optionHeight) { - optionHeight = theme ? detectHeight(theme) : DEFAULT_OPTION_HEIGHT; - } - - const itemCount = children.length; - const totalHeight = optionHeight * itemCount; - - const Row: FunctionComponent = ({ - data, - index, - style, - }) =>
{data[index]}
; - - useEffect(() => { - const lastSelected = getLastSelected(children); - if (windowListRef.current && lastSelected) { - windowListRef.current.scrollToItem(lastSelected); - } - }, [children, windowListRef]); - - return ( - - {Row} - - ); -} diff --git a/superset-frontend/src/components/DeprecatedSelect/WindowedSelect/index.tsx b/superset-frontend/src/components/DeprecatedSelect/WindowedSelect/index.tsx deleted file mode 100644 index 3770b542df4..00000000000 --- a/superset-frontend/src/components/DeprecatedSelect/WindowedSelect/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import Select from 'react-select'; -import Creatable from 'react-select/creatable'; -import AsyncCreatable from 'react-select/async-creatable'; -import windowed from './windowed'; - -export * from './windowed'; - -export const WindowedSelect = windowed(Select); -export const WindowedCreatableSelect = windowed(Creatable); -export const WindowedAsyncCreatableSelect = windowed(AsyncCreatable); -export default WindowedSelect; diff --git a/superset-frontend/src/components/DeprecatedSelect/WindowedSelect/windowed.tsx b/superset-frontend/src/components/DeprecatedSelect/WindowedSelect/windowed.tsx deleted file mode 100644 index a611cf36c96..00000000000 --- a/superset-frontend/src/components/DeprecatedSelect/WindowedSelect/windowed.tsx +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React, { - ComponentType, - FunctionComponent, - ReactElement, - forwardRef, -} from 'react'; -import Select, { - Props as SelectProps, - OptionTypeBase, - MenuListComponentProps, - components as defaultComponents, -} from 'react-select'; -import WindowedMenuList, { WindowedMenuListProps } from './WindowedMenuList'; - -const { MenuList: DefaultMenuList } = defaultComponents; - -export const DEFAULT_WINDOW_THRESHOLD = 100; - -export type WindowedSelectProps = - SelectProps & { - windowThreshold?: number; - } & WindowedMenuListProps['selectProps']; - -export type WindowedSelectComponentType = - FunctionComponent>; - -export function MenuList({ - children, - ...props -}: MenuListComponentProps & { - selectProps: WindowedSelectProps; -}) { - const { windowThreshold = DEFAULT_WINDOW_THRESHOLD } = props.selectProps; - if (Array.isArray(children) && children.length > windowThreshold) { - return ( - - {children as ReactElement[]} - - ); - } - return {children}; -} - -/** - * Add "windowThreshold" option to a react-select component, turn the options - * list into a virtualized list when appropriate. - * - * @param SelectComponent the React component to render Select - */ -export default function windowed( - SelectComponent: ComponentType>, -): WindowedSelectComponentType { - const WindowedSelect = forwardRef( - ( - props: WindowedSelectProps, - ref: React.RefObject>, - ) => { - const { components: components_ = {}, ...restProps } = props; - const components = { ...components_, MenuList }; - return ( - - ); - }, - ); - return WindowedSelect; -} diff --git a/superset-frontend/src/components/DeprecatedSelect/index.ts b/superset-frontend/src/components/DeprecatedSelect/index.ts deleted file mode 100644 index e8f30eb7e4c..00000000000 --- a/superset-frontend/src/components/DeprecatedSelect/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -export * from './DeprecatedSelect'; -export * from './styles'; -export { default } from './DeprecatedSelect'; -export { default as OnPasteSelect } from './OnPasteSelect'; -export { NativeSelect, NativeGraySelect } from './NativeSelect'; diff --git a/superset-frontend/src/components/DeprecatedSelect/styles.tsx b/superset-frontend/src/components/DeprecatedSelect/styles.tsx deleted file mode 100644 index f04cfbdba9e..00000000000 --- a/superset-frontend/src/components/DeprecatedSelect/styles.tsx +++ /dev/null @@ -1,406 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// Deprecated component -/* eslint-disable theme-colors/no-literal-colors */ - -import React, { CSSProperties, ComponentType, ReactNode } from 'react'; -import { SerializedStyles } from '@emotion/react'; -import { SupersetTheme, css } from '@superset-ui/core'; -import { - Styles, - Theme, - SelectComponentsConfig, - components as defaultComponents, - InputProps as ReactSelectInputProps, - Props as SelectProps, -} from 'react-select'; -import type { colors as reactSelectColors } from 'react-select/src/theme'; -import type { DeepNonNullable } from 'react-select/src/components'; -import { OptionType } from 'antd/lib/select'; -import { SupersetStyledSelectProps } from './DeprecatedSelect'; - -export const DEFAULT_CLASS_NAME = 'Select'; -export const DEFAULT_CLASS_NAME_PREFIX = 'Select'; - -type RecursivePartial = { - [P in keyof T]?: RecursivePartial; -}; - -const colors = (theme: SupersetTheme) => ({ - primary: theme.colors.success.base, - danger: theme.colors.error.base, - warning: theme.colors.warning.base, - indicator: theme.colors.info.base, - almostBlack: theme.colors.grayscale.dark1, - grayDark: theme.colors.grayscale.dark1, - grayLight: theme.colors.grayscale.light2, - gray: theme.colors.grayscale.light1, - grayBg: theme.colors.grayscale.light4, - grayBgDarker: theme.colors.grayscale.light3, - grayBgDarkest: theme.colors.grayscale.light2, - grayHeading: theme.colors.grayscale.light1, - menuHover: theme.colors.grayscale.light3, - lightest: theme.colors.grayscale.light5, - darkest: theme.colors.grayscale.dark2, - grayBorder: theme.colors.grayscale.light2, - grayBorderLight: theme.colors.grayscale.light3, - grayBorderDark: theme.colors.grayscale.light1, - textDefault: theme.colors.grayscale.dark1, - textDarkest: theme.colors.grayscale.dark2, - dangerLight: theme.colors.error.light1, -}); - -export type ThemeConfig = { - borderRadius: number; - // z-index for menu dropdown - // (the same as `@z-index-above-dashboard-charts + 1` in variables.less) - zIndex: number; - colors: { - // add known colors - [key in keyof typeof reactSelectColors]: string; - } & { - [key in keyof ReturnType]: string; - } & { - [key: string]: string; // any other colors - }; - spacing: Theme['spacing'] & { - // line height and font size must be pixels for easier computation - // of option item height in WindowedMenuList - lineHeight: number; - fontSize: number; - // other relative size must be string - minWidth: string; - }; -}; - -export type PartialThemeConfig = RecursivePartial; - -export const defaultTheme: (theme: SupersetTheme) => PartialThemeConfig = - theme => ({ - borderRadius: theme.borderRadius, - zIndex: 11, - colors: colors(theme), - spacing: { - baseUnit: 3, - menuGutter: 0, - controlHeight: 34, - lineHeight: 19, - fontSize: 14, - minWidth: '6.5em', - }, - weights: theme.typography.weights, - }); - -// let styles accept serialized CSS, too -type CSSStyles = CSSProperties | SerializedStyles; -type styleFnWithSerializedStyles = ( - base: CSSProperties, - state: any, -) => CSSStyles | CSSStyles[]; - -export type StylesConfig = { - [key in keyof Styles]: styleFnWithSerializedStyles; -}; -export type PartialStylesConfig = Partial; - -export const DEFAULT_STYLES: PartialStylesConfig = { - container: ( - provider, - { - theme: { - spacing: { minWidth }, - }, - }, - ) => [ - provider, - css` - min-width: ${minWidth}; - `, - ], - placeholder: provider => [ - provider, - css` - white-space: nowrap; - `, - ], - indicatorSeparator: () => css` - display: none; - `, - indicatorsContainer: provider => [ - provider, - css` - i { - width: 1em; - display: inline-block; - } - `, - ], - clearIndicator: provider => [ - provider, - css` - padding: 4px 0 4px 6px; - `, - ], - control: ( - provider, - { isFocused, menuIsOpen, theme: { borderRadius, colors } }, - ) => { - const isPseudoFocused = isFocused && !menuIsOpen; - let borderColor = colors.grayBorder; - if (isPseudoFocused || menuIsOpen) { - borderColor = colors.grayBorderDark; - } - return [ - provider, - css` - border-color: ${borderColor}; - box-shadow: ${isPseudoFocused - ? 'inset 0 1px 1px rgba(0,0,0,.075), 0 0 0 3px rgba(0,0,0,.1)' - : 'none'}; - border-radius: ${menuIsOpen - ? `${borderRadius}px ${borderRadius}px 0 0` - : `${borderRadius}px`}; - &:hover { - border-color: ${borderColor}; - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06); - } - flex-wrap: nowrap; - padding-left: 1px; - `, - ]; - }, - menu: (provider, { theme: { zIndex } }) => [ - provider, - css` - padding-bottom: 2em; - z-index: ${zIndex}; /* override at least multi-page pagination */ - width: auto; - min-width: 100%; - max-width: 80vw; - background: none; - box-shadow: none; - border: 0; - `, - ], - menuList: (provider, { theme: { borderRadius, colors } }) => [ - provider, - css` - background: ${colors.lightest}; - border-radius: 0 0 ${borderRadius}px ${borderRadius}px; - border: 1px solid ${colors.grayBorderDark}; - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06); - margin-top: -1px; - border-top-color: ${colors.grayBorderLight}; - min-width: 100%; - width: auto; - border-radius: 0 0 ${borderRadius}px ${borderRadius}px; - padding-top: 0; - padding-bottom: 0; - `, - ], - option: ( - provider, - { - isDisabled, - isFocused, - isSelected, - theme: { - colors, - spacing: { lineHeight, fontSize }, - weights, - }, - }, - ) => { - let color = colors.textDefault; - let backgroundColor = colors.lightest; - if (isFocused) { - backgroundColor = colors.grayBgDarker; - } else if (isDisabled) { - color = '#ccc'; - } - return [ - provider, - css` - cursor: pointer; - line-height: ${lineHeight}px; - font-size: ${fontSize}px; - background-color: ${backgroundColor}; - color: ${color}; - font-weight: ${isSelected ? weights.bold : weights.normal}; - white-space: nowrap; - &:hover:active { - background-color: ${colors.grayBg}; - } - `, - ]; - }, - valueContainer: ( - provider, - { - isMulti, - hasValue, - theme: { - spacing: { baseUnit }, - }, - }, - ) => [ - provider, - css` - padding-left: ${isMulti && hasValue ? 1 : baseUnit * 3}px; - `, - ], - multiValueLabel: ( - provider, - { - theme: { - spacing: { baseUnit }, - }, - }, - ) => ({ - ...provider, - paddingLeft: baseUnit * 1.2, - paddingRight: baseUnit * 1.2, - }), - input: (provider, { selectProps }) => [ - provider, - css` - margin-left: 0; - vertical-align: middle; - ${selectProps?.isMulti && selectProps?.value?.length - ? 'padding: 0 6px; width: 100%' - : 'padding: 0; flex: 1 1 auto;'}; - `, - ], - menuPortal: base => ({ - ...base, - zIndex: 1030, // must be same or higher of antd popover - }), -}; - -const INPUT_TAG_BASE_STYLES = { - background: 'none', - border: 'none', - outline: 'none', - padding: 0, -}; - -export type SelectComponentsType = Omit< - SelectComponentsConfig, - 'Input' -> & { - Input: ComponentType; -}; - -// react-select is missing selectProps from their props type -// so overwriting it here to avoid errors -export type InputProps = ReactSelectInputProps & { - placeholder?: ReactNode; - selectProps: SelectProps; - autoComplete?: string; - onPaste?: SupersetStyledSelectProps['onPaste']; - inputStyle?: object; -}; - -const { ClearIndicator, DropdownIndicator, Option, Input, SelectContainer } = - defaultComponents as Required>; - -export const DEFAULT_COMPONENTS: SelectComponentsType = { - SelectContainer: ({ children, ...props }) => { - const { - selectProps: { assistiveText }, - } = props; - return ( -
- {children} - {assistiveText && ( - ({ - marginLeft: 3, - fontSize: theme.typography.sizes.s, - color: theme.colors.grayscale.light1, - })} - > - {assistiveText} - - )} -
- ); - }, - Option: ({ children, innerProps, data, ...props }) => ( - - ), - ClearIndicator: props => ( - - × - - ), - DropdownIndicator: props => ( - - - - ), - Input: (props: InputProps) => { - const { getStyles } = props; - return ( - - ); - }, -}; - -export const VALUE_LABELED_STYLES: PartialStylesConfig = { - valueContainer: ( - provider, - { - getValue, - theme: { - spacing: { baseUnit }, - }, - isMulti, - }, - ) => ({ - ...provider, - paddingLeft: getValue().length > 0 ? 1 : baseUnit * 3, - overflow: isMulti && getValue().length > 0 ? 'visible' : 'hidden', - }), - // render single value as is they are multi-value - singleValue: (provider, props) => { - const { getStyles } = props; - return { - ...getStyles('multiValue', props), - '.metric-option': getStyles('multiValueLabel', props), - }; - }, -}; diff --git a/superset-frontend/src/components/DeprecatedSelect/utils.ts b/superset-frontend/src/components/DeprecatedSelect/utils.ts deleted file mode 100644 index a6590efebd3..00000000000 --- a/superset-frontend/src/components/DeprecatedSelect/utils.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { - OptionTypeBase, - ValueType, - OptionsType, - GroupedOptionsType, -} from 'react-select'; - -/** - * Find Option value that matches a possibly string value. - * - * Translate possible string values to `OptionType` objects, fallback to value - * itself if cannot be found in the options list. - * - * Always returns an array. - */ -export function findValue( - value: ValueType | string, - options: GroupedOptionsType | OptionsType = [], - valueKey = 'value', -): OptionType[] { - if (value === null || value === undefined || value === '') { - return []; - } - const isGroup = Array.isArray(options[0]?.options); - const flatOptions = isGroup - ? (options as GroupedOptionsType).flatMap(x => x.options || []) - : (options as OptionsType); - - const find = (val: OptionType) => { - const realVal = value?.hasOwnProperty(valueKey) ? val[valueKey] : val; - return ( - flatOptions.find(x => x === realVal || x[valueKey] === realVal) || val - ); - }; - - // If value is a single string, must return an Array so `cleanValue` won't be - // empty: https://github.com/JedWatson/react-select/blob/32ad5c040bdd96cd1ca71010c2558842d684629c/packages/react-select/src/utils.js#L64 - return (Array.isArray(value) ? value : [value]).map(find); -} diff --git a/superset-frontend/src/components/ListView/utils.ts b/superset-frontend/src/components/ListView/utils.ts index 8a8c57cb623..31a9368a1ab 100644 --- a/superset-frontend/src/components/ListView/utils.ts +++ b/superset-frontend/src/components/ListView/utils.ts @@ -35,7 +35,6 @@ import { import rison from 'rison'; import { isEqual } from 'lodash'; -import { PartialStylesConfig } from 'src/components/DeprecatedSelect'; import { FetchDataConfig, Filter, @@ -381,21 +380,3 @@ export function useListViewState({ query, }; } - -export const filterSelectStyles: PartialStylesConfig = { - container: (provider, { getValue }) => ({ - ...provider, - // dynamic width based on label string length - minWidth: `${Math.min( - 12, - Math.max(5, 3 + getValue()[0].label.length / 2), - )}em`, - }), - control: provider => ({ - ...provider, - borderWidth: 0, - boxShadow: 'none', - cursor: 'pointer', - backgroundColor: 'transparent', - }), -}; diff --git a/superset-frontend/src/components/Select/AsyncSelect.tsx b/superset-frontend/src/components/Select/AsyncSelect.tsx index d102af74833..015a12cb968 100644 --- a/superset-frontend/src/components/Select/AsyncSelect.tsx +++ b/superset-frontend/src/components/Select/AsyncSelect.tsx @@ -90,8 +90,6 @@ const getQueryCacheKey = (value: string, page: number, pageSize: number) => /** * This component is a customized version of the Antdesign 4.X Select component * https://ant.design/components/select/. - * The aim of the component was to combine all the instances of select components throughout the - * project under one and to remove the react-select component entirely. * This Select component provides an API that is tested against all the different use cases of Superset. * It limits and overrides the existing Antdesign API in order to keep their usage to the minimum * and to enforce simplification and standardization. diff --git a/superset-frontend/src/components/Select/Select.tsx b/superset-frontend/src/components/Select/Select.tsx index 1e3bc73758c..f4f9565abb8 100644 --- a/superset-frontend/src/components/Select/Select.tsx +++ b/superset-frontend/src/components/Select/Select.tsx @@ -73,8 +73,6 @@ import { customTagRender } from './CustomTag'; /** * This component is a customized version of the Antdesign 4.X Select component * https://ant.design/components/select/. - * The aim of the component was to combine all the instances of select components throughout the - * project under one and to remove the react-select component entirely. * This Select component provides an API that is tested against all the different use cases of Superset. * It limits and overrides the existing Antdesign API in order to keep their usage to the minimum * and to enforce simplification and standardization. diff --git a/superset-frontend/src/dashboard/actions/dashboardFilters.js b/superset-frontend/src/dashboard/actions/dashboardFilters.js index b8f92b8df05..0e5e5454c68 100644 --- a/superset-frontend/src/dashboard/actions/dashboardFilters.js +++ b/superset-frontend/src/dashboard/actions/dashboardFilters.js @@ -22,26 +22,6 @@ function isValidFilter(getState, chartId) { return getState().dashboardState.sliceIds.includes(chartId); } -export const ADD_FILTER = 'ADD_FILTER'; -export function addFilter(chartId, component, form_data) { - return (dispatch, getState) => { - if (isValidFilter(getState, chartId)) { - return dispatch({ type: ADD_FILTER, chartId, component, form_data }); - } - return getState().dashboardFilters; - }; -} - -export const REMOVE_FILTER = 'REMOVE_FILTER'; -export function removeFilter(chartId) { - return (dispatch, getState) => { - if (isValidFilter(getState, chartId)) { - return dispatch({ type: REMOVE_FILTER, chartId }); - } - return getState().dashboardFilters; - }; -} - export const CHANGE_FILTER = 'CHANGE_FILTER'; export function changeFilter(chartId, newSelectedValues, merge) { return (dispatch, getState) => { diff --git a/superset-frontend/src/dashboard/actions/dashboardState.js b/superset-frontend/src/dashboard/actions/dashboardState.js index b461275d8c6..fa3eeadf41d 100644 --- a/superset-frontend/src/dashboard/actions/dashboardState.js +++ b/superset-frontend/src/dashboard/actions/dashboardState.js @@ -61,11 +61,7 @@ import { SAVE_CHART_CONFIG_COMPLETE, } from './dashboardInfo'; import { fetchDatasourceMetadata } from './datasources'; -import { - addFilter, - removeFilter, - updateDirectPathToFilter, -} from './dashboardFilters'; +import { updateDirectPathToFilter } from './dashboardFilters'; import { SET_FILTER_CONFIG_COMPLETE } from './nativeFilters'; import getOverwriteItems from '../util/getOverwriteItems'; @@ -554,7 +550,7 @@ export function showBuilderPane() { return { type: SHOW_BUILDER_PANE }; } -export function addSliceToDashboard(id, component) { +export function addSliceToDashboard(id) { return (dispatch, getState) => { const { sliceEntities } = getState(); const selectedSlice = sliceEntities.slices[id]; @@ -580,21 +576,12 @@ export function addSliceToDashboard(id, component) { dispatch(fetchDatasourceMetadata(form_data.datasource)), ]).then(() => { dispatch(addSlice(selectedSlice)); - - if (selectedSlice && selectedSlice.viz_type === 'filter_box') { - dispatch(addFilter(id, component, selectedSlice.form_data)); - } }); }; } export function removeSliceFromDashboard(id) { - return (dispatch, getState) => { - const sliceEntity = getState().sliceEntities.slices[id]; - if (sliceEntity && sliceEntity.viz_type === 'filter_box') { - dispatch(removeFilter(id)); - } - + return dispatch => { dispatch(removeSlice(id)); dispatch(removeChart(id)); getSharedLabelColor().removeSlice(id); diff --git a/superset-frontend/src/dashboard/actions/dashboardState.test.js b/superset-frontend/src/dashboard/actions/dashboardState.test.js index 1ef85f0b99c..4e30c38fb1d 100644 --- a/superset-frontend/src/dashboard/actions/dashboardState.test.js +++ b/superset-frontend/src/dashboard/actions/dashboardState.test.js @@ -21,12 +21,10 @@ import { SupersetClient } from '@superset-ui/core'; import { waitFor } from '@testing-library/react'; import { - removeSliceFromDashboard, SAVE_DASHBOARD_STARTED, saveDashboardRequest, SET_OVERRIDE_CONFIRM, } from 'src/dashboard/actions/dashboardState'; -import { REMOVE_FILTER } from 'src/dashboard/actions/dashboardFilters'; import * as uiCore from '@superset-ui/core'; import { UPDATE_COMPONENTS_PARENTS_LIST } from 'src/dashboard/actions/dashboardLayout'; import { @@ -193,14 +191,4 @@ describe('dashboardState actions', () => { }); }); }); - - it('should dispatch removeFilter if a removed slice is a filter_box', () => { - const { getState, dispatch } = setup(mockState); - const thunk = removeSliceFromDashboard(filterId); - thunk(dispatch, getState); - - const removeFilter = dispatch.getCall(0).args[0]; - removeFilter(dispatch, getState); - expect(dispatch.getCall(3).args[0].type).toBe(REMOVE_FILTER); - }); }); diff --git a/superset-frontend/src/dashboard/actions/hydrate.js b/superset-frontend/src/dashboard/actions/hydrate.js index 699c2041c89..930280a1f9b 100644 --- a/superset-frontend/src/dashboard/actions/hydrate.js +++ b/superset-frontend/src/dashboard/actions/hydrate.js @@ -32,10 +32,6 @@ import { getCrossFiltersConfiguration, isCrossFiltersEnabled, } from 'src/dashboard/util/crossFilters'; -import { - DASHBOARD_FILTER_SCOPE_GLOBAL, - dashboardFilter, -} from 'src/dashboard/reducers/dashboardFilters'; import { DASHBOARD_HEADER_ID, GRID_DEFAULT_CHART_WIDTH, @@ -49,10 +45,8 @@ import { } from 'src/dashboard/util/componentTypes'; import findFirstParentContainerId from 'src/dashboard/util/findFirstParentContainer'; import getEmptyLayout from 'src/dashboard/util/getEmptyLayout'; -import getFilterConfigsFromFormdata from 'src/dashboard/util/getFilterConfigsFromFormdata'; import getLocationHash from 'src/dashboard/util/getLocationHash'; import newComponentFactory from 'src/dashboard/util/newComponentFactory'; -import { TIME_RANGE } from 'src/visualizations/FilterBox/FilterBox'; import { URL_PARAMS } from 'src/constants'; import { getUrlParam } from 'src/utils/urlUtils'; import { ResourceStatus } from 'src/hooks/apiResources/apiResources'; @@ -72,20 +66,10 @@ export const hydrateDashboard = const reservedUrlParams = extractUrlParams('reserved'); const editMode = reservedUrlParams.edit === 'true'; - let preselectFilters = {}; - charts.forEach(chart => { // eslint-disable-next-line no-param-reassign chart.slice_id = chart.form_data.slice_id; }); - try { - // allow request parameter overwrite dashboard metadata - preselectFilters = - getUrlParam(URL_PARAMS.preselectFilters) || - JSON.parse(metadata.default_filters); - } catch (e) { - // - } if (metadata?.shared_label_colors) { updateColorSchema(metadata, metadata?.shared_label_colors); @@ -117,8 +101,6 @@ export const hydrateDashboard = let newSlicesContainer; let newSlicesContainerWidth = 0; - const filterScopes = metadata?.filter_scopes || {}; - const chartQueries = {}; const dashboardFilters = {}; const slices = {}; @@ -189,57 +171,6 @@ export const hydrateDashboard = newSlicesContainerWidth += GRID_DEFAULT_CHART_WIDTH; } - // build DashboardFilters for interactive filter features - if (slice.form_data.viz_type === 'filter_box') { - const configs = getFilterConfigsFromFormdata(slice.form_data); - let { columns } = configs; - const { labels } = configs; - if (preselectFilters[key]) { - Object.keys(columns).forEach(col => { - if (preselectFilters[key][col]) { - columns = { - ...columns, - [col]: preselectFilters[key][col], - }; - } - }); - } - - const scopesByChartId = Object.keys(columns).reduce((map, column) => { - const scopeSettings = { - ...filterScopes[key], - }; - const { scope, immune } = { - ...DASHBOARD_FILTER_SCOPE_GLOBAL, - ...scopeSettings[column], - }; - - return { - ...map, - [column]: { - scope, - immune, - }, - }; - }, {}); - - const componentId = chartIdToLayoutId[key]; - const directPathToFilter = (layout[componentId].parents || []).slice(); - directPathToFilter.push(componentId); - dashboardFilters[key] = { - ...dashboardFilter, - chartId: key, - componentId, - datasourceId: slice.form_data.datasource, - filterName: slice.slice_name, - directPathToFilter, - columns, - labels, - scopes: scopesByChartId, - isDateFilter: Object.keys(columns).includes(TIME_RANGE), - }; - } - // sync layout names with current slice names in case a slice was edited // in explore since the layout was updated. name updates go through layout for undo/redo // functionality and python updates slice names based on layout upon dashboard save diff --git a/superset-frontend/src/dashboard/actions/sliceEntities.ts b/superset-frontend/src/dashboard/actions/sliceEntities.ts index 562d90657e7..9d85e57a6a5 100644 --- a/superset-frontend/src/dashboard/actions/sliceEntities.ts +++ b/superset-frontend/src/dashboard/actions/sliceEntities.ts @@ -17,13 +17,7 @@ * under the License. */ import rison from 'rison'; -import { - DatasourceType, - isFeatureEnabled, - FeatureFlag, - SupersetClient, - t, -} from '@superset-ui/core'; +import { DatasourceType, SupersetClient, t } from '@superset-ui/core'; import { addDangerToast } from 'src/components/MessageToasts/actions'; import { getClientErrorObject } from 'src/utils/getClientErrorObject'; import { Dispatch } from 'redux'; @@ -114,14 +108,6 @@ export function fetchSlices( ? [{ col: 'slice_name', opr: 'chart_all_text', value: filter_value }] : []; - if (isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS)) { - filters.push({ - col: 'viz_type', - opr: 'neq', - value: 'filter_box', - }); - } - if (userId) { filters.push({ col: 'owners', opr: 'rel_m_m', value: userId }); } diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx index 02a3a49971c..179c03c996f 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx @@ -47,12 +47,6 @@ jest.mock('src/dashboard/actions/dashboardState', () => ({ jest.mock('src/components/ResizableSidebar/useStoredSidebarWidth'); // mock following dependant components to fix the prop warnings -jest.mock('src/components/DeprecatedSelect/WindowedSelect', () => () => ( -
-)); -jest.mock('src/components/DeprecatedSelect', () => () => ( -
-)); jest.mock('src/components/Select/Select', () => () => (
)); diff --git a/superset-frontend/src/dashboard/components/FilterBoxMigrationModal.tsx b/superset-frontend/src/dashboard/components/FilterBoxMigrationModal.tsx deleted file mode 100644 index d42b3254bec..00000000000 --- a/superset-frontend/src/dashboard/components/FilterBoxMigrationModal.tsx +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React, { FunctionComponent } from 'react'; -import { styled, t } from '@superset-ui/core'; - -import Modal from 'src/components/Modal'; -import Button from 'src/components/Button'; - -const StyledFilterBoxMigrationModal = styled(Modal)` - .modal-content { - height: 900px; - display: flex; - flex-direction: column; - align-items: stretch; - } - - .modal-header { - flex: 0 1 auto; - } - - .modal-body { - flex: 1 1 auto; - overflow: auto; - } - - .modal-footer { - flex: 0 1 auto; - } - - .ant-modal-body { - overflow: auto; - } -`; - -interface FilterBoxMigrationModalProps { - onHide: () => void; - onClickReview: () => void; - onClickSnooze: () => void; - show: boolean; - hideFooter: boolean; -} - -const FilterBoxMigrationModal: FunctionComponent = - ({ onClickReview, onClickSnooze, onHide, show, hideFooter = false }) => ( - - - - - - } - responsive - > -
- {t( - 'filter_box will be deprecated ' + - 'in a future version of Superset. ' + - 'Please replace filter_box by dashboard filter components.', - )} -
-
- ); - -export default FilterBoxMigrationModal; diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx b/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx index 2d7b5c05bdf..83099e54907 100644 --- a/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeaderControls/SliceHeaderControls.test.tsx @@ -183,12 +183,6 @@ test('Should "export to Excel"', async () => { expect(props.exportXLSX).toBeCalledWith(371); }); -test('Should not show "Download" if slice is filter box', () => { - const props = createProps('filter_box'); - renderWrapper(props); - expect(screen.queryByText('Download')).not.toBeInTheDocument(); -}); - test('Export full CSV is under featureflag', async () => { // @ts-ignore global.featureFlags = { diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx b/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx index 17d5bdc83e0..305bc384345 100644 --- a/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx @@ -489,7 +489,7 @@ const SliceHeaderControls = (props: SliceHeaderControlsPropsWithRouter) => { )} - {props.slice.viz_type !== 'filter_box' && props.supersetCanCSV && ( + {props.supersetCanCSV && ( { {t('Export to Excel')} - {props.slice.viz_type !== 'filter_box' && - isFeatureEnabled(FeatureFlag.ALLOW_FULL_CSV_EXPORT) && + {isFeatureEnabled(FeatureFlag.ALLOW_FULL_CSV_EXPORT) && props.supersetCanCSV && isTable && ( <> diff --git a/superset-frontend/src/dashboard/components/filterscope/FilterScopeSelector.jsx b/superset-frontend/src/dashboard/components/filterscope/FilterScopeSelector.jsx index 1b146148682..3fc6775bdb5 100644 --- a/superset-frontend/src/dashboard/components/filterscope/FilterScopeSelector.jsx +++ b/superset-frontend/src/dashboard/components/filterscope/FilterScopeSelector.jsx @@ -30,7 +30,7 @@ import getKeyForFilterScopeTree from 'src/dashboard/util/getKeyForFilterScopeTre import getSelectedChartIdForFilterScopeTree from 'src/dashboard/util/getSelectedChartIdForFilterScopeTree'; import getFilterScopeFromNodesTree from 'src/dashboard/util/getFilterScopeFromNodesTree'; import getRevertedFilterScope from 'src/dashboard/util/getRevertedFilterScope'; -import { getChartIdsInFilterBoxScope } from 'src/dashboard/util/activeDashboardFilters'; +import { getChartIdsInFilterScope } from 'src/dashboard/util/activeDashboardFilters'; import { getChartIdAndColumnFromFilterKey, getDashboardFilterKey, @@ -277,12 +277,6 @@ const ScopeSelector = styled.div` } .multi-edit-mode { - &.filter-scope-pane { - .rct-node.rct-node-leaf .filter-scope-type.filter_box { - display: none; - } - } - .filter-field-item { padding: 0 ${theme.gridUnit * 4}px 0 ${theme.gridUnit * 12}px; margin-left: ${theme.gridUnit * -12}px; @@ -367,9 +361,8 @@ export default class FilterScopeSelector extends React.PureComponent { selectedChartId: filterId, }); const expanded = getFilterScopeParentNodes(nodes, 1); - // force display filter_box chart as unchecked, but show checkbox as disabled const chartIdsInFilterScope = ( - getChartIdsInFilterBoxScope({ + getChartIdsInFilterScope({ filterScope: dashboardFilters[filterId].scopes[columnName], }) || [] ).filter(id => id !== filterId); diff --git a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx index a99061c7071..a6046539142 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx @@ -40,9 +40,6 @@ import SliceHeader from '../SliceHeader'; import MissingChart from '../MissingChart'; import { slicePropShape, chartPropShape } from '../../util/propShapes'; -import { isFilterBox } from '../../util/activeDashboardFilters'; -import getFilterValuesByFilterId from '../../util/getFilterValuesByFilterId'; - const propTypes = { id: PropTypes.number.isRequired, componentId: PropTypes.string.isRequired, @@ -100,7 +97,6 @@ const SHOULD_UPDATE_ON_PROP_CHANGES = Object.keys(propTypes).filter( prop => prop !== 'width' && prop !== 'height' && prop !== 'isComponentVisible', ); -const OVERFLOWABLE_VIZ_TYPES = new Set(['filter_box']); const DEFAULT_HEADER_HEIGHT = 22; const ChartWrapper = styled.div` @@ -421,13 +417,7 @@ class Chart extends React.Component { const cachedDttm = // eslint-disable-next-line camelcase queriesResponse?.map(({ cached_dttm }) => cached_dttm) || []; - const isOverflowable = OVERFLOWABLE_VIZ_TYPES.has(slice.viz_type); - const initialValues = isFilterBox(id) - ? getFilterValuesByFilterId({ - activeFilters: filters, - filterId: id, - }) - : {}; + const initialValues = {}; return ( )} - + {isLoading && ( - (type === TAB_TYPE || type === CHART_TYPE || type === DASHBOARD_ROOT_TYPE) && - (!charts || charts[meta?.chartId]?.form_data?.viz_type !== 'filter_box'); +export const isShowTypeInTree = ({ type }: LayoutItem) => + type === TAB_TYPE || type === CHART_TYPE || type === DASHBOARD_ROOT_TYPE; export const getNodeTitle = (node: LayoutItem) => node?.meta?.sliceNameOverride ?? @@ -51,7 +50,7 @@ export const buildTree = ( if ( node && treeItem && - isShowTypeInTree(node, charts) && + isShowTypeInTree(node) && node.type !== DASHBOARD_ROOT_TYPE && validNodes?.includes?.(node.id) ) { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/selectors.ts b/superset-frontend/src/dashboard/components/nativeFilters/selectors.ts index 9247538a5d4..a8bfafd8341 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/selectors.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/selectors.ts @@ -31,7 +31,7 @@ import { QueryFormColumn, } from '@superset-ui/core'; import { TIME_FILTER_MAP } from 'src/explore/constants'; -import { getChartIdsInFilterBoxScope } from 'src/dashboard/util/activeDashboardFilters'; +import { getChartIdsInFilterScope } from 'src/dashboard/util/activeDashboardFilters'; import { ChartConfiguration, DashboardLayout, @@ -130,7 +130,7 @@ const selectIndicatorsForChartFromFilter = ( return Object.keys(filter.columns) .filter(column => - getChartIdsInFilterBoxScope({ + getChartIdsInFilterScope({ filterScope: filter.scopes[column], }).includes(chartId), ) diff --git a/superset-frontend/src/dashboard/containers/Dashboard.ts b/superset-frontend/src/dashboard/containers/Dashboard.ts index 5f9b29b95dd..ba91d748dab 100644 --- a/superset-frontend/src/dashboard/containers/Dashboard.ts +++ b/superset-frontend/src/dashboard/containers/Dashboard.ts @@ -54,11 +54,10 @@ function mapStateToProps(state: RootState) { dashboardInfo, dashboardState, datasources, - // filters prop: a map structure for all the active filter_box's values and scope in this dashboard, + // filters prop: a map structure for all the active filter's values and scope in this dashboard, // for each filter field. map key is [chartId_column] // When dashboard is first loaded into browser, // its value is from preselect_filters that dashboard owner saved in dashboard's meta data - // When user start interacting with dashboard, it will be user picked values from all filter_box activeFilters: { ...getActiveFilters(), ...getAllActiveFilters({ diff --git a/superset-frontend/src/dashboard/reducers/dashboardFilters.js b/superset-frontend/src/dashboard/reducers/dashboardFilters.js index d31af825717..a971df7d6a4 100644 --- a/superset-frontend/src/dashboard/reducers/dashboardFilters.js +++ b/superset-frontend/src/dashboard/reducers/dashboardFilters.js @@ -18,17 +18,13 @@ */ /* eslint-disable camelcase */ import { - ADD_FILTER, - REMOVE_FILTER, CHANGE_FILTER, UPDATE_DIRECT_PATH_TO_FILTER, UPDATE_LAYOUT_COMPONENTS, UPDATE_DASHBOARD_FILTERS_SCOPE, } from '../actions/dashboardFilters'; import { HYDRATE_DASHBOARD } from '../actions/hydrate'; -import { TIME_RANGE } from '../../visualizations/FilterBox/FilterBox'; import { DASHBOARD_ROOT_ID } from '../util/constants'; -import getFilterConfigsFromFormdata from '../util/getFilterConfigsFromFormdata'; import { buildActiveFilters } from '../util/activeDashboardFilters'; import { getChartIdAndColumnFromFilterKey } from '../util/getDashboardFilterKey'; @@ -50,41 +46,10 @@ export const dashboardFilter = { scopes: {}, }; -const CHANGE_FILTER_VALUE_ACTIONS = [ADD_FILTER, REMOVE_FILTER, CHANGE_FILTER]; +const CHANGE_FILTER_VALUE_ACTIONS = [CHANGE_FILTER]; export default function dashboardFiltersReducer(dashboardFilters = {}, action) { const actionHandlers = { - [ADD_FILTER]() { - const { chartId, component, form_data } = action; - const { columns, labels } = getFilterConfigsFromFormdata(form_data); - const scopes = Object.keys(columns).reduce( - (map, column) => ({ - ...map, - [column]: DASHBOARD_FILTER_SCOPE_GLOBAL, - }), - {}, - ); - const directPathToFilter = component - ? (component.parents || []).slice().concat(component.id) - : []; - - const newFilter = { - ...dashboardFilter, - chartId, - componentId: component.id, - datasourceId: form_data.datasource, - filterName: component.meta.sliceName, - directPathToFilter, - columns, - labels, - scopes, - isInstantFilter: !!form_data.instant_filtering, - isDateFilter: Object.keys(columns).includes(TIME_RANGE), - }; - - return newFilter; - }, - [CHANGE_FILTER](state) { const { newSelectedValues, merge } = action; const updatedColumns = Object.keys(newSelectedValues).reduce( @@ -155,13 +120,6 @@ export default function dashboardFiltersReducer(dashboardFilters = {}, action) { buildActiveFilters({ dashboardFilters: updatedFilters }); return updatedFilters; } - if (action.type === REMOVE_FILTER) { - const { chartId } = action; - const { [chartId]: deletedFilter, ...updatedFilters } = dashboardFilters; - buildActiveFilters({ dashboardFilters: updatedFilters }); - - return updatedFilters; - } if (action.type === HYDRATE_DASHBOARD) { return action.data.dashboardFilters; } diff --git a/superset-frontend/src/dashboard/reducers/dashboardFilters.test.js b/superset-frontend/src/dashboard/reducers/dashboardFilters.test.js index 19527d2276e..a629e631937 100644 --- a/superset-frontend/src/dashboard/reducers/dashboardFilters.test.js +++ b/superset-frontend/src/dashboard/reducers/dashboardFilters.test.js @@ -18,8 +18,6 @@ */ /* eslint-disable camelcase */ import { - ADD_FILTER, - REMOVE_FILTER, CHANGE_FILTER, UPDATE_DASHBOARD_FILTERS_SCOPE, } from 'src/dashboard/actions/dashboardFilters'; @@ -27,10 +25,7 @@ import dashboardFiltersReducer, { DASHBOARD_FILTER_SCOPE_GLOBAL, } from 'src/dashboard/reducers/dashboardFilters'; import * as activeDashboardFilters from 'src/dashboard/util/activeDashboardFilters'; -import { - emptyFilters, - dashboardFilters, -} from 'spec/fixtures/mockDashboardFilters'; +import { dashboardFilters } from 'spec/fixtures/mockDashboardFilters'; import { sliceEntitiesForDashboard, filterId, @@ -44,35 +39,6 @@ describe('dashboardFilters reducer', () => { const directPathToFilter = (component.parents || []).slice(); directPathToFilter.push(component.id); - it('should add a new filter if it does not exist', () => { - expect( - dashboardFiltersReducer(emptyFilters, { - type: ADD_FILTER, - chartId: filterId, - component, - form_data, - }), - ).toEqual({ - [filterId]: { - chartId: filterId, - componentId: component.id, - directPathToFilter, - filterName: component.meta.sliceName, - isDateFilter: false, - isInstantFilter: !!form_data.instant_filtering, - columns: { - [column]: undefined, - }, - labels: { - [column]: column, - }, - scopes: { - [column]: DASHBOARD_FILTER_SCOPE_GLOBAL, - }, - }, - }); - }); - it('should overwrite a filter if merge is false', () => { expect( dashboardFiltersReducer(dashboardFilters, { @@ -139,15 +105,6 @@ describe('dashboardFilters reducer', () => { }); }); - it('should remove the filter if values are empty', () => { - expect( - dashboardFiltersReducer(dashboardFilters, { - type: REMOVE_FILTER, - chartId: filterId, - }), - ).toEqual({}); - }); - it('should buildActiveFilters on UPDATE_DASHBOARD_FILTERS_SCOPE', () => { const regionScope = { scope: ['TAB-1'], diff --git a/superset-frontend/src/dashboard/util/activeDashboardFilters.js b/superset-frontend/src/dashboard/util/activeDashboardFilters.js index 3369dc1c5be..ef6fd7f5e1e 100644 --- a/superset-frontend/src/dashboard/util/activeDashboardFilters.js +++ b/superset-frontend/src/dashboard/util/activeDashboardFilters.js @@ -25,7 +25,6 @@ import { import { CHART_TYPE } from './componentTypes'; import { DASHBOARD_FILTER_SCOPE_GLOBAL } from '../reducers/dashboardFilters'; -let allFilterBoxChartIds = []; let activeFilters = {}; let appliedFilterValuesByChart = {}; let allComponents = {}; @@ -35,13 +34,6 @@ export function getActiveFilters() { return activeFilters; } -// currently filter_box is a chart, -// when selecting filter scopes, they have to be out pulled out in a few places. -// after we make filter_box a dashboard build-in component, will not need this check anymore. -export function isFilterBox(chartId) { - return allFilterBoxChartIds.includes(chartId); -} - // this function is to find all filter values applied to a chart, // it goes through all active filters and their scopes. // return: { [column]: array of selected values } @@ -61,10 +53,10 @@ export function getAppliedFilterValues(chartId, filters) { return appliedFilterValuesByChart[chartId]; } -// Legacy - getChartIdsInFilterBoxScope is used only by -// components and functions related to filter box -// Please use src/dashboard/util/getChartIdsInFilterScope instead -export function getChartIdsInFilterBoxScope({ filterScope }) { +/** + * @deprecated Please use src/dashboard/util/getChartIdsInFilterScope instead + */ +export function getChartIdsInFilterScope({ filterScope }) { function traverse(chartIds = [], component = {}, immuneChartIds = []) { if (!component) { return; @@ -99,10 +91,6 @@ export function getChartIdsInFilterBoxScope({ filterScope }) { // values: array of selected values // scope: array of chartIds that applicable to the filter field. export function buildActiveFilters({ dashboardFilters = {}, components = {} }) { - allFilterBoxChartIds = Object.values(dashboardFilters).map( - filter => filter.chartId, - ); - // clear cache if (!isEmpty(components)) { allComponents = components; @@ -119,7 +107,7 @@ export function buildActiveFilters({ dashboardFilters = {}, components = {} }) { : columns[column] !== undefined ) { // remove filter itself - const scope = getChartIdsInFilterBoxScope({ + const scope = getChartIdsInFilterScope({ filterScope: scopes[column], }).filter(id => chartId !== id); diff --git a/superset-frontend/src/dashboard/util/getFilterScopeNodesTree.js b/superset-frontend/src/dashboard/util/getFilterScopeNodesTree.js index 92868f047e8..aed133b1f39 100644 --- a/superset-frontend/src/dashboard/util/getFilterScopeNodesTree.js +++ b/superset-frontend/src/dashboard/util/getFilterScopeNodesTree.js @@ -51,12 +51,7 @@ function traverse({ return { ...chartNode, - children: filterFields.map(filterField => ({ - value: `${currentNode.meta.chartId}:${filterField}`, - label: `${chartNode.label}`, - type: 'filter_box', - showCheckbox: false, - })), + children: [], }; } diff --git a/superset-frontend/src/dashboard/util/getFilterValuesByFilterId.js b/superset-frontend/src/dashboard/util/getFilterValuesByFilterId.js deleted file mode 100644 index 75f9c705eb4..00000000000 --- a/superset-frontend/src/dashboard/util/getFilterValuesByFilterId.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { getChartIdAndColumnFromFilterKey } from './getDashboardFilterKey'; - -// input: { [id_column1]: values, [id_column2]: values } -// output: { column1: values, column2: values } -export default function getFilterValuesByFilterId({ - activeFilters = {}, - filterId, -}) { - return Object.entries(activeFilters).reduce((map, entry) => { - const [filterKey, { values }] = entry; - const { chartId, column } = getChartIdAndColumnFromFilterKey(filterKey); - if (chartId === filterId) { - return { - ...map, - [column]: values, - }; - } - return map; - }, {}); -} diff --git a/superset-frontend/src/dashboard/util/getRevertedFilterScope.ts b/superset-frontend/src/dashboard/util/getRevertedFilterScope.ts index 9dac0583aac..d873b80d488 100644 --- a/superset-frontend/src/dashboard/util/getRevertedFilterScope.ts +++ b/superset-frontend/src/dashboard/util/getRevertedFilterScope.ts @@ -16,8 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -import { getChartIdAndColumnFromFilterKey } from './getDashboardFilterKey'; - interface FilterScopeMap { [key: string]: number[]; } @@ -44,19 +42,14 @@ export default function getRevertedFilterScope({ {}, ); - return filterFields.reduce((map, filterField) => { - const { chartId } = getChartIdAndColumnFromFilterKey(filterField); - // force display filter_box chart as unchecked, but show checkbox as disabled - const updatedCheckedIds = ( - checkedChartIdsByFilterField[filterField] || [] - ).filter(id => id !== chartId); - - return { + return filterFields.reduce( + (map, filterField) => ({ ...map, [filterField]: { ...filterScopeMap[filterField], - checked: updatedCheckedIds, + checked: checkedChartIdsByFilterField[filterField] || [], }, - }; - }, {}); + }), + {}, + ); } diff --git a/superset-frontend/src/dashboard/util/getSelectedChartIdForFilterScopeTree.js b/superset-frontend/src/dashboard/util/getSelectedChartIdForFilterScopeTree.js index cde72e35851..ac9bc065017 100644 --- a/superset-frontend/src/dashboard/util/getSelectedChartIdForFilterScopeTree.js +++ b/superset-frontend/src/dashboard/util/getSelectedChartIdForFilterScopeTree.js @@ -22,8 +22,6 @@ export default function getSelectedChartIdForFilterScopeTree({ activeFilterField, checkedFilterFields, }) { - // we don't apply filter on filter_box itself, so we will disable - // checkbox in filter scope selector. // this function returns chart id based on current filter scope selector local state: // 1. if in single-edit mode, return the chart id for selected filter field. // 2. if in multi-edit mode, if all filter fields are from same chart id, diff --git a/superset-frontend/src/dashboard/util/logging/childChartsDidLoad.js b/superset-frontend/src/dashboard/util/logging/childChartsDidLoad.js index 7cef9ae6dc5..a23958da0c4 100644 --- a/superset-frontend/src/dashboard/util/logging/childChartsDidLoad.js +++ b/superset-frontend/src/dashboard/util/logging/childChartsDidLoad.js @@ -24,14 +24,7 @@ export default function childChartsDidLoad({ chartQueries, layout, id }) { let minQueryStartTime = Infinity; const didLoad = chartIds.every(chartId => { const query = chartQueries[chartId] || {}; - - // filterbox's don't re-render, don't use stale update time - if (query.form_data && query.form_data.viz_type !== 'filter_box') { - minQueryStartTime = Math.min( - query.chartUpdateStartTime, - minQueryStartTime, - ); - } + minQueryStartTime = Math.min(query.chartUpdateStartTime, minQueryStartTime); return ['stopped', 'failed', 'rendered'].indexOf(query.chartStatus) > -1; }); diff --git a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.test.tsx b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.test.tsx index fdc31f78af5..96b0f21655d 100644 --- a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.test.tsx +++ b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.test.tsx @@ -24,9 +24,6 @@ import mockState from 'spec/fixtures/mockState'; import reducerIndex from 'spec/helpers/reducerIndex'; import { screen, render } from 'spec/helpers/testing-library'; import { initialState } from 'src/SqlLab/fixtures'; -import { dashboardFilters } from 'spec/fixtures/mockDashboardFilters'; -import { dashboardWithFilter } from 'spec/fixtures/mockDashboardLayout'; -import { buildActiveFilters } from './activeDashboardFilters'; import useFilterFocusHighlightStyles from './useFilterFocusHighlightStyles'; const TestComponent = ({ chartId }: { chartId: number }) => { @@ -185,64 +182,4 @@ describe('useFilterFocusHighlightStyles', () => { const styles = getComputedStyle(container); expect(parseFloat(styles.opacity)).toBe(1); }); - - it('should return unfocused styles if chart is not inside filter box scope', async () => { - buildActiveFilters({ - dashboardFilters, - components: dashboardWithFilter, - }); - - const chartId = 18; - const store = createMockStore({ - dashboardState: { - focusedFilterField: { - chartId, - column: 'test', - }, - }, - dashboardFilters: { - [chartId]: { - scopes: { - column: {}, - }, - }, - }, - }); - renderWrapper(20, store); - - const container = screen.getByTestId('test-component'); - - const styles = getComputedStyle(container); - expect(parseFloat(styles.opacity)).toBe(0.3); - }); - - it('should return focused styles if chart is inside filter box scope', async () => { - buildActiveFilters({ - dashboardFilters, - components: dashboardWithFilter, - }); - - const chartId = 18; - const store = createMockStore({ - dashboardState: { - focusedFilterField: { - chartId, - column: 'test', - }, - }, - dashboardFilters: { - [chartId]: { - scopes: { - column: {}, - }, - }, - }, - }); - renderWrapper(chartId, store); - - const container = screen.getByTestId('test-component'); - - const styles = getComputedStyle(container); - expect(parseFloat(styles.opacity)).toBe(1); - }); }); diff --git a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts index 8be43490ad3..f1f428240c1 100644 --- a/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts +++ b/superset-frontend/src/dashboard/util/useFilterFocusHighlightStyles.ts @@ -19,7 +19,7 @@ import { useTheme } from '@superset-ui/core'; import { useSelector } from 'react-redux'; -import { getChartIdsInFilterBoxScope } from 'src/dashboard/util/activeDashboardFilters'; +import { getChartIdsInFilterScope } from 'src/dashboard/util/activeDashboardFilters'; import { DashboardState, RootState } from 'src/dashboard/types'; const selectFocusedFilterScope = ( @@ -78,7 +78,7 @@ const useFilterFocusHighlightStyles = (chartId: number) => { } } else if ( chartId === focusedFilterScope?.chartId || - getChartIdsInFilterBoxScope({ + getChartIdsInFilterScope({ filterScope: focusedFilterScope?.scope, }).includes(chartId) ) { diff --git a/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx b/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx index 984b389a5c9..bc2d83a90a6 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx @@ -430,31 +430,27 @@ const ExploreChartPanel = ({ className="panel panel-default chart-container" showSplite={showSplite} > - {vizType === 'filter_box' ? ( - panelBody - ) : ( - - {panelBody} - - - )} + + {panelBody} + + {showDatasetModal && ( { datasetName: props.datasource?.name, action: this.canOverwriteSlice() ? 'overwrite' : 'saveas', isLoading: false, - vizType: props.form_data?.viz_type, dashboard: undefined, }; this.onDashboardChange = this.onDashboardChange.bind(this); @@ -383,32 +379,27 @@ class SaveModal extends React.Component { /> )} - {!( - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && - this.state.vizType === 'filter_box' - ) && ( - - - {t('Select')} - {t(' a dashboard OR ')} - {t('create')} - {t(' a new one')} -
- } - /> - - )} + + + {t('Select')} + {t(' a dashboard OR ')} + {t('create')} + {t(' a new one')} +
+ } + /> + {info && } {this.props.alert && ( { !this.state.newSliceName || !this.state.dashboard || (this.props.datasource?.type !== DatasourceType.Table && - !this.state.datasetName) || - (isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && - this.state.vizType === 'filter_box') + !this.state.datasetName) } onClick={() => this.saveOrOverwrite(true)} > diff --git a/superset-frontend/src/explore/components/controls/FilterBoxItemControl/FilterBoxItemControl.test.jsx b/superset-frontend/src/explore/components/controls/FilterBoxItemControl/FilterBoxItemControl.test.jsx deleted file mode 100644 index 4cf88645d75..00000000000 --- a/superset-frontend/src/explore/components/controls/FilterBoxItemControl/FilterBoxItemControl.test.jsx +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -/* eslint-disable no-unused-expressions */ -import React from 'react'; -import sinon from 'sinon'; -import { shallow } from 'enzyme'; - -import FilterBoxItemControl from 'src/explore/components/controls/FilterBoxItemControl'; -import FormRow from 'src/components/FormRow'; -import datasources from 'spec/fixtures/mockDatasource'; -import ControlPopover from '../ControlPopover/ControlPopover'; - -const defaultProps = { - label: 'some label', - datasource: datasources['7__table'], - onChange: sinon.spy(), -}; - -describe('FilterBoxItemControl', () => { - let wrapper; - let inst; - - const getWrapper = propOverrides => { - const props = { ...defaultProps, ...propOverrides }; - return shallow(); - }; - beforeEach(() => { - wrapper = getWrapper(); - inst = wrapper.instance(); - }); - - it('renders a Popover', () => { - expect(wrapper.find(ControlPopover)).toExist(); - }); - - it('renderForms does the job', () => { - const popover = shallow(inst.renderForm()); - expect(popover.find(FormRow)).toHaveLength(8); - expect(popover.find(FormRow).get(1).props.control.props.value).toEqual( - 'some label', - ); - }); - - it('convert type for single value filter_box', () => { - inst = getWrapper({ - datasource: { - columns: [ - { - column_name: 'SP_POP_TOTL', - description: null, - expression: null, - filterable: true, - groupby: true, - id: 312, - is_dttm: false, - type: 'FLOAT', - verbose_name: null, - }, - ], - metrics: [ - { - d3format: null, - description: null, - expression: 'sum("SP_POP_TOTL")', - id: 3, - metric_name: 'sum__SP_POP_TOTL', - verbose_name: null, - warning_text: null, - }, - ], - }, - }).instance(); - inst.setState({ - asc: true, - clearable: true, - column: 'SP_POP_TOTL', - defaultValue: 254454778, - metric: undefined, - multiple: false, - }); - inst.setState = sinon.spy(); - - inst.onControlChange('defaultValue', '1'); - expect(inst.setState.callCount).toBe(1); - expect(inst.setState.getCall(0).args[0]).toEqual({ defaultValue: 1 }); - - // user input is invalid for number type column - inst.onControlChange('defaultValue', 'abc'); - expect(inst.setState.callCount).toBe(2); - expect(inst.setState.getCall(1).args[0]).toEqual({ defaultValue: null }); - }); -}); diff --git a/superset-frontend/src/explore/components/controls/FilterBoxItemControl/FilterBoxItemControl.test.tsx b/superset-frontend/src/explore/components/controls/FilterBoxItemControl/FilterBoxItemControl.test.tsx deleted file mode 100644 index 4ad09e958cb..00000000000 --- a/superset-frontend/src/explore/components/controls/FilterBoxItemControl/FilterBoxItemControl.test.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { render, screen } from 'spec/helpers/testing-library'; -import userEvent from '@testing-library/user-event'; -import FilterBoxItemControl from '.'; - -const createProps = () => ({ - datasource: { - columns: [], - metrics: [], - }, - asc: true, - clearable: true, - multiple: true, - column: 'developer_type', - label: 'Developer Type', - metric: undefined, - searchAllOptions: false, - defaultValue: undefined, - onChange: jest.fn(), -}); - -test('Should render', () => { - const props = createProps(); - render(); - expect(screen.getByTestId('FilterBoxItemControl')).toBeInTheDocument(); - expect(screen.getByRole('button')).toBeInTheDocument(); -}); - -test('Should open modal', () => { - const props = createProps(); - render(); - userEvent.click(screen.getByRole('button')); - expect(screen.getByText('Filter configuration')).toBeInTheDocument(); - expect(screen.getByText('Column')).toBeInTheDocument(); - expect(screen.getByText('Label')).toBeInTheDocument(); - expect(screen.getByText('Default')).toBeInTheDocument(); - expect(screen.getByText('Sort metric')).toBeInTheDocument(); - expect(screen.getByText('Sort ascending')).toBeInTheDocument(); - expect(screen.getByText('Allow multiple selections')).toBeInTheDocument(); - expect(screen.getByText('Search all filter options')).toBeInTheDocument(); - expect(screen.getByText('Required')).toBeInTheDocument(); -}); diff --git a/superset-frontend/src/explore/components/controls/FilterBoxItemControl/index.jsx b/superset-frontend/src/explore/components/controls/FilterBoxItemControl/index.jsx deleted file mode 100644 index 4c8a367e352..00000000000 --- a/superset-frontend/src/explore/components/controls/FilterBoxItemControl/index.jsx +++ /dev/null @@ -1,295 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React from 'react'; -import PropTypes from 'prop-types'; -import { t } from '@superset-ui/core'; -import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls'; - -import FormRow from 'src/components/FormRow'; -import { Select } from 'src/components'; -import CheckboxControl from 'src/explore/components/controls/CheckboxControl'; -import TextControl from 'src/explore/components/controls/TextControl'; -import { FILTER_CONFIG_ATTRIBUTES } from 'src/explore/constants'; -import ControlPopover from '../ControlPopover/ControlPopover'; - -const INTEGRAL_TYPES = new Set([ - 'TINYINT', - 'SMALLINT', - 'INT', - 'INTEGER', - 'BIGINT', - 'LONG', -]); -const DECIMAL_TYPES = new Set([ - 'FLOAT', - 'DOUBLE', - 'REAL', - 'NUMERIC', - 'DECIMAL', - 'MONEY', -]); - -const propTypes = { - datasource: PropTypes.object.isRequired, - onChange: PropTypes.func, - asc: PropTypes.bool, - clearable: PropTypes.bool, - multiple: PropTypes.bool, - column: PropTypes.string, - label: PropTypes.string, - metric: PropTypes.string, - searchAllOptions: PropTypes.bool, - defaultValue: PropTypes.string, -}; - -const defaultProps = { - onChange: () => {}, - asc: true, - clearable: true, - multiple: true, - searchAllOptions: false, -}; - -const STYLE_WIDTH = { width: 350 }; - -export default class FilterBoxItemControl extends React.Component { - constructor(props) { - super(props); - const { - column, - metric, - asc, - clearable, - multiple, - searchAllOptions, - label, - defaultValue, - } = props; - this.state = { - column, - metric, - label, - asc, - clearable, - multiple, - searchAllOptions, - defaultValue, - }; - this.onChange = this.onChange.bind(this); - this.onControlChange = this.onControlChange.bind(this); - } - - onChange() { - this.props.onChange(this.state); - } - - onControlChange(attr, value) { - let typedValue = value; - const { column: selectedColumnName, multiple } = this.state; - if (value && !multiple && attr === FILTER_CONFIG_ATTRIBUTES.DEFAULT_VALUE) { - // if single value filter_box, - // convert input value string to the column's data type - const { datasource } = this.props; - const selectedColumn = datasource.columns.find( - col => col.column_name === selectedColumnName, - ); - - if (selectedColumn && selectedColumn.type) { - const type = selectedColumn.type.toUpperCase(); - if (type === 'BOOLEAN') { - typedValue = value === 'true'; - } else if (INTEGRAL_TYPES.has(type)) { - typedValue = Number.isNaN(Number(value)) ? null : parseInt(value, 10); - } else if (DECIMAL_TYPES.has(type)) { - typedValue = Number.isNaN(Number(value)) ? null : parseFloat(value); - } - } - } - this.setState({ [attr]: typedValue }, this.onChange); - } - - setType() {} - - textSummary() { - return this.state.column || 'N/A'; - } - - renderForm() { - return ( -
- col.column_name !== this.state.column) - .map(col => ({ - value: col.column_name, - label: col.column_name, - })) - .concat([ - { value: this.state.column, label: this.state.column }, - ])} - onChange={v => this.onControlChange('column', v)} - /> - } - /> - this.onControlChange('label', v)} - /> - } - /> - - this.onControlChange(FILTER_CONFIG_ATTRIBUTES.DEFAULT_VALUE, v) - } - /> - } - /> - m.metric_name !== this.state.metric) - .map(m => ({ - value: m.metric_name, - label: m.metric_name, - })) - .concat([ - { value: this.state.metric, label: this.state.metric }, - ])} - onChange={v => this.onControlChange('metric', v)} - /> - } - /> - this.onControlChange('asc', v)} - /> - } - /> - - this.onControlChange(FILTER_CONFIG_ATTRIBUTES.MULTIPLE, v) - } - /> - } - /> - - this.onControlChange( - FILTER_CONFIG_ATTRIBUTES.SEARCH_ALL_OPTIONS, - v, - ) - } - /> - } - /> - this.onControlChange('clearable', !v)} - /> - } - /> -
- ); - } - - renderPopover() { - return ( -
- {this.renderForm()} -
- ); - } - - render() { - return ( - - {this.textSummary()}{' '} - - - - - ); - } -} - -FilterBoxItemControl.propTypes = propTypes; -FilterBoxItemControl.defaultProps = defaultProps; diff --git a/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx b/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx index 8934ca9cf03..347b339481d 100644 --- a/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx +++ b/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx @@ -77,7 +77,6 @@ const DEFAULT_ORDER = [ 'echarts_timeseries_scatter', 'pie', 'mixed_timeseries', - 'filter_box', 'dist_bar', 'area', 'bar', diff --git a/superset-frontend/src/explore/components/controls/VizTypeControl/index.tsx b/superset-frontend/src/explore/components/controls/VizTypeControl/index.tsx index ec78b4267d8..bdfcf1e40a8 100644 --- a/superset-frontend/src/explore/components/controls/VizTypeControl/index.tsx +++ b/superset-frontend/src/explore/components/controls/VizTypeControl/index.tsx @@ -23,8 +23,6 @@ import { getChartMetadataRegistry, styled, SupersetTheme, - isFeatureEnabled, - FeatureFlag, } from '@superset-ui/core'; import { usePluginContext } from 'src/components/DynamicPlugins'; import Modal from 'src/components/Modal'; @@ -48,13 +46,6 @@ const bootstrapData = getBootstrapData(); const denyList: string[] = bootstrapData.common.conf.VIZ_TYPE_DENYLIST || []; const metadataRegistry = getChartMetadataRegistry(); -if ( - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && - !denyList.includes('filter_box') -) { - denyList.push('filter_box'); -} - export const VIZ_TYPE_CONTROL_TEST_ID = 'viz-type-control'; function VizSupportValidation({ vizType }: { vizType: string }) { diff --git a/superset-frontend/src/explore/components/controls/index.js b/superset-frontend/src/explore/components/controls/index.js index cba3c27f556..a5d65f77683 100644 --- a/superset-frontend/src/explore/components/controls/index.js +++ b/superset-frontend/src/explore/components/controls/index.js @@ -38,7 +38,6 @@ import ViewportControl from './ViewportControl'; import VizTypeControl from './VizTypeControl'; import MetricsControl from './MetricControl/MetricsControl'; import AdhocFilterControl from './FilterControl/AdhocFilterControl'; -import FilterBoxItemControl from './FilterBoxItemControl'; import ConditionalFormattingControl from './ConditionalFormattingControl'; import ContourControl from './ContourControl'; import DndColumnSelectControl, { @@ -78,7 +77,6 @@ const controlMap = { VizTypeControl, MetricsControl, AdhocFilterControl, - FilterBoxItemControl, ConditionalFormattingControl, XAxisSortControl, ContourControl, diff --git a/superset-frontend/src/pages/ChartCreation/index.tsx b/superset-frontend/src/pages/ChartCreation/index.tsx index 7a1ff43dc7a..f3a602dbc9d 100644 --- a/superset-frontend/src/pages/ChartCreation/index.tsx +++ b/superset-frontend/src/pages/ChartCreation/index.tsx @@ -20,8 +20,6 @@ import React, { ReactNode } from 'react'; import rison from 'rison'; import querystring from 'query-string'; import { - isFeatureEnabled, - FeatureFlag, isDefined, JsonResponse, styled, @@ -64,13 +62,6 @@ const ELEMENTS_EXCEPT_VIZ_GALLERY = ESTIMATED_NAV_HEIGHT + 250; const bootstrapData = getBootstrapData(); const denyList: string[] = bootstrapData.common.conf.VIZ_TYPE_DENYLIST || []; -if ( - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && - !denyList.includes('filter_box') -) { - denyList.push('filter_box'); -} - const StyledContainer = styled.div` ${({ theme }) => ` flex: 1 1 auto; diff --git a/superset-frontend/src/utils/localStorageHelpers.ts b/superset-frontend/src/utils/localStorageHelpers.ts index beb5ed10147..12fba5b94c9 100644 --- a/superset-frontend/src/utils/localStorageHelpers.ts +++ b/superset-frontend/src/utils/localStorageHelpers.ts @@ -30,7 +30,6 @@ export enum LocalStorageKeys { * TODO: Update all local storage keys to follow the new pattern. This is a breaking change, * and therefore should be done in a major release. */ - filter_box_transition_snoozed_at = 'filter_box_transition_snoozed_at', db = 'db', chart_split_sizes = 'chart_split_sizes', controls_width = 'controls_width', @@ -59,7 +58,6 @@ export enum LocalStorageKeys { } export type LocalStorageValues = { - filter_box_transition_snoozed_at: Record; db: object | null; chart_split_sizes: [number, number]; controls_width: number; diff --git a/superset-frontend/src/utils/urlUtils.ts b/superset-frontend/src/utils/urlUtils.ts index 07c8ad55007..91c0ae801cb 100644 --- a/superset-frontend/src/utils/urlUtils.ts +++ b/superset-frontend/src/utils/urlUtils.ts @@ -172,7 +172,7 @@ export function getDashboardPermalink({ */ anchor?: string; }) { - // only encode filter box state if non-empty + // only encode filter state if non-empty return getPermalink(`/api/v1/dashboard/${dashboardId}/permalink`, { urlParams: getDashboardUrlParams(), dataMask, diff --git a/superset-frontend/src/visualizations/FilterBox/FilterBox.jsx b/superset-frontend/src/visualizations/FilterBox/FilterBox.jsx deleted file mode 100644 index a2b2a9a2829..00000000000 --- a/superset-frontend/src/visualizations/FilterBox/FilterBox.jsx +++ /dev/null @@ -1,480 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React from 'react'; -import PropTypes from 'prop-types'; -import { debounce } from 'lodash'; -import { max as d3Max } from 'd3-array'; -import { - AsyncCreatableSelect, - CreatableSelect, -} from 'src/components/DeprecatedSelect'; -import Button from 'src/components/Button'; -import { - css, - styled, - t, - SupersetClient, - ensureIsArray, - withTheme, -} from '@superset-ui/core'; -import { Global } from '@emotion/react'; - -import { - BOOL_FALSE_DISPLAY, - BOOL_TRUE_DISPLAY, - SLOW_DEBOUNCE, -} from 'src/constants'; -import { FormLabel } from 'src/components/Form'; -import DateFilterControl from 'src/explore/components/controls/DateFilterControl'; -import ControlRow from 'src/explore/components/ControlRow'; -import Control from 'src/explore/components/Control'; -import { controls } from 'src/explore/controls'; -import { getExploreUrl } from 'src/explore/exploreUtils'; -import OnPasteSelect from 'src/components/DeprecatedSelect/OnPasteSelect'; -import { - FILTER_CONFIG_ATTRIBUTES, - FILTER_OPTIONS_LIMIT, - TIME_FILTER_LABELS, - TIME_FILTER_MAP, -} from 'src/explore/constants'; - -// a shortcut to a map key, used by many components -export const TIME_RANGE = TIME_FILTER_MAP.time_range; - -const propTypes = { - chartId: PropTypes.number.isRequired, - origSelectedValues: PropTypes.object, - datasource: PropTypes.object.isRequired, - instantFiltering: PropTypes.bool, - filtersFields: PropTypes.arrayOf( - PropTypes.shape({ - field: PropTypes.string, - label: PropTypes.string, - }), - ), - filtersChoices: PropTypes.objectOf( - PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string, - text: PropTypes.string, - filter: PropTypes.string, - metric: PropTypes.number, - }), - ), - ), - onChange: PropTypes.func, - onFilterMenuOpen: PropTypes.func, - onFilterMenuClose: PropTypes.func, - showDateFilter: PropTypes.bool, - showSqlaTimeGrain: PropTypes.bool, - showSqlaTimeColumn: PropTypes.bool, -}; -const defaultProps = { - origSelectedValues: {}, - onChange: () => {}, - onFilterMenuOpen: () => {}, - onFilterMenuClose: () => {}, - showDateFilter: false, - showSqlaTimeGrain: false, - showSqlaTimeColumn: false, - instantFiltering: false, -}; - -const StyledFilterContainer = styled.div` - ${({ theme }) => ` - display: flex; - flex-direction: column; - margin-bottom: ${theme.gridUnit * 2 + 2}px; - - &:last-child { - margin-bottom: 0; - } - - label { - display: flex; - font-weight: ${theme.typography.weights.bold}; - } - - .filter-badge-container { - width: 30px; - padding-right: ${theme.gridUnit * 2 + 2}px; - } - - .filter-badge-container + div { - width: 100%; - } - `} -`; - -/** - * @deprecated in version 3.0. - */ -class FilterBox extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - selectedValues: props.origSelectedValues, - // this flag is used by non-instant filter, to make the apply button enabled/disabled - hasChanged: false, - }; - this.debouncerCache = {}; - this.maxValueCache = {}; - this.changeFilter = this.changeFilter.bind(this); - this.onFilterMenuOpen = this.onFilterMenuOpen.bind(this); - this.onOpenDateFilterControl = this.onOpenDateFilterControl.bind(this); - this.onFilterMenuClose = this.onFilterMenuClose.bind(this); - } - - onFilterMenuOpen(column) { - return this.props.onFilterMenuOpen(this.props.chartId, column); - } - - onFilterMenuClose(column) { - return this.props.onFilterMenuClose(this.props.chartId, column); - } - - onOpenDateFilterControl() { - return this.onFilterMenuOpen(TIME_RANGE); - } - - onCloseDateFilterControl = () => this.onFilterMenuClose(TIME_RANGE); - - getControlData(controlName) { - const { selectedValues } = this.state; - const control = { - ...controls[controlName], // TODO: make these controls ('granularity_sqla', 'time_grain_sqla') accessible from getControlsForVizType. - name: controlName, - key: `control-${controlName}`, - value: selectedValues[TIME_FILTER_MAP[controlName]], - actions: { setControlValue: this.changeFilter }, - }; - const mapFunc = control.mapStateToProps; - return mapFunc ? { ...control, ...mapFunc(this.props) } : control; - } - - /** - * Get known max value of a column - */ - getKnownMax(key, choices) { - this.maxValueCache[key] = Math.max( - this.maxValueCache[key] || 0, - d3Max(choices || this.props.filtersChoices[key] || [], x => x.metric), - ); - return this.maxValueCache[key]; - } - - clickApply() { - const { selectedValues } = this.state; - this.setState({ hasChanged: false }, () => { - this.props.onChange(selectedValues, false); - }); - } - - changeFilter(filter, options) { - const fltr = TIME_FILTER_MAP[filter] || filter; - let vals = null; - if (options !== null) { - if (Array.isArray(options)) { - vals = options.map(opt => (typeof opt === 'string' ? opt : opt.value)); - } else if (Object.values(TIME_FILTER_MAP).includes(fltr)) { - vals = options.value ?? options; - } else { - // must use array member for legacy extra_filters's value - vals = ensureIsArray(options.value ?? options); - } - } - - this.setState( - prevState => ({ - selectedValues: { - ...prevState.selectedValues, - [fltr]: vals, - }, - hasChanged: true, - }), - () => { - if (this.props.instantFiltering) { - this.props.onChange({ [fltr]: vals }, false); - } - }, - ); - } - - /** - * Generate a debounce function that loads options for a specific column - */ - debounceLoadOptions(key) { - if (!(key in this.debouncerCache)) { - this.debouncerCache[key] = debounce((input, callback) => { - this.loadOptions(key, input).then(callback); - }, SLOW_DEBOUNCE); - } - return this.debouncerCache[key]; - } - - /** - * Transform select options, add bar background - */ - transformOptions(options, max) { - const maxValue = max === undefined ? d3Max(options, x => x.metric) : max; - return options.map(opt => { - const perc = Math.round((opt.metric / maxValue) * 100); - const color = 'lightgrey'; - const backgroundImage = `linear-gradient(to right, ${color}, ${color} ${perc}%, rgba(0,0,0,0) ${perc}%`; - const style = { backgroundImage }; - let label = opt.id; - if (label === true) { - label = BOOL_TRUE_DISPLAY; - } else if (label === false) { - label = BOOL_FALSE_DISPLAY; - } - return { value: opt.id, label, style }; - }); - } - - async loadOptions(key, inputValue = '') { - const input = inputValue.toLowerCase(); - const sortAsc = this.props.filtersFields.find(x => x.key === key).asc; - const formData = { - ...this.props.rawFormData, - adhoc_filters: inputValue - ? [ - { - clause: 'WHERE', - expressionType: 'SIMPLE', - subject: key, - operator: 'ILIKE', - comparator: `%${input}%`, - }, - ] - : null, - }; - - const { json } = await SupersetClient.get({ - url: getExploreUrl({ - formData, - endpointType: 'json', - method: 'GET', - }), - }); - const options = (json?.data?.[key] || []).filter(x => x.id); - if (!options || options.length === 0) { - return []; - } - if (input) { - // sort those starts with search query to front - options.sort((a, b) => { - const labelA = a.id.toLowerCase(); - const labelB = b.id.toLowerCase(); - const textOrder = labelB.startsWith(input) - labelA.startsWith(input); - return textOrder === 0 - ? (a.metric - b.metric) * (sortAsc ? 1 : -1) - : textOrder; - }); - } - return this.transformOptions(options, this.getKnownMax(key, options)); - } - - renderDateFilter() { - const { showDateFilter } = this.props; - const label = TIME_FILTER_LABELS.time_range; - if (showDateFilter) { - return ( -
-
- { - this.changeFilter(TIME_RANGE, newValue); - }} - onOpenDateFilterControl={this.onOpenDateFilterControl} - onCloseDateFilterControl={this.onCloseDateFilterControl} - value={this.state.selectedValues[TIME_RANGE] || 'No filter'} - endpoints={['inclusive', 'exclusive']} - /> -
-
- ); - } - return null; - } - - renderDatasourceFilters() { - const { showSqlaTimeGrain, showSqlaTimeColumn } = this.props; - const datasourceFilters = []; - const sqlaFilters = []; - if (showSqlaTimeGrain) sqlaFilters.push('time_grain_sqla'); - if (showSqlaTimeColumn) sqlaFilters.push('granularity_sqla'); - if (sqlaFilters.length) { - datasourceFilters.push( - ( - - ))} - />, - ); - } - return datasourceFilters; - } - - renderSelect(filterConfig) { - const { filtersChoices } = this.props; - const { selectedValues } = this.state; - this.debouncerCache = {}; - this.maxValueCache = {}; - - // Add created options to filtersChoices, even though it doesn't exist, - // or these options will exist in query sql but invisible to end user. - Object.keys(selectedValues) - .filter(key => key in filtersChoices) - .forEach(key => { - // empty values are ignored - if (!selectedValues[key]) { - return; - } - const choices = filtersChoices[key] || (filtersChoices[key] = []); - const choiceIds = new Set(choices.map(f => f.id)); - const selectedValuesForKey = Array.isArray(selectedValues[key]) - ? selectedValues[key] - : [selectedValues[key]]; - selectedValuesForKey - .filter(value => value !== null && !choiceIds.has(value)) - .forEach(value => { - choices.unshift({ - filter: key, - id: value, - text: value, - metric: 0, - }); - }); - }); - const { - key, - label, - [FILTER_CONFIG_ATTRIBUTES.MULTIPLE]: isMultiple, - [FILTER_CONFIG_ATTRIBUTES.DEFAULT_VALUE]: defaultValue, - [FILTER_CONFIG_ATTRIBUTES.CLEARABLE]: isClearable, - [FILTER_CONFIG_ATTRIBUTES.SEARCH_ALL_OPTIONS]: searchAllOptions, - } = filterConfig; - const data = filtersChoices[key] || []; - let value = selectedValues[key] || null; - - // Assign default value if required - if (value === undefined && defaultValue) { - // multiple values are separated by semicolons - value = isMultiple ? defaultValue.split(';') : defaultValue; - } - - return ( - { - // avoid excessive re-renders - if (newValue !== value) { - this.changeFilter(key, newValue); - } - }} - // TODO try putting this back once react-select is upgraded - // onFocus={() => this.onFilterMenuOpen(key)} - onMenuOpen={() => this.onFilterMenuOpen(key)} - onBlur={() => this.onFilterMenuClose(key)} - onMenuClose={() => this.onFilterMenuClose(key)} - selectWrap={ - searchAllOptions && data.length >= FILTER_OPTIONS_LIMIT - ? AsyncCreatableSelect - : CreatableSelect - } - noResultsText={t('No results found')} - forceOverflow - /> - ); - } - - renderFilters() { - const { filtersFields = [] } = this.props; - return filtersFields.map(filterConfig => { - const { label, key } = filterConfig; - return ( - - {label} - {this.renderSelect(filterConfig)} - - ); - }); - } - - render() { - const { instantFiltering, width, height } = this.props; - const { zIndex, gridUnit } = this.props.theme; - return ( - <> - div:not(.alert) { - padding-top: 0; - } - - .filter_box { - padding: ${gridUnit * 2 + 2}px 0; - overflow: visible !important; - - &:hover { - z-index: ${zIndex.max}; - } - } - `} - /> -
- {this.renderDateFilter()} - {this.renderDatasourceFilters()} - {this.renderFilters()} - {!instantFiltering && ( - - )} -
- - ); - } -} - -FilterBox.propTypes = propTypes; -FilterBox.defaultProps = defaultProps; - -export default withTheme(FilterBox); diff --git a/superset-frontend/src/visualizations/FilterBox/FilterBox.test.jsx b/superset-frontend/src/visualizations/FilterBox/FilterBox.test.jsx deleted file mode 100644 index e37a4bf1c69..00000000000 --- a/superset-frontend/src/visualizations/FilterBox/FilterBox.test.jsx +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React from 'react'; -import { styledMount as mount } from 'spec/helpers/theming'; -import FilterBox from 'src/visualizations/FilterBox/FilterBox'; -import SelectControl from 'src/explore/components/controls/SelectControl'; - -describe('FilterBox', () => { - it('should only add defined non-predefined options to filtersChoices', () => { - const wrapper = mount( - , - ); - const inst = wrapper.find('FilterBox').instance(); - // choose a predefined value - inst.setState({ selectedValues: { name: ['John'] } }); - expect(inst.props.filtersChoices.name.length).toEqual(2); - // reset selection - inst.setState({ selectedValues: { name: null } }); - expect(inst.props.filtersChoices.name.length).toEqual(2); - // Add a new name - inst.setState({ selectedValues: { name: 'James' } }); - expect(inst.props.filtersChoices.name.length).toEqual(3); - }); - - it('should support granularity_sqla options', () => { - const wrapper = mount( - , - ); - - expect(wrapper.find(SelectControl).props().choices).toEqual( - expect.arrayContaining([ - ['created_on', 'created_on'], - ['changed_on', 'changed_on'], - ]), - ); - }); -}); diff --git a/superset-frontend/src/visualizations/FilterBox/FilterBoxChartPlugin.js b/superset-frontend/src/visualizations/FilterBox/FilterBoxChartPlugin.js deleted file mode 100644 index 774f7bdedff..00000000000 --- a/superset-frontend/src/visualizations/FilterBox/FilterBoxChartPlugin.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { t, ChartMetadata, ChartPlugin, ChartLabel } from '@superset-ui/core'; -import transformProps from './transformProps'; -import thumbnail from './images/thumbnail.png'; -import example1 from './images/example1.jpg'; -import example2 from './images/example2.jpg'; -import controlPanel from './controlPanel'; - -const metadata = new ChartMetadata({ - category: t('Tools'), - label: ChartLabel.DEPRECATED, - name: t('Filter box (legacy)'), - description: - t(`Chart component that lets you add a custom filter UI in your dashboard. When added to dashboard, a filter box lets users specify specific values or ranges to filter charts by. The charts that each filter box is applied to can be fine tuned as well in the dashboard view. - - Note that this plugin is being replaced with the new Filters feature that lives in the dashboard view itself. It's easier to use and has more capabilities!`), - exampleGallery: [{ url: example1 }, { url: example2 }], - thumbnail, - useLegacyApi: true, - tags: [t('Legacy'), t('Deprecated')], -}); - -/** - * @deprecated in version 3.0. - */ -export default class FilterBoxChartPlugin extends ChartPlugin { - constructor() { - super({ - controlPanel, - metadata, - transformProps, - loadChart: () => import('./FilterBox'), - }); - } -} diff --git a/superset-frontend/src/visualizations/FilterBox/controlPanel.jsx b/superset-frontend/src/visualizations/FilterBox/controlPanel.jsx deleted file mode 100644 index 60bb9c83af9..00000000000 --- a/superset-frontend/src/visualizations/FilterBox/controlPanel.jsx +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React from 'react'; -import { t } from '@superset-ui/core'; -import { sections } from '@superset-ui/chart-controls'; - -export default { - controlPanelSections: [ - sections.legacyTimeseriesTime, - { - label: t('Filters configuration'), - expanded: true, - controlSetRows: [ - [ - { - name: 'filter_configs', - config: { - type: 'CollectionControl', - label: t('Filters'), - description: t('Filter configuration for the filter box'), - validators: [], - controlName: 'FilterBoxItemControl', - mapStateToProps: ({ datasource }) => ({ datasource }), - }, - }, - ], - [
], - [ - { - name: 'date_filter', - config: { - type: 'CheckboxControl', - label: t('Date filter'), - default: true, - description: t('Whether to include a time filter'), - }, - }, - ], - [ - { - name: 'instant_filtering', - config: { - type: 'CheckboxControl', - label: t('Instant filtering'), - renderTrigger: true, - default: false, - description: t( - 'Check to apply filters instantly as they change instead of displaying [Apply] button', - ), - }, - }, - ], - [ - { - name: 'show_sqla_time_granularity', - config: { - type: 'CheckboxControl', - label: t('Show time grain dropdown'), - default: false, - description: t('Check to include time grain dropdown'), - }, - }, - ], - [ - { - name: 'show_sqla_time_column', - config: { - type: 'CheckboxControl', - label: t('Show time column'), - default: false, - description: t('Check to include time column dropdown'), - }, - }, - ], - ['adhoc_filters'], - ], - }, - ], - controlOverrides: { - adhoc_filters: { - label: t('Limit selector values'), - description: t( - 'These filters apply to the values available in the dropdowns', - ), - }, - }, -}; diff --git a/superset-frontend/src/visualizations/FilterBox/images/example1.jpg b/superset-frontend/src/visualizations/FilterBox/images/example1.jpg deleted file mode 100644 index cc109ee5aa38724a0aa7b2274a739a485b520859..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10921 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 diff --git a/superset-frontend/src/visualizations/FilterBox/images/example2.jpg b/superset-frontend/src/visualizations/FilterBox/images/example2.jpg deleted file mode 100644 index 17912d52f72cf29106303524e866766398587dea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16969 zcmeHu2T)YY*6s!rkRU;VWFK^d;f6Hx$m8O-d}&!tH0jqnXc;Y-Me?M)!l2aZ>_bl6WDox{DG3H5`cq) z14M&A0J{KKDtcI30)Vt;n1S|&obBs_73?B0A*3wDL?_h#liXY|F?v98ShuZzjO)jG66mT!LLks zh4=~~ArT<~0TC$?5itpv2(DZuBPF@|tNd$_U$_6d3;dH15)l6C@qd@F-vJ6j;1I_F z4~G@NrNF_Xz`?cvEZ|HpgIxK=n14$+xOkT?n^%YIO64E|QvUvW&((0wPjkAlZo4bdnS71>3͢v+m_#frE-kODuB~ru?(H8O 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 diff --git a/superset-frontend/src/visualizations/FilterBox/images/thumbnail.png b/superset-frontend/src/visualizations/FilterBox/images/thumbnail.png deleted file mode 100644 index be08f687a5b7a7ca4ff56204b5f358c90ae39898..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8550 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 diff --git a/superset-frontend/src/visualizations/FilterBox/transformProps.ts b/superset-frontend/src/visualizations/FilterBox/transformProps.ts deleted file mode 100644 index 59387edae1d..00000000000 --- a/superset-frontend/src/visualizations/FilterBox/transformProps.ts +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { FilterBoxChartProps } from './types'; - -const NOOP = () => {}; - -export default function transformProps(chartProps: FilterBoxChartProps) { - const { - datasource, - formData, - hooks, - initialValues, - queriesData, - rawDatasource = {}, - rawFormData, - width, - height, - } = chartProps; - const { - onAddFilter = NOOP, - onFilterMenuOpen = NOOP, - onFilterMenuClose = NOOP, - } = hooks; - const { - sliceId, - dateFilter, - instantFiltering, - showSqlaTimeColumn, - showSqlaTimeGranularity, - } = formData; - const { verboseMap = {} } = datasource; - const filterConfigs = formData.filterConfigs || []; - - const filtersFields = filterConfigs.map(flt => ({ - ...flt, - key: flt.column, - label: flt.label || verboseMap[flt.column] || flt.column, - })); - - return { - chartId: sliceId, - width, - height, - datasource: rawDatasource, - filtersChoices: queriesData[0].data, - filtersFields, - instantFiltering, - onChange: onAddFilter, - onFilterMenuOpen, - onFilterMenuClose, - origSelectedValues: initialValues || {}, - showDateFilter: dateFilter, - showSqlaTimeColumn, - showSqlaTimeGrain: showSqlaTimeGranularity, - // the original form data, needed for async select options - rawFormData, - }; -} diff --git a/superset-frontend/src/visualizations/FilterBox/types.ts b/superset-frontend/src/visualizations/FilterBox/types.ts deleted file mode 100644 index 316a29f9bbe..00000000000 --- a/superset-frontend/src/visualizations/FilterBox/types.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { ChartProps, Datasource } from '@superset-ui/core'; - -export interface FilterConfig { - column: string; - label: string; -} - -export type FilterBoxChartProps = ChartProps & { - datasource?: Datasource; - formData: ChartProps['formData'] & { filterConfigs: FilterConfig[] }; -}; diff --git a/superset-frontend/src/visualizations/presets/MainPreset.js b/superset-frontend/src/visualizations/presets/MainPreset.js index a8cc847c8b4..e96b528c9de 100644 --- a/superset-frontend/src/visualizations/presets/MainPreset.js +++ b/superset-frontend/src/visualizations/presets/MainPreset.js @@ -76,7 +76,6 @@ import { } from 'src/filters/components'; import { PivotTableChartPlugin as PivotTableChartPluginV2 } from '@superset-ui/plugin-chart-pivot-table'; import { HandlebarsChartPlugin } from '@superset-ui/plugin-chart-handlebars'; -import FilterBoxChartPlugin from '../FilterBox/FilterBoxChartPlugin'; import TimeTableChartPlugin from '../TimeTable'; export default class MainPreset extends Preset { @@ -98,7 +97,6 @@ export default class MainPreset extends Preset { new CountryMapChartPlugin().configure({ key: 'country_map' }), new DistBarChartPlugin().configure({ key: 'dist_bar' }), new EventFlowChartPlugin().configure({ key: 'event_flow' }), - new FilterBoxChartPlugin().configure({ key: 'filter_box' }), new EchartsFunnelChartPlugin().configure({ key: 'funnel' }), new EchartsTreemapChartPlugin().configure({ key: 'treemap_v2' }), new EchartsGaugeChartPlugin().configure({ key: 'gauge_chart' }), diff --git a/superset-frontend/webpack.config.js b/superset-frontend/webpack.config.js index 3399be3d608..db512b074f1 100644 --- a/superset-frontend/webpack.config.js +++ b/superset-frontend/webpack.config.js @@ -247,7 +247,6 @@ const config = { 'redux', 'react-redux', 'react-hot-loader', - 'react-select', 'react-sortable-hoc', 'react-table', 'react-ace', diff --git a/superset/cli/native_filters.py b/superset/cli/native_filters.py deleted file mode 100644 index 75df428e381..00000000000 --- a/superset/cli/native_filters.py +++ /dev/null @@ -1,398 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -import json -from copy import deepcopy -from textwrap import dedent - -import click -from click_option_group import optgroup, RequiredMutuallyExclusiveOptionGroup -from flask.cli import with_appcontext -from sqlalchemy import Column, ForeignKey, Integer, String, Table, Text -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import relationship - -from superset import db, is_feature_enabled - -Base = declarative_base() - - -dashboard_slices = Table( - "dashboard_slices", - Base.metadata, - Column("id", Integer, primary_key=True), - Column("dashboard_id", Integer, ForeignKey("dashboards.id")), - Column("slice_id", Integer, ForeignKey("slices.id")), -) - - -slice_user = Table( - "slice_user", - Base.metadata, - Column("id", Integer, primary_key=True), - Column("slice_id", Integer, ForeignKey("slices.id")), -) - - -class Dashboard(Base): # type: ignore # pylint: disable=too-few-public-methods - __tablename__ = "dashboards" - - id = Column(Integer, primary_key=True) - json_metadata = Column(Text) - slices = relationship("Slice", secondary=dashboard_slices, backref="dashboards") - position_json = Column() - - def __repr__(self) -> str: - return f"Dashboard<{self.id}>" - - -class Slice(Base): # type: ignore # pylint: disable=too-few-public-methods - __tablename__ = "slices" - - id = Column(Integer, primary_key=True) - datasource_id = Column(Integer) - params = Column(Text) - slice_name = Column(String(250)) - viz_type = Column(String(250)) - - def __repr__(self) -> str: - return f"Slice<{self.id}>" - - -@click.group() -def native_filters() -> None: - """ - Perform native filter operations. - """ - - -@native_filters.command() -@with_appcontext -@optgroup.group( - "Grouped options", - cls=RequiredMutuallyExclusiveOptionGroup, -) -@optgroup.option( - "--all", - "all_", - default=False, - help="Upgrade all dashboards", - is_flag=True, -) -@optgroup.option( - "--id", - "dashboard_ids", - help="Upgrade the specific dashboard. Can be supplied multiple times.", - multiple=True, - type=int, -) -def upgrade( - all_: bool, # pylint: disable=unused-argument - dashboard_ids: tuple[int, ...], -) -> None: - """ - Upgrade legacy filter-box charts to native dashboard filters. - """ - - # pylint: disable=import-outside-toplevel - from superset.utils.dashboard_filter_scopes_converter import ( - convert_filter_scopes_to_native_filters, - ) - - if not is_feature_enabled("DASHBOARD_NATIVE_FILTERS"): - click.echo("The 'DASHBOARD_NATIVE_FILTERS' feature needs to be enabled.") - return - - # Mapping between the CHART- and MARKDOWN- IDs. - mapping = {} - - for dashboard in ( # pylint: disable=too-many-nested-blocks - db.session.query(Dashboard) - .filter(*[Dashboard.id.in_(dashboard_ids)] if dashboard_ids else []) - .all() - ): - click.echo(f"Upgrading {str(dashboard)}") - - try: - json_metadata = json.loads(dashboard.json_metadata or "{}") - position_json = json.loads(dashboard.position_json or "{}") - - if "native_filter_migration" in json_metadata: - click.echo(f"{dashboard} has already been upgraded") - continue - - # Save the native and legacy filter configurations for recovery purposes. - json_metadata["native_filter_migration"] = { - key: deepcopy(json_metadata[key]) - for key in ( - "default_filters", - "filter_scopes", - "native_filter_configuration", - ) - if key in json_metadata - } - - filter_boxes_by_id = { - slc.id: slc for slc in dashboard.slices if slc.viz_type == "filter_box" - } - - # Convert the legacy filter configurations to native filters. - native_filter_configuration = json_metadata.setdefault( - "native_filter_configuration", - [], - ) - - native_filter_configuration.extend( - convert_filter_scopes_to_native_filters( - json_metadata, - position_json, - filter_boxes=list(filter_boxes_by_id.values()), - ), - ) - - # Remove the legacy filter configuration. - for key in ["default_filters", "filter_scopes"]: - json_metadata.pop(key, None) - - # Replace the filter-box charts with markdown elements. - for key, value in list(position_json.items()): # Immutable iteration - if ( - isinstance(value, dict) - and value["type"] == "CHART" - and (meta := value.get("meta")) - and meta["chartId"] in filter_boxes_by_id - ): - slc = filter_boxes_by_id[meta["chartId"]] - mapping[key] = key.replace("CHART-", "MARKDOWN-") - - value["id"] = mapping[key] - value["type"] = "MARKDOWN" - - meta["code"] = dedent( - f""" - ⚠ The {slc.slice_name} - filter-box chart has been migrated to a native filter. - - This placeholder markdown element can be safely removed after - verifying that the native filter(s) have been correctly applied, - otherwise ask an admin to revert the migration. - """ - ) - - # Save the filter-box info for recovery purposes. - meta["native_filter_migration"] = { - key: meta.pop(key) - for key in ( - "chartId", - "sliceName", - "sliceNameOverride", - ) - if key in meta - } - - position_json[mapping[key]] = value - del position_json[key] - - # Replace the relevant CHART- references. - for value in position_json.values(): - if isinstance(value, dict): - for relation in ["children", "parents"]: - if relation in value: - for idx, key in enumerate(value[relation]): - if key in mapping: - value[relation][idx] = mapping[key] - - # Remove the filter-box charts from the dashboard/slice mapping - dashboard.slices = [ - slc for slc in dashboard.slices if slc.viz_type != "filter_box" - ] - - dashboard.json_metadata = json.dumps(json_metadata) - dashboard.position_json = json.dumps(position_json) - except Exception: # pylint: disable=broad-except - click.echo(f"Unable to upgrade {str(dashboard)}") - - db.session.commit() - db.session.close() - - -@native_filters.command() -@with_appcontext -@optgroup.group( - "Grouped options", - cls=RequiredMutuallyExclusiveOptionGroup, -) -@optgroup.option( - "--all", - "all_", - default=False, - help="Downgrade all dashboards", - is_flag=True, -) -@optgroup.option( - "--id", - "dashboard_ids", - help="Downgrade the specific dashboard. Can be supplied multiple times.", - multiple=True, - type=int, -) -def downgrade( - all_: bool, # pylint: disable=unused-argument - dashboard_ids: tuple[int, ...], -) -> None: - """ - Downgrade native dashboard filters to legacy filter-box charts (where applicable). - """ - - # Mapping between the MARKDOWN- and CHART- IDs. - mapping = {} - - for dashboard in ( # pylint: disable=too-many-nested-blocks - db.session.query(Dashboard) - .filter(*[Dashboard.id.in_(dashboard_ids)] if dashboard_ids else []) - .all() - ): - click.echo(f"Downgrading {str(dashboard)}") - - try: - json_metadata = json.loads(dashboard.json_metadata or "{}") - position_json = json.loads(dashboard.position_json or "{}") - - if "native_filter_migration" not in json_metadata: - click.echo(f"{str(dashboard)} has not been upgraded") - continue - - # Restore the native and legacy filter configurations. - for key in ( - "default_filters", - "filter_scopes", - "native_filter_configuration", - ): - json_metadata.pop(key, None) - - json_metadata.update(json_metadata.pop("native_filter_migration")) - - # Replace the relevant markdown elements with filter-box charts. - slice_ids = set() - - for key, value in list(position_json.items()): # Immutable iteration - if ( - isinstance(value, dict) - and value["type"] == "MARKDOWN" - and (meta := value.get("meta")) - and "native_filter_migration" in meta - ): - meta.update(meta.pop("native_filter_migration")) - slice_ids.add(meta["chartId"]) - mapping[key] = key.replace("MARKDOWN-", "CHART-") - value["id"] = mapping[key] - del meta["code"] - value["type"] = "CHART" - position_json[mapping[key]] = value - del position_json[key] - - # Replace the relevant CHART- references. - for value in position_json.values(): - if isinstance(value, dict): - for relation in ["children", "parents"]: - if relation in value: - for idx, key in enumerate(value[relation]): - if key in mapping: - value[relation][idx] = mapping[key] - - # Restore the filter-box charts to the dashboard/slice mapping. - for slc in db.session.query(Slice).filter(Slice.id.in_(slice_ids)).all(): - dashboard.slices.append(slc) - - dashboard.json_metadata = json.dumps(json_metadata) - dashboard.position_json = json.dumps(position_json) - except Exception: # pylint: disable=broad-except - click.echo(f"Unable to downgrade {str(dashboard)}") - - db.session.commit() - db.session.close() - - -@native_filters.command() -@with_appcontext -@optgroup.group( - "Grouped options", - cls=RequiredMutuallyExclusiveOptionGroup, -) -@optgroup.option( - "--all", - "all_", - default=False, - help="Cleanup all dashboards", - is_flag=True, -) -@optgroup.option( - "--id", - "dashboard_ids", - help="Cleanup the specific dashboard. Can be supplied multiple times.", - multiple=True, - type=int, -) -def cleanup( - all_: bool, # pylint: disable=unused-argument - dashboard_ids: tuple[int, ...], -) -> None: - """ - Cleanup obsolete legacy filter-box charts and interim metadata. - - Note this operation is irreversible. - """ - - slice_ids: set[int] = set() - - # Cleanup the dashboard which contains legacy fields used for downgrading. - for dashboard in ( - db.session.query(Dashboard) - .filter(*[Dashboard.id.in_(dashboard_ids)] if dashboard_ids else []) - .all() - ): - click.echo(f"Cleaning up {str(dashboard)}") - - try: - json_metadata = json.loads(dashboard.json_metadata or "{}") - position_json = json.loads(dashboard.position_json or "{}") - - # Remove the saved filter configurations. - if "native_filter_migration" in json_metadata: - del json_metadata["native_filter_migration"] - dashboard.json_metadata = json.dumps(json_metadata) - - for value in position_json.values(): - if ( - isinstance(value, dict) - and value["type"] == "MARKDOWN" - and (meta := value.get("meta")) - and "native_filter_migration" in meta - ): - slice_ids.add(meta["native_filter_migration"]["chartId"]) - del meta["native_filter_migration"] - - dashboard.json_metadata = json.dumps(json_metadata) - dashboard.position_json = json.dumps(position_json) - except Exception: # pylint: disable=broad-except - click.echo(f"Unable to cleanup {str(dashboard)}") - - # Delete the obsolete filter-box charts associated with the dashboards. - db.session.query(slice_user).filter(slice_user.c.slice_id.in_(slice_ids)).delete() - db.session.query(Slice).filter(Slice.id.in_(slice_ids)).delete() - - db.session.commit() - db.session.close() diff --git a/superset/commands/chart/importers/v1/__init__.py b/superset/commands/chart/importers/v1/__init__.py index 783f300c074..f99fbb90089 100644 --- a/superset/commands/chart/importers/v1/__init__.py +++ b/superset/commands/chart/importers/v1/__init__.py @@ -83,6 +83,10 @@ def _import( # import charts with the correct parent ref for file_name, config in configs.items(): if file_name.startswith("charts/") and config["dataset_uuid"] in datasets: + # Ignore obsolete filter-box charts. + if config["viz_type"] == "filter_box": + continue + # update datasource id, type, and name dataset = datasets[config["dataset_uuid"]] config.update( diff --git a/superset/commands/dashboard/importers/v0.py b/superset/commands/dashboard/importers/v0.py index bd7aaa4c903..0bfd57c5a5d 100644 --- a/superset/commands/dashboard/importers/v0.py +++ b/superset/commands/dashboard/importers/v0.py @@ -29,6 +29,7 @@ from superset.commands.dataset.importers.v0 import import_dataset from superset.connectors.sqla.models import SqlaTable, SqlMetric, TableColumn from superset.exceptions import DashboardImportException +from superset.migrations.shared.native_filters import migrate_dashboard from superset.models.dashboard import Dashboard from superset.models.slice import Slice from superset.utils.dashboard_filter_scopes_converter import ( @@ -79,7 +80,7 @@ def import_chart( def import_dashboard( - # pylint: disable=too-many-locals,too-many-statements + # pylint: disable=too-many-branches,too-many-locals,too-many-statements dashboard_to_import: Dashboard, dataset_id_mapping: Optional[dict[int, int]] = None, import_time: Optional[int] = None, @@ -173,6 +174,7 @@ def alter_native_filters(dashboard: Dashboard) -> None: for slc in db.session.query(Slice).all() if "remote_id" in slc.params_dict } + new_slice_ids = [] for slc in slices: logger.info( "Importing slice %s from the dashboard: %s", @@ -181,6 +183,7 @@ def alter_native_filters(dashboard: Dashboard) -> None: ) remote_slc = remote_id_slice_map.get(slc.id) new_slc_id = import_chart(slc, remote_slc, import_time=import_time) + new_slice_ids.append(new_slc_id) old_to_new_slc_id_dict[slc.id] = new_slc_id # update json metadata that deals with slice ids new_slc_id_str = str(new_slc_id) @@ -249,22 +252,21 @@ def alter_native_filters(dashboard: Dashboard) -> None: alter_native_filters(dashboard_to_import) - new_slices = ( + if existing_dashboard: + existing_dashboard.override(dashboard_to_import) + else: + db.session.add(dashboard_to_import) + + dashboard = existing_dashboard or dashboard_to_import + dashboard.slices = ( db.session.query(Slice) .filter(Slice.id.in_(old_to_new_slc_id_dict.values())) .all() ) - - if existing_dashboard: - existing_dashboard.override(dashboard_to_import) - existing_dashboard.slices = new_slices - db.session.flush() - return existing_dashboard.id - - dashboard_to_import.slices = new_slices - db.session.add(dashboard_to_import) + # Migrate any filter-box charts to native dashboard filters. + migrate_dashboard(dashboard) db.session.flush() - return dashboard_to_import.id # type: ignore + return dashboard.id def decode_dashboards(o: dict[str, Any]) -> Any: diff --git a/superset/commands/dashboard/importers/v1/__init__.py b/superset/commands/dashboard/importers/v1/__init__.py index 2717650e9e3..62f5f393e96 100644 --- a/superset/commands/dashboard/importers/v1/__init__.py +++ b/superset/commands/dashboard/importers/v1/__init__.py @@ -37,7 +37,8 @@ from superset.dashboards.schemas import ImportV1DashboardSchema from superset.databases.schemas import ImportV1DatabaseSchema from superset.datasets.schemas import ImportV1DatasetSchema -from superset.models.dashboard import dashboard_slices +from superset.migrations.shared.native_filters import migrate_dashboard +from superset.models.dashboard import Dashboard, dashboard_slices class ImportDashboardsCommand(ImportModelsCommand): @@ -105,6 +106,7 @@ def _import( } # import charts with the correct parent ref + charts = [] chart_ids: dict[str, int] = {} for file_name, config in configs.items(): if ( @@ -121,6 +123,7 @@ def _import( config["query_context"] = None chart = import_chart(session, config, overwrite=False) + charts.append(chart) chart_ids[str(chart.uuid)] = chart.id # store the existing relationship between dashboards and charts @@ -129,11 +132,13 @@ def _import( ).fetchall() # import dashboards + dashboards: list[Dashboard] = [] dashboard_chart_ids: list[tuple[int, int]] = [] for file_name, config in configs.items(): if file_name.startswith("dashboards/"): config = update_id_refs(config, chart_ids, dataset_info) dashboard = import_dashboard(session, config, overwrite=overwrite) + dashboards.append(dashboard) for uuid in find_chart_uuids(config["position"]): if uuid not in chart_ids: break @@ -147,3 +152,12 @@ def _import( for (dashboard_id, chart_id) in dashboard_chart_ids ] session.execute(dashboard_slices.insert(), values) + + # Migrate any filter-box charts to native dashboard filters. + for dashboard in dashboards: + migrate_dashboard(dashboard) + + # Remove all obsolete filter-box charts. + for chart in charts: + if chart.viz_type == "filter_box": + session.delete(chart) diff --git a/superset/commands/importers/v1/assets.py b/superset/commands/importers/v1/assets.py index b6bc29e0fa4..fe9539ac80d 100644 --- a/superset/commands/importers/v1/assets.py +++ b/superset/commands/importers/v1/assets.py @@ -42,6 +42,7 @@ from superset.dashboards.schemas import ImportV1DashboardSchema from superset.databases.schemas import ImportV1DatabaseSchema from superset.datasets.schemas import ImportV1DatasetSchema +from superset.migrations.shared.native_filters import migrate_dashboard from superset.models.dashboard import dashboard_slices from superset.queries.saved_queries.schemas import ImportV1SavedQuerySchema @@ -106,6 +107,7 @@ def _import(session: Session, configs: dict[str, Any]) -> None: } # import charts + charts = [] chart_ids: dict[str, int] = {} for file_name, config in configs.items(): if file_name.startswith("charts/"): @@ -117,6 +119,7 @@ def _import(session: Session, configs: dict[str, Any]) -> None: if "query_context" in config: config["query_context"] = None chart = import_chart(session, config, overwrite=True) + charts.append(chart) chart_ids[str(chart.uuid)] = chart.id # import dashboards @@ -144,6 +147,14 @@ def _import(session: Session, configs: dict[str, Any]) -> None: ) session.execute(insert(dashboard_slices).values(dashboard_chart_ids)) + # Migrate any filter-box charts to native dashboard filters. + migrate_dashboard(dashboard) + + # Remove all obsolete filter-box charts. + for chart in charts: + if chart.viz_type == "filter_box": + session.delete(chart) + def run(self) -> None: self.validate() diff --git a/superset/migrations/shared/native_filters.py b/superset/migrations/shared/native_filters.py new file mode 100644 index 00000000000..c30c7d37892 --- /dev/null +++ b/superset/migrations/shared/native_filters.py @@ -0,0 +1,338 @@ +import json +from collections import defaultdict +from textwrap import dedent +from typing import Any + +from shortid import ShortId + +from superset.models.dashboard import Dashboard +from superset.models.slice import Slice +from superset.utils.dashboard_filter_scopes_converter import convert_filter_scopes + + +def convert_filter_scopes_to_native_filters( # pylint: disable=invalid-name,too-many-branches,too-many-locals,too-many-nested-blocks,too-many-statements + json_metadata: dict[str, Any], + position_json: dict[str, Any], + filter_boxes: list[Slice], +) -> list[dict[str, Any]]: + """ + Convert the legacy filter scopes et al. to the native filter configuration. + Dashboard filter scopes are implicitly defined where an undefined scope implies + no immunity, i.e., they apply to all applicable charts. The `convert_filter_scopes` + method provides an explicit definition by extracting the underlying filter-box + configurations. + + Hierarchical legacy filters are defined via non-exclusion of peer or children + filter-box charts whereas native hierarchical filters are defined via explicit + parental relationships, i.e., the inverse. + + :param json_metadata: The dashboard metadata + :param position_json: The dashboard layout + :param filter_boxes: The filter-box charts associated with the dashboard + :returns: The native filter configuration + :see: convert_filter_scopes + """ + + shortid = ShortId() + default_filters = json.loads(json_metadata.get("default_filters") or "{}") + filter_scopes = json_metadata.get("filter_scopes", {}) + filter_box_ids = {filter_box.id for filter_box in filter_boxes} + + filter_scope_by_key_and_field: dict[str, dict[str, dict[str, Any]]] = defaultdict( + dict + ) + + filter_by_key_and_field: dict[str, dict[str, dict[str, Any]]] = defaultdict(dict) + + # Dense representation of filter scopes, falling back to chart level filter configs + # if the respective filter scope is not defined at the dashboard level. + for filter_box in filter_boxes: + key = str(filter_box.id) + + filter_scope_by_key_and_field[key] = { + **( + convert_filter_scopes( + json_metadata, + filter_boxes=[filter_box], + ).get(filter_box.id, {}) + ), + **(filter_scopes.get(key, {})), + } + + # Construct the native filters. + for filter_box in filter_boxes: + key = str(filter_box.id) + params = json.loads(filter_box.params or "{}") + + for field, filter_scope in filter_scope_by_key_and_field[key].items(): + default = default_filters.get(key, {}).get(field) + + fltr: dict[str, Any] = { + "cascadeParentIds": [], + "id": f"NATIVE_FILTER-{shortid.generate()}", + "scope": { + "rootPath": filter_scope["scope"], + "excluded": [ + id_ + for id_ in filter_scope["immune"] + if id_ not in filter_box_ids + ], + }, + "type": "NATIVE_FILTER", + } + + if field == "__time_col" and params.get("show_sqla_time_column"): + fltr.update( + { + "filterType": "filter_timecolumn", + "name": "Time Column", + "targets": [{"datasetId": filter_box.datasource_id}], + } + ) + + if not default: + default = params.get("granularity_sqla") + + if default: + fltr["defaultDataMask"] = { + "extraFormData": {"granularity_sqla": default}, + "filterState": {"value": [default]}, + } + elif field == "__time_grain" and params.get("show_sqla_time_granularity"): + fltr.update( + { + "filterType": "filter_timegrain", + "name": "Time Grain", + "targets": [{"datasetId": filter_box.datasource_id}], + } + ) + + if not default: + default = params.get("time_grain_sqla") + + if default: + fltr["defaultDataMask"] = { + "extraFormData": {"time_grain_sqla": default}, + "filterState": {"value": [default]}, + } + elif field == "__time_range" and params.get("date_filter"): + fltr.update( + { + "filterType": "filter_time", + "name": "Time Range", + "targets": [{}], + } + ) + + if not default: + default = params.get("time_range") + + if default and default != "No filter": + fltr["defaultDataMask"] = { + "extraFormData": {"time_range": default}, + "filterState": {"value": default}, + } + else: + for config in params.get("filter_configs") or []: + if config["column"] == field: + fltr.update( + { + "controlValues": { + "defaultToFirstItem": False, + "enableEmptyFilter": not config.get( + "clearable", + True, + ), + "inverseSelection": False, + "multiSelect": config.get( + "multiple", + False, + ), + "searchAllOptions": config.get( + "searchAllOptions", + False, + ), + }, + "filterType": "filter_select", + "name": config.get("label") or field, + "targets": [ + { + "column": {"name": field}, + "datasetId": filter_box.datasource_id, + }, + ], + } + ) + + if "metric" in config: + fltr["sortMetric"] = config["metric"] + fltr["controlValues"]["sortAscending"] = config["asc"] + + if params.get("adhoc_filters"): + fltr["adhoc_filters"] = params["adhoc_filters"] + + # Pre-filter available values based on time range/column. + time_range = params.get("time_range") + + if time_range and time_range != "No filter": + fltr.update( + { + "time_range": time_range, + "granularity_sqla": params.get("granularity_sqla"), + } + ) + + if not default: + default = config.get("defaultValue") + + if default and config["multiple"]: + default = default.split(";") + + if default: + if not isinstance(default, list): + default = [default] + + fltr["defaultDataMask"] = { + "extraFormData": { + "filters": [ + { + "col": field, + "op": "IN", + "val": default, + } + ], + }, + "filterState": {"value": default}, + } + + break + + if "filterType" in fltr: + filter_by_key_and_field[key][field] = fltr + + # Ancestors of filter-box charts. + ancestors_by_id = defaultdict(set) + + for filter_box in filter_boxes: + for value in position_json.values(): + try: + if ( + isinstance(value, dict) + and value["type"] == "CHART" + and value["meta"]["chartId"] == filter_box.id + and value["parents"] # Misnomer as this the complete ancestry. + ): + ancestors_by_id[filter_box.id] = set(value["parents"]) + except KeyError: + pass + + # Wire up the hierarchical filters. + for this in filter_boxes: + for other in filter_boxes: + if ( + this != other + and any( # Immunity is at the chart rather than field level. + this.id not in filter_scope["immune"] + and set(filter_scope["scope"]) <= ancestors_by_id[this.id] + for filter_scope in filter_scope_by_key_and_field[ + str(other.id) + ].values() + ) + ): + for child in filter_by_key_and_field[str(this.id)].values(): + if child["filterType"] == "filter_select": + for parent in filter_by_key_and_field[str(other.id)].values(): + if ( + parent["filterType"] in {"filter_select", "filter_time"} + and parent["id"] not in child["cascadeParentIds"] + ): + child["cascadeParentIds"].append(parent["id"]) + + return sorted( + [ + fltr + for key in filter_by_key_and_field + for fltr in filter_by_key_and_field[key].values() + ], + key=lambda fltr: fltr["filterType"], + ) + + +def migrate_dashboard(dashboard: Dashboard) -> None: + """ + Convert the dashboard to use native filters. + + :param dashboard: The dashboard to convert + """ + + # Mapping between the CHART- and MARKDOWN- IDs. + mapping = {} + + try: + json_metadata = json.loads(dashboard.json_metadata or "{}") + position_json = json.loads(dashboard.position_json or "{}") + + filter_boxes_by_id = { + slc.id: slc for slc in dashboard.slices if slc.viz_type == "filter_box" + } + + # Convert the legacy filter configurations to native filters. + native_filter_configuration = json_metadata.setdefault( + "native_filter_configuration", + [], + ) + + native_filter_configuration.extend( + convert_filter_scopes_to_native_filters( + json_metadata, + position_json, + filter_boxes=list(filter_boxes_by_id.values()), + ), + ) + + # Remove the legacy filter configuration. + for key in ["default_filters", "filter_scopes"]: + json_metadata.pop(key, None) + + # Replace the filter-box charts with markdown elements. + for key, value in list(position_json.items()): # Immutable iteration + if ( + isinstance(value, dict) + and value["type"] == "CHART" + and (meta := value.get("meta")) + and meta["chartId"] in filter_boxes_by_id + ): + slc = filter_boxes_by_id[meta["chartId"]] + mapping[key] = key.replace("CHART-", "MARKDOWN-") + + value["id"] = mapping[key] + value["type"] = "MARKDOWN" + + meta["code"] = dedent( + f""" + ⚠ The {slc.slice_name} + filter-box chart has been migrated to a native filter. + """ + ) + + position_json[mapping[key]] = value + del position_json[key] + + # Replace the relevant CHART- references. + for value in position_json.values(): + if isinstance(value, dict): + for relation in ["children", "parents"]: + if relation in value: + for idx, key in enumerate(value[relation]): + if key in mapping: + value[relation][idx] = mapping[key] + + # Remove the filter-box charts from the dashboard/slice mapping. + dashboard.slices = [ + slc for slc in dashboard.slices if slc.viz_type != "filter_box" + ] + + dashboard.json_metadata = json.dumps(json_metadata) + dashboard.position_json = json.dumps(position_json) + except Exception: # pylint: disable=broad-except + print(f"Unable to upgrade {str(dashboard)}") diff --git a/superset/migrations/versions/2024-01-18_15-20_214f580d09c9_migrate_filter_boxes_to_native_filters.py b/superset/migrations/versions/2024-01-18_15-20_214f580d09c9_migrate_filter_boxes_to_native_filters.py new file mode 100644 index 00000000000..b54b60cb9db --- /dev/null +++ b/superset/migrations/versions/2024-01-18_15-20_214f580d09c9_migrate_filter_boxes_to_native_filters.py @@ -0,0 +1,85 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""migrate_filter_boxes_to_native_filters + +Revision ID: 214f580d09c9 +Revises: a32e0c4d8646 +Create Date: 2024-01-10 09:20:32.233912 + +""" +# revision identifiers, used by Alembic. +revision = "214f580d09c9" +down_revision = "a32e0c4d8646" + +from alembic import op +from sqlalchemy import Column, ForeignKey, Integer, String, Table, Text +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship + +from superset import db +from superset.migrations.shared.native_filters import migrate_dashboard +from superset.migrations.shared.utils import paginated_update + +Base = declarative_base() + +dashboard_slices = Table( + "dashboard_slices", + Base.metadata, + Column("id", Integer, primary_key=True), + Column("dashboard_id", Integer, ForeignKey("dashboards.id")), + Column("slice_id", Integer, ForeignKey("slices.id")), +) + + +class Dashboard(Base): # type: ignore # pylint: disable=too-few-public-methods + __tablename__ = "dashboards" + + id = Column(Integer, primary_key=True) + json_metadata = Column(Text) + slices = relationship("Slice", secondary=dashboard_slices, backref="dashboards") + position_json = Column() + + def __repr__(self) -> str: + return f"Dashboard<{self.id}>" + + +class Slice(Base): # type: ignore # pylint: disable=too-few-public-methods + __tablename__ = "slices" + + id = Column(Integer, primary_key=True) + datasource_id = Column(Integer) + params = Column(Text) + slice_name = Column(String(250)) + viz_type = Column(String(250)) + + def __repr__(self) -> str: + return f"Slice<{self.id}>" + + +def upgrade(): + session = db.Session(bind=op.get_bind()) + + for dashboard in paginated_update(session.query(Dashboard)): + migrate_dashboard(dashboard) + + # Delete the obsolete filter-box charts. + session.query(Slice).filter(Slice.viz_type == "filter_box").delete() + session.commit() + + +def downgrade(): + pass diff --git a/superset/utils/core.py b/superset/utils/core.py index b9c24076a4e..3a761cad1fc 100644 --- a/superset/utils/core.py +++ b/superset/utils/core.py @@ -1058,7 +1058,7 @@ def merge_extra_form_data(form_data: dict[str, Any]) -> None: def merge_extra_filters(form_data: dict[str, Any]) -> None: # extra_filters are temporary/contextual filters (using the legacy constructs) # that are external to the slice definition. We use those for dynamic - # interactive filters like the ones emitted by the "Filter Box" visualization. + # interactive filters. # Note extra_filters only support simple filters. form_data.setdefault("applied_time_extras", {}) adhoc_filters = form_data.get("adhoc_filters", []) diff --git a/superset/utils/dashboard_filter_scopes_converter.py b/superset/utils/dashboard_filter_scopes_converter.py index 6cabbbb315a..6a3ead7c144 100644 --- a/superset/utils/dashboard_filter_scopes_converter.py +++ b/superset/utils/dashboard_filter_scopes_converter.py @@ -19,8 +19,6 @@ from collections import defaultdict from typing import Any -from shortid import ShortId - from superset.models.slice import Slice logger = logging.getLogger(__name__) @@ -90,252 +88,3 @@ def copy_filter_scopes( if int(slice_id) in old_to_new_slc_id_dict ] return new_filter_scopes - - -def convert_filter_scopes_to_native_filters( # pylint: disable=invalid-name,too-many-branches,too-many-locals,too-many-nested-blocks,too-many-statements - json_metadata: dict[str, Any], - position_json: dict[str, Any], - filter_boxes: list[Slice], -) -> list[dict[str, Any]]: - """ - Convert the legacy filter scopes et al. to the native filter configuration. - - Dashboard filter scopes are implicitly defined where an undefined scope implies - no immunity, i.e., they apply to all applicable charts. The `convert_filter_scopes` - method provides an explicit definition by extracting the underlying filter-box - configurations. - - Hierarchical legacy filters are defined via non-exclusion of peer or children - filter-box charts whereas native hierarchical filters are defined via explicit - parental relationships, i.e., the inverse. - - :param json_metadata: The dashboard metadata - :param position_json: The dashboard layout - :param filter_boxes: The filter-box charts associated with the dashboard - :returns: The native filter configuration - :see: convert_filter_scopes - """ - - shortid = ShortId() - default_filters = json.loads(json_metadata.get("default_filters") or "{}") - filter_scopes = json_metadata.get("filter_scopes", {}) - filter_box_ids = {filter_box.id for filter_box in filter_boxes} - - filter_scope_by_key_and_field: dict[str, dict[str, dict[str, Any]]] = defaultdict( - dict - ) - - filter_by_key_and_field: dict[str, dict[str, dict[str, Any]]] = defaultdict(dict) - - # Dense representation of filter scopes, falling back to chart level filter configs - # if the respective filter scope is not defined at the dashboard level. - for filter_box in filter_boxes: - key = str(filter_box.id) - - filter_scope_by_key_and_field[key] = { - **( - convert_filter_scopes( - json_metadata, - filter_boxes=[filter_box], - ).get(filter_box.id, {}) - ), - **(filter_scopes.get(key, {})), - } - - # Construct the native filters. - for filter_box in filter_boxes: - key = str(filter_box.id) - params = json.loads(filter_box.params or "{}") - - for field, filter_scope in filter_scope_by_key_and_field[key].items(): - default = default_filters.get(key, {}).get(field) - - fltr: dict[str, Any] = { - "cascadeParentIds": [], - "id": f"NATIVE_FILTER-{shortid.generate()}", - "scope": { - "rootPath": filter_scope["scope"], - "excluded": [ - id_ - for id_ in filter_scope["immune"] - if id_ not in filter_box_ids - ], - }, - "type": "NATIVE_FILTER", - } - - if field == "__time_col" and params.get("show_sqla_time_column"): - fltr.update( - { - "filterType": "filter_timecolumn", - "name": "Time Column", - "targets": [{"datasetId": filter_box.datasource_id}], - } - ) - - if not default: - default = params.get("granularity_sqla") - - if default: - fltr["defaultDataMask"] = { - "extraFormData": {"granularity_sqla": default}, - "filterState": {"value": [default]}, - } - elif field == "__time_grain" and params.get("show_sqla_time_granularity"): - fltr.update( - { - "filterType": "filter_timegrain", - "name": "Time Grain", - "targets": [{"datasetId": filter_box.datasource_id}], - } - ) - - if not default: - default = params.get("time_grain_sqla") - - if default: - fltr["defaultDataMask"] = { - "extraFormData": {"time_grain_sqla": default}, - "filterState": {"value": [default]}, - } - elif field == "__time_range" and params.get("date_filter"): - fltr.update( - { - "filterType": "filter_time", - "name": "Time Range", - "targets": [{}], - } - ) - - if not default: - default = params.get("time_range") - - if default and default != "No filter": - fltr["defaultDataMask"] = { - "extraFormData": {"time_range": default}, - "filterState": {"value": default}, - } - else: - for config in params.get("filter_configs") or []: - if config["column"] == field: - fltr.update( - { - "controlValues": { - "defaultToFirstItem": False, - "enableEmptyFilter": not config.get( - "clearable", - True, - ), - "inverseSelection": False, - "multiSelect": config.get( - "multiple", - False, - ), - "searchAllOptions": config.get( - "searchAllOptions", - False, - ), - }, - "filterType": "filter_select", - "name": config.get("label") or field, - "targets": [ - { - "column": {"name": field}, - "datasetId": filter_box.datasource_id, - }, - ], - } - ) - - if "metric" in config: - fltr["sortMetric"] = config["metric"] - fltr["controlValues"]["sortAscending"] = config["asc"] - - if params.get("adhoc_filters"): - fltr["adhoc_filters"] = params["adhoc_filters"] - - # Pre-filter available values based on time range/column. - time_range = params.get("time_range") - - if time_range and time_range != "No filter": - fltr.update( - { - "time_range": time_range, - "granularity_sqla": params.get("granularity_sqla"), - } - ) - - if not default: - default = config.get("defaultValue") - - if default and config["multiple"]: - default = default.split(";") - - if default: - if not isinstance(default, list): - default = [default] - - fltr["defaultDataMask"] = { - "extraFormData": { - "filters": [ - { - "col": field, - "op": "IN", - "val": default, - } - ], - }, - "filterState": {"value": default}, - } - - break - - if "filterType" in fltr: - filter_by_key_and_field[key][field] = fltr - - # Ancestors of filter-box charts. - ancestors_by_id = defaultdict(set) - - for filter_box in filter_boxes: - for value in position_json.values(): - try: - if ( - isinstance(value, dict) - and value["type"] == "CHART" - and value["meta"]["chartId"] == filter_box.id - and value["parents"] # Misnomer as this the complete ancestry. - ): - ancestors_by_id[filter_box.id] = set(value["parents"]) - except KeyError: - pass - - # Wire up the hierarchical filters. - for this in filter_boxes: - for other in filter_boxes: - if ( - this != other - and any( # Immunity is at the chart rather than field level. - this.id not in filter_scope["immune"] - and set(filter_scope["scope"]) <= ancestors_by_id[this.id] - for filter_scope in filter_scope_by_key_and_field[ - str(other.id) - ].values() - ) - ): - for child in filter_by_key_and_field[str(this.id)].values(): - if child["filterType"] == "filter_select": - for parent in filter_by_key_and_field[str(other.id)].values(): - if ( - parent["filterType"] in {"filter_select", "filter_time"} - and parent["id"] not in child["cascadeParentIds"] - ): - child["cascadeParentIds"].append(parent["id"]) - - return sorted( - [ - fltr - for key in filter_by_key_and_field - for fltr in filter_by_key_and_field[key].values() - ], - key=lambda fltr: fltr["filterType"], - ) diff --git a/superset/viz.py b/superset/viz.py index 5738fabc939..ade52ee7be7 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -1568,85 +1568,6 @@ def get_data(self, df: pd.DataFrame) -> VizData: return data -class FilterBoxViz(BaseViz): - - """A multi filter, multi-choice filter box to make dashboards interactive""" - - query_context_factory: QueryContextFactory | None = None - viz_type = "filter_box" - verbose_name = _("Filters") - is_timeseries = False - credits = 'a Superset original' - cache_type = "get_data" - filter_row_limit = 1000 - - @deprecated(deprecated_in="3.0") - def query_obj(self) -> QueryObjectDict: - return {} - - @deprecated(deprecated_in="3.0") - def run_extra_queries(self) -> None: - query_obj = super().query_obj() - filters = self.form_data.get("filter_configs") or [] - query_obj["row_limit"] = self.filter_row_limit - self.dataframes = {} # pylint: disable=attribute-defined-outside-init - for flt in filters: - col = flt.get("column") - if not col: - raise QueryObjectValidationError( - _("Invalid filter configuration, please select a column") - ) - query_obj["groupby"] = [col] - metric = flt.get("metric") - query_obj["metrics"] = [metric] if metric else [] - asc = flt.get("asc") - if metric and asc is not None: - query_obj["orderby"] = [(metric, asc)] - self.get_query_context_factory().create( - datasource={"id": self.datasource.id, "type": self.datasource.type}, - form_data=self.form_data, - queries=[query_obj], - ).raise_for_access() - df = self.get_df_payload(query_obj=query_obj).get("df") - self.dataframes[col] = df - - @deprecated(deprecated_in="3.0") - def get_data(self, df: pd.DataFrame) -> VizData: - filters = self.form_data.get("filter_configs") or [] - data = {} - for flt in filters: - col = flt.get("column") - metric = flt.get("metric") - df = self.dataframes.get(col) - if df is not None and not df.empty: - if metric: - df = df.sort_values( - utils.get_metric_name(metric), ascending=flt.get("asc", False) - ) - data[col] = [ - {"id": row[0], "text": row[0], "metric": row[1]} - for row in df.itertuples(index=False) - ] - else: - df = df.sort_values(col, ascending=flt.get("asc", False)) - data[col] = [ - {"id": row[0], "text": row[0]} - for row in df.itertuples(index=False) - ] - else: - data[col] = [] - return data - - @deprecated(deprecated_in="3.0") - def get_query_context_factory(self) -> QueryContextFactory: - if self.query_context_factory is None: - # pylint: disable=import-outside-toplevel - from superset.common.query_context_factory import QueryContextFactory - - self.query_context_factory = QueryContextFactory() - return self.query_context_factory - - class ParallelCoordinatesViz(BaseViz): """Interactive parallel coordinate implementation diff --git a/tests/integration_tests/commands_test.py b/tests/integration_tests/commands_test.py index 6512a141bea..3215364e800 100644 --- a/tests/integration_tests/commands_test.py +++ b/tests/integration_tests/commands_test.py @@ -125,14 +125,9 @@ def test_import_assets(self): } assert json.loads(dashboard.json_metadata) == { "color_scheme": None, - "default_filters": "{}", "expanded_slices": {str(new_chart_id): True}, - "filter_scopes": { - str(new_chart_id): { - "region": {"scope": ["ROOT_ID"], "immune": [new_chart_id]} - }, - }, "import_time": 1604342885, + "native_filter_configuration": [], "refresh_frequency": 0, "remote_id": 7, "timed_refresh_immune_slices": [new_chart_id], diff --git a/tests/integration_tests/dashboards/commands_tests.py b/tests/integration_tests/dashboards/commands_tests.py index 175a8a3198d..6e9beab2492 100644 --- a/tests/integration_tests/dashboards/commands_tests.py +++ b/tests/integration_tests/dashboards/commands_tests.py @@ -551,14 +551,9 @@ def test_import_v1_dashboard(self, sm_g, utils_g): } assert json.loads(dashboard.json_metadata) == { "color_scheme": None, - "default_filters": "{}", "expanded_slices": {str(new_chart_id): True}, - "filter_scopes": { - str(new_chart_id): { - "region": {"scope": ["ROOT_ID"], "immune": [new_chart_id]} - }, - }, "import_time": 1604342885, + "native_filter_configuration": [], "refresh_frequency": 0, "remote_id": 7, "timed_refresh_immune_slices": [new_chart_id], diff --git a/tests/integration_tests/import_export_tests.py b/tests/integration_tests/import_export_tests.py index c195e3a4cb3..adc398e785f 100644 --- a/tests/integration_tests/import_export_tests.py +++ b/tests/integration_tests/import_export_tests.py @@ -381,7 +381,11 @@ def test_import_dashboard_1_slice(self): expected_dash, imported_dash, check_position=False, check_slugs=False ) self.assertEqual( - {"remote_id": 10002, "import_time": 1990}, + { + "remote_id": 10002, + "import_time": 1990, + "native_filter_configuration": [], + }, json.loads(imported_dash.json_metadata), ) @@ -411,7 +415,7 @@ def test_import_dashboard_2_slices(self): f"{e_slc.id}": True, f"{b_slc.id}": False, }, - # mocked filter_scope metadata + # mocked legacy filter_scope metadata "filter_scopes": { str(e_slc.id): { "region": {"scope": ["ROOT_ID"], "immune": [b_slc.id]} @@ -435,15 +439,11 @@ def test_import_dashboard_2_slices(self): expected_json_metadata = { "remote_id": 10003, "import_time": 1991, - "filter_scopes": { - str(i_e_slc.id): { - "region": {"scope": ["ROOT_ID"], "immune": [i_b_slc.id]} - } - }, "expanded_slices": { f"{i_e_slc.id}": True, f"{i_b_slc.id}": False, }, + "native_filter_configuration": [], } self.assertEqual( expected_json_metadata, json.loads(imported_dash.json_metadata) @@ -489,7 +489,11 @@ def test_import_override_dashboard_2_slices(self): expected_dash, imported_dash, check_position=False, check_slugs=False ) self.assertEqual( - {"remote_id": 10004, "import_time": 1992}, + { + "remote_id": 10004, + "import_time": 1992, + "native_filter_configuration": [], + }, json.loads(imported_dash.json_metadata), ) @@ -517,6 +521,7 @@ def test_import_new_dashboard_slice_reset_ownership(self): self.assertEqual(imported_slc.changed_by, gamma_user) self.assertEqual(imported_slc.owners, [gamma_user]) + @pytest.mark.skip def test_import_override_dashboard_slice_reset_ownership(self): admin_user = security_manager.find_user(username="admin") self.assertTrue(admin_user) @@ -539,7 +544,6 @@ def test_import_override_dashboard_slice_reset_ownership(self): # re-import with another user shouldn't change the permissions g.user = admin_user - dash_with_1_slice = self._create_dashboard_for_import(id_=10300) imported_dash_id = import_dashboard(dash_with_1_slice) diff --git a/tests/integration_tests/utils_tests.py b/tests/integration_tests/utils_tests.py index ddd0b0caf43..bdbb912eecc 100644 --- a/tests/integration_tests/utils_tests.py +++ b/tests/integration_tests/utils_tests.py @@ -759,7 +759,7 @@ def test_merge_extra_filters_with_no_extras(self): def test_merge_extra_filters_with_unset_legacy_time_range(self): """ - Make sure native filter is applied if filter box time range is unset. + Make sure native filter is applied if filter time range is unset. """ form_data = { "time_range": "Last 10 days", @@ -778,28 +778,6 @@ def test_merge_extra_filters_with_unset_legacy_time_range(self): }, ) - def test_merge_extra_filters_with_conflicting_time_ranges(self): - """ - Make sure filter box takes precedence if both native filter and filter box - time ranges are set. - """ - form_data = { - "time_range": "Last 10 days", - "extra_filters": [{"col": "__time_range", "op": "==", "val": "Last week"}], - "extra_form_data": { - "time_range": "Last year", - }, - } - merge_extra_filters(form_data) - self.assertEqual( - form_data, - { - "time_range": "Last week", - "applied_time_extras": {"__time_range": "Last week"}, - "adhoc_filters": [], - }, - ) - def test_merge_extra_filters_with_extras(self): form_data = { "time_range": "Last 10 days", diff --git a/tests/integration_tests/viz_tests.py b/tests/integration_tests/viz_tests.py index c4c11df9d81..5c7a494d878 100644 --- a/tests/integration_tests/viz_tests.py +++ b/tests/integration_tests/viz_tests.py @@ -1105,70 +1105,3 @@ def test_apply_rolling_without_data(self): ) with pytest.raises(QueryObjectValidationError): test_viz.apply_rolling(df) - - -class TestFilterBoxViz(SupersetTestCase): - def test_get_data(self): - form_data = { - "filter_configs": [ - {"column": "value1", "metric": "metric1"}, - {"column": "value2", "metric": "metric2", "asc": True}, - {"column": "value3"}, - {"column": "value4", "asc": True}, - {"column": "value5"}, - {"column": "value6"}, - ], - } - datasource = self.get_datasource_mock() - test_viz = viz.FilterBoxViz(datasource, form_data) - test_viz.dataframes = { - "value1": pd.DataFrame( - data=[ - {"value1": "v1", "metric1": 1}, - {"value1": "v2", "metric1": 2}, - ] - ), - "value2": pd.DataFrame( - data=[ - {"value2": "v3", "metric2": 3}, - {"value2": "v4", "metric2": 4}, - ] - ), - "value3": pd.DataFrame( - data=[ - {"value3": "v5"}, - {"value3": "v6"}, - ] - ), - "value4": pd.DataFrame( - data=[ - {"value4": "v7"}, - {"value4": "v8"}, - ] - ), - "value5": pd.DataFrame(), - } - - df = pd.DataFrame() - data = test_viz.get_data(df) - expected = { - "value1": [ - {"id": "v2", "text": "v2", "metric": 2}, - {"id": "v1", "text": "v1", "metric": 1}, - ], - "value2": [ - {"id": "v3", "text": "v3", "metric": 3}, - {"id": "v4", "text": "v4", "metric": 4}, - ], - "value3": [ - {"id": "v6", "text": "v6"}, - {"id": "v5", "text": "v5"}, - ], - "value4": [ - {"id": "v7", "text": "v7"}, - {"id": "v8", "text": "v8"}, - ], - "value5": [], - "value6": [], - } - self.assertEqual(expected, data) From a84d86fe264f6b3b1ea51545e31acbbc559c1805 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Fri, 19 Jan 2024 11:39:04 -0300 Subject: [PATCH 02/39] refactor: Removes the deprecated redirect endpoint (#26377) --- RESOURCES/STANDARD_ROLES.md | 1 - UPDATING.md | 1 + .../components/gridComponents/Tabs.test.jsx | 3 - superset/initialization/__init__.py | 2 - ...01-19_10-03_e863403c0c50_drop_url_table.py | 45 +++++++++++ superset/models/core.py | 8 -- superset/views/__init__.py | 1 - superset/views/redirects.py | 74 ------------------- superset/views/utils.py | 17 +---- tests/integration_tests/core_tests.py | 11 --- .../integration_tests/tags/commands_tests.py | 1 + 11 files changed, 48 insertions(+), 116 deletions(-) create mode 100644 superset/migrations/versions/2024-01-19_10-03_e863403c0c50_drop_url_table.py delete mode 100644 superset/views/redirects.py diff --git a/RESOURCES/STANDARD_ROLES.md b/RESOURCES/STANDARD_ROLES.md index 51fcc6479b6..e1734314f4d 100644 --- a/RESOURCES/STANDARD_ROLES.md +++ b/RESOURCES/STANDARD_ROLES.md @@ -57,7 +57,6 @@ | can external metadata on Datasource | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | O | | can save on Datasource | :heavy_check_mark: | :heavy_check_mark: | O | O | | can get on Datasource | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | O | -| can shortner on R | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | O | | can my queries on SqlLab | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | can log on Superset | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | O | | can schemas access for csv upload on Superset | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | O | diff --git a/UPDATING.md b/UPDATING.md index cf4f846715a..b239866221e 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -41,6 +41,7 @@ assists people when migrating to a new version. - [26636](https://github.com/apache/superset/issues/26636): Sets the `DASHBOARD_VIRTUALIZATION` feature flag to `True` by default. This feature was introduced by [21438](https://github.com/apache/superset/pull/21438) and will enable virtualization when rendering a dashboard's charts in an attempt to reduce the number of elements (DOM nodes) rendered at once. This is especially useful for large dashboards. - [26637](https://github.com/apache/superset/issues/26637): Sets the `DRILL_BY` feature flag to `True` by default given that the feature has been tested for a while and reached a stable state. - [26462](https://github.com/apache/superset/issues/26462): Removes the Profile feature given that it's not actively maintained and not widely used. +- [26377](https://github.com/apache/superset/pull/26377): Removes the deprecated Redirect API that supported short URLs used before the permalink feature. ### Potential Downtime diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tabs.test.jsx b/superset-frontend/src/dashboard/components/gridComponents/Tabs.test.jsx index 8a4f5117187..359e58b5a8d 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Tabs.test.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Tabs.test.jsx @@ -25,7 +25,6 @@ import { HTML5Backend } from 'react-dnd-html5-backend'; import { LineEditableTabs } from 'src/components/Tabs'; import { AntdModal } from 'src/components'; -import fetchMock from 'fetch-mock'; import { styledMount as mount } from 'spec/helpers/theming'; import DashboardComponent from 'src/dashboard/containers/DashboardComponent'; import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton'; @@ -40,8 +39,6 @@ import { nativeFilters } from 'spec/fixtures/mockNativeFilters'; import { initialState } from 'src/SqlLab/fixtures'; describe('Tabs', () => { - fetchMock.post('glob:*/r/shortener/', {}); - const props = { id: 'TABS_ID', parentId: DASHBOARD_ROOT_ID, diff --git a/superset/initialization/__init__.py b/superset/initialization/__init__.py index 9da84c1fa32..807f430ee44 100644 --- a/superset/initialization/__init__.py +++ b/superset/initialization/__init__.py @@ -183,7 +183,6 @@ def init_views(self) -> None: from superset.views.key_value import KV from superset.views.log.api import LogRestApi from superset.views.log.views import LogModelView - from superset.views.redirects import R from superset.views.sql_lab.views import ( SavedQueryView, SavedQueryViewApi, @@ -309,7 +308,6 @@ def init_views(self) -> None: appbuilder.add_view_no_menu(ExploreView) appbuilder.add_view_no_menu(ExplorePermalinkView) appbuilder.add_view_no_menu(KV) - appbuilder.add_view_no_menu(R) appbuilder.add_view_no_menu(SavedQueryView) appbuilder.add_view_no_menu(SavedQueryViewApi) appbuilder.add_view_no_menu(SliceAsync) diff --git a/superset/migrations/versions/2024-01-19_10-03_e863403c0c50_drop_url_table.py b/superset/migrations/versions/2024-01-19_10-03_e863403c0c50_drop_url_table.py new file mode 100644 index 00000000000..49b320f13f6 --- /dev/null +++ b/superset/migrations/versions/2024-01-19_10-03_e863403c0c50_drop_url_table.py @@ -0,0 +1,45 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""drop_url_table + +Revision ID: e863403c0c50 +Revises: 214f580d09c9 +Create Date: 2023-12-28 16:03:31.691033 + +""" + +# revision identifiers, used by Alembic. +revision = "e863403c0c50" +down_revision = "214f580d09c9" + +from importlib import import_module + +import sqlalchemy as sa +from alembic import op +from sqlalchemy.dialects import postgresql + +module = import_module("superset.migrations.versions.2016-01-13_20-24_8e80a26a31db_") + + +def upgrade(): + module.downgrade() + + +def downgrade(): + module.upgrade() + op.alter_column("url", "changed_on", existing_type=sa.DATETIME(), nullable=True) + op.alter_column("url", "created_on", existing_type=sa.DATETIME(), nullable=True) diff --git a/superset/models/core.py b/superset/models/core.py index eece661ec51..a8d0cdeb517 100755 --- a/superset/models/core.py +++ b/superset/models/core.py @@ -90,14 +90,6 @@ DB_CONNECTION_MUTATOR = config["DB_CONNECTION_MUTATOR"] -class Url(Model, AuditMixinNullable): - """Used for the short url feature""" - - __tablename__ = "url" - id = Column(Integer, primary_key=True) - url = Column(Text) - - class KeyValue(Model): # pylint: disable=too-few-public-methods """Used for any type of key-value store""" diff --git a/superset/views/__init__.py b/superset/views/__init__.py index 1b8d1b8f095..838e92aca23 100644 --- a/superset/views/__init__.py +++ b/superset/views/__init__.py @@ -22,7 +22,6 @@ css_templates, dynamic_plugins, health, - redirects, sql_lab, tags, ) diff --git a/superset/views/redirects.py b/superset/views/redirects.py deleted file mode 100644 index 93a43394031..00000000000 --- a/superset/views/redirects.py +++ /dev/null @@ -1,74 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -import logging -from typing import Optional - -from flask import flash -from flask_appbuilder import expose -from werkzeug.utils import redirect - -from superset import db, event_logger -from superset.models import core as models -from superset.superset_typing import FlaskResponse -from superset.views.base import BaseSupersetView - -logger = logging.getLogger(__name__) - - -class R(BaseSupersetView): # pylint: disable=invalid-name - - """used for short urls""" - - @staticmethod - def _validate_explore_url(url: str) -> Optional[str]: - if url.startswith("//superset/explore/p/"): - return url - - if url.startswith("//superset/explore"): - return "/" + url[10:] # Remove /superset from old Explore URLs - - if url.startswith("//explore"): - return url - - return None - - @staticmethod - def _validate_dashboard_url(url: str) -> Optional[str]: - if url.startswith("//superset/dashboard/"): - return url - - return None - - @event_logger.log_this - @expose("/") - def index(self, url_id: int) -> FlaskResponse: - url = db.session.query(models.Url).get(url_id) - if url and url.url: - explore_url = self._validate_explore_url(url.url) - if explore_url: - if explore_url.startswith("//explore/?"): - explore_url = f"//explore/?r={url_id}" - return redirect(explore_url[1:]) - - dashboard_url = self._validate_dashboard_url(url.url) - if dashboard_url: - return redirect(dashboard_url[1:]) - - return redirect("/") - - flash("URL to nowhere...", "danger") - return redirect("/") diff --git a/superset/views/utils.py b/superset/views/utils.py index 574fedb66b7..bf1099a6aa4 100644 --- a/superset/views/utils.py +++ b/superset/views/utils.py @@ -19,7 +19,6 @@ from collections import defaultdict from functools import wraps from typing import Any, Callable, DefaultDict, Optional, Union -from urllib import parse import msgpack import pyarrow as pa @@ -31,7 +30,6 @@ from sqlalchemy.exc import NoResultFound from werkzeug.wrappers.response import Response -import superset.models.core as models from superset import app, dataframe, db, result_set, viz from superset.common.db_query_status import QueryStatus from superset.daos.datasource import DatasourceDAO @@ -145,7 +143,7 @@ def loads_request_json(request_json_data: str) -> dict[Any, Any]: return {} -def get_form_data( # pylint: disable=too-many-locals +def get_form_data( slice_id: Optional[int] = None, use_slice_data: bool = False, initial_form_data: Optional[dict[str, Any]] = None, @@ -185,19 +183,6 @@ def get_form_data( # pylint: disable=too-many-locals json_data = form_data["queries"][0] if "queries" in form_data else {} form_data.update(json_data) - if has_request_context(): - url_id = request.args.get("r") - if url_id: - saved_url = db.session.query(models.Url).filter_by(id=url_id).first() - if saved_url: - url_str = parse.unquote_plus( - saved_url.url.split("?")[1][10:], encoding="utf-8" - ) - url_form_data = loads_request_json(url_str) - # allow form_date in request override saved url - url_form_data.update(form_data) - form_data = url_form_data - form_data = {k: v for k, v in form_data.items() if k not in REJECTED_FORM_DATA_KEYS} # When a slice_id is present, load from DB and override diff --git a/tests/integration_tests/core_tests.py b/tests/integration_tests/core_tests.py index 526a5592e96..9e1a9ad11c8 100644 --- a/tests/integration_tests/core_tests.py +++ b/tests/integration_tests/core_tests.py @@ -413,17 +413,6 @@ def test_cache_logging(self): db.session.delete(ck) app.config["STORE_CACHE_KEYS_IN_METADATA_DB"] = store_cache_keys - def test_redirect_invalid(self): - model_url = models.Url(url="hhttp://invalid.com") - db.session.add(model_url) - db.session.commit() - - self.login(username="admin") - response = self.client.get(f"/r/{model_url.id}") - assert response.headers["Location"] == "/" - db.session.delete(model_url) - db.session.commit() - @with_feature_flags(KV_STORE=False) def test_kv_disabled(self): self.login(username="admin") diff --git a/tests/integration_tests/tags/commands_tests.py b/tests/integration_tests/tags/commands_tests.py index 48abfd31b41..83762f8f6e8 100644 --- a/tests/integration_tests/tags/commands_tests.py +++ b/tests/integration_tests/tags/commands_tests.py @@ -112,6 +112,7 @@ def test_delete_tags_command(self): TaggedObject.object_id == example_dashboard.id, Tag.type == TagType.custom, ) + .order_by(Tag.name) .all() ) assert example_tags == [tag.name for tag in created_tags] From 1010294f2b5459c3a9456b76b2aaf27f42059457 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Fri, 19 Jan 2024 13:31:56 -0300 Subject: [PATCH 03/39] chore: Updates the Release Process link in the issue template (#26677) --- .github/ISSUE_TEMPLATE/bug-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index b79acd184d8..40e5d97f27d 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -38,7 +38,7 @@ body: value: | ### Environment - Please specify your environment. If your environment does not match the alternatives, you need to upgrade your environment before submitting the issue as it may have already been fixed. For additional information about the releases, check out the [release page](https://github.com/apache/superset/wiki). + Please specify your environment. If your environment does not match the alternatives, you need to upgrade your environment before submitting the issue as it may have already been fixed. For additional information about the releases, see [Release Process](https://github.com/apache/superset/wiki/Release-Process). - type: dropdown id: superset-version attributes: From 649ff4dd616fe1e7839444e0408b07cb16b18d12 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:00:51 -0300 Subject: [PATCH 04/39] fix: Revert "buld(deps): bump swagger-ui-react from 4.1.3 to 5.11.0 in docs (#26552) (#26679) --- docs/package.json | 2 +- docs/yarn.lock | 1415 +++++++++++---------------------------------- 2 files changed, 340 insertions(+), 1077 deletions(-) diff --git a/docs/package.json b/docs/package.json index 5ac908c3af9..747063d5bad 100644 --- a/docs/package.json +++ b/docs/package.json @@ -41,7 +41,7 @@ "react-dom": "^17.0.1", "react-github-btn": "^1.2.0", "stream": "^0.0.2", - "swagger-ui-react": "^5.11.0", + "swagger-ui-react": "^4.1.3", "url-loader": "^4.1.1" }, "devDependencies": { diff --git a/docs/yarn.lock b/docs/yarn.lock index 7fc5b339327..60b67abfac1 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -2455,15 +2455,23 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime-corejs3@^7.18.6", "@babel/runtime-corejs3@^7.20.7", "@babel/runtime-corejs3@^7.22.15", "@babel/runtime-corejs3@^7.23.7": - version "7.23.8" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.23.8.tgz#b8aa3d47570bdd08fed77fdfd69542118af0df26" - integrity sha512-2ZzmcDugdm0/YQKFVYsXiwUN7USPX8PM7cytpb4PFl87fM+qYPSvTZX//8tyeJB1j0YDmafBJEbl5f8NfLyuKw== +"@babel/runtime-corejs3@^7.11.2", "@babel/runtime-corejs3@^7.16.3": + version "7.17.9" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.9.tgz#3d02d0161f0fbf3ada8e88159375af97690f4055" + integrity sha512-WxYHHUWF2uZ7Hp1K+D1xQgbgkGUfA+5UPOegEXGt2Y5SMog/rYCVaifLZDbw8UkNXozEqqrZTy6bglL7xTaCOw== dependencies: - core-js-pure "^3.30.2" - regenerator-runtime "^0.14.0" + core-js-pure "^3.20.2" + regenerator-runtime "^0.13.4" + +"@babel/runtime-corejs3@^7.18.6": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz#6e4939d9d9789ff63e2dc58e88f13a3913a24eba" + integrity sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw== + dependencies: + core-js-pure "^3.25.1" + regenerator-runtime "^0.13.11" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.3.1", "@babel/runtime@^7.8.4": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.15.4", "@babel/runtime@^7.3.1", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.16.3" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz" integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ== @@ -2570,10 +2578,10 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" -"@braintree/sanitize-url@=7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-7.0.0.tgz#8899d8e68a1b3f6933d4ad57a263fd3cf1d34d8a" - integrity sha512-GMu2OJiTd1HSe74bbJYQnVvELANpYiGFZELyyTM1CR0sdv5ReQAcJ/c/8pIrPab3lO11+D+EpuGLUxqz+y832g== +"@braintree/sanitize-url@^5.0.2": + version "5.0.2" + resolved "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-5.0.2.tgz" + integrity sha512-NBEJlHWrhQucLhZGHtSxM2loSaNUMajC7KOYJLyfcdW/6goVoff2HoYI3bz8YCDN0wKGbxtUL0gx2dvHpvnWlw== "@colors/colors@1.5.0": version "1.5.0" @@ -3156,11 +3164,6 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== -"@fastify/busboy@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.0.tgz#0709e9f4cb252351c609c6e6d8d6779a8d25edff" - integrity sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA== - "@hapi/hoek@^9.0.0": version "9.2.1" resolved "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz" @@ -3578,401 +3581,6 @@ "@svgr/plugin-jsx" "^6.2.1" "@svgr/plugin-svgo" "^6.2.0" -"@swagger-api/apidom-ast@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ast/-/apidom-ast-0.92.0.tgz#58faf1bbc88fa161cabe40fa16bd837f3570fd28" - integrity sha512-j9vuKaYZP3mAGXUcKeWIkSToxPPCBLJcLEfjSEh14P0n6NRJp7Yg19SA+IwHdIvOAfJonuebj/lhPOMjzd6P1g== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-error" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - unraw "^3.0.0" - -"@swagger-api/apidom-core@>=0.90.0 <1.0.0", "@swagger-api/apidom-core@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-core/-/apidom-core-0.92.0.tgz#44bb5d58f0a551ec7529617df10a23093eac2a06" - integrity sha512-PK1zlS0UCcE5dIPtSy8/+oWfXAVf7b/iM3LRaPgaFGF5b8qa6S/zmROTh10Yjug9v9Vnuq8opEhyHkGyl+WdSA== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-ast" "^0.92.0" - "@swagger-api/apidom-error" "^0.92.0" - "@types/ramda" "~0.29.6" - minim "~0.23.8" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - short-unique-id "^5.0.2" - stampit "^4.3.2" - -"@swagger-api/apidom-error@>=0.90.0 <1.0.0", "@swagger-api/apidom-error@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-error/-/apidom-error-0.92.0.tgz#a5e93e98f689cf346b9d3d12ea31e20bb67376b1" - integrity sha512-wo7xCvTpWr5Lpt/ly1L4bhZ6W7grgtAg7SK/d8FNZR85zPJXM4FPMpcRtKktfWJ/RikQJT/g5DjI33iTqB6z/w== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - -"@swagger-api/apidom-json-pointer@>=0.90.0 <1.0.0", "@swagger-api/apidom-json-pointer@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-0.92.0.tgz#68188d7e1ae2988b9a8c0107e7201b9545a77764" - integrity sha512-VmZ1EXE7BWX+ndeeh9t1uFRql5jbPRmAcglUfdtu3jlg6fOqXzzgx9qFpRz9GhpMHWEGFm1ymd8tMAa1CvgcHw== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-error" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-ns-api-design-systems@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-0.92.0.tgz#b99dc79b96a9b444e20ccb45aec49b0aa16e8996" - integrity sha512-wXEXhw0wDQIPTUqff953h44oQZr29DcoAzZfROWlGtOLItGDDMjhfIYiRg1406mXA4N7d5d0vNi9V/HXkxItQw== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-error" "^0.92.0" - "@swagger-api/apidom-ns-openapi-3-1" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - -"@swagger-api/apidom-ns-asyncapi-2@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-0.92.0.tgz#872fc6ef5548bacb88b3c3550ac7350e12830331" - integrity sha512-FmJLT3GqzT4HK7Mwh54cXZ4PZt58yKVtJAKWKJ0dg2/Gim0AKJWf6t6B3Z9ZFUiKyehbqP4K7gSM7qGL0tKe2Q== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-json-schema-draft-7" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - -"@swagger-api/apidom-ns-json-schema-draft-4@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-0.92.0.tgz#11c6fede3eef005efe8b5c9d61001d24916b7633" - integrity sha512-7s2EKjCQwRXbK4Y4AGpVkyn1AANCxOUFSHebo1h2katyVeAopV0LJmbXH5yQedTltV0k3BIjnd7hS+7dI846Pw== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-ast" "^0.92.0" - "@swagger-api/apidom-core" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - -"@swagger-api/apidom-ns-json-schema-draft-6@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-0.92.0.tgz#59c37e8064c72b5e88939d71b6abd6a8312a94c4" - integrity sha512-zur80x04jesXVzlU9sLZhW4giO9RfOouI7L/H8v2wUlcBvjaPBn1tIqrURw2VEHKAcJORhTRusQCR21vnFot2g== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-error" "^0.92.0" - "@swagger-api/apidom-ns-json-schema-draft-4" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - -"@swagger-api/apidom-ns-json-schema-draft-7@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-0.92.0.tgz#7d833b1b8b968aa16c8313a8594ed8b309758d3f" - integrity sha512-DSY7lY98XHnc0wg0V38ZmBPs5HWuRuSb6G+n5Z+qs5RRodh1x5BrTIY6M0Yk3oJVbbEoFGmF0VlTe6vHf44pbw== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-error" "^0.92.0" - "@swagger-api/apidom-ns-json-schema-draft-6" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - -"@swagger-api/apidom-ns-openapi-2@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-0.92.0.tgz#b61cc851f21fc14fcc58fef15a0bea0ab57b87e6" - integrity sha512-OJlSTvPzK+zqzd2xXeWkF50z08Wlpygc98eVzZjYI0Af8mz7x6R5T9BCP5p6ZlQoO9OTvk4gfv7ViWXCdamObg== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-error" "^0.92.0" - "@swagger-api/apidom-ns-json-schema-draft-4" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - -"@swagger-api/apidom-ns-openapi-3-0@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-0.92.0.tgz#f8e9a62cc06e758a7d3b8cc8b030c28f5457281a" - integrity sha512-VGha4RRnoeoAZBWLGy37YsBzwICM3ZFNyCk2Dwpaqfg9zFN+E6BL2CtIbkxvFkMdwaMURmDItiQsw28pF0tOgQ== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-error" "^0.92.0" - "@swagger-api/apidom-ns-json-schema-draft-4" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - -"@swagger-api/apidom-ns-openapi-3-1@>=0.90.0 <1.0.0", "@swagger-api/apidom-ns-openapi-3-1@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-0.92.0.tgz#3a393c9c56672471233198079a1e15354629dfdd" - integrity sha512-xZD+JxifYhDoTjn76K2ZT3xNoXBQChaKfSkJr4l5Xh9Guuk0IcsPTUDRpuytuZZXVez0O401XFoUso/mZRTjkA== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-ast" "^0.92.0" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-openapi-3-0" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - -"@swagger-api/apidom-ns-workflows-1@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-ns-workflows-1/-/apidom-ns-workflows-1-0.92.0.tgz#8ee3d51bd0014fcf8dfc0b58ba03d97b8427b9c3" - integrity sha512-gl1dF+SrRHK4lLiwaK4PMjL9A5z28cW9xiMWCxRyppX/I2bVTVVOfgdAyqLWsFA0gopmITWesJxohRumG35fTw== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-openapi-3-1" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - -"@swagger-api/apidom-parser-adapter-api-design-systems-json@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-0.92.0.tgz#9437cae4c06dc8933345830ff1d055eaea314cda" - integrity sha512-i07FeLdNobWzHT9LnfsdOix+XrlZN/KnQL1RODPzxWk7i7ya2e4uc3JemyHh4Tnv04G8JV32SQqtzOtMteJsdA== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-api-design-systems" "^0.92.0" - "@swagger-api/apidom-parser-adapter-json" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-api-design-systems-yaml@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-0.92.0.tgz#72d97d3cef6d30c30a7de61dbdd67321b1913d59" - integrity sha512-bbjFkU0D4zqaZnd8/m1Kyx2UuHpri8ZxLdT1TiXqHweSfRQcNt4VYt0bjWBnnGGBMkHElgYbX5ov6kHvPf3wJg== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-api-design-systems" "^0.92.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-asyncapi-json-2@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-0.92.0.tgz#4996bc69e9f7e17a9f4d1b8316429d5373043918" - integrity sha512-Q7gudmGA5TUGbbr0QYNQkndktP91C0WE7uDDS2IwCBtHroRDiMPFCjzE9dsjIST5WnP+LUXmxG1Bv0NLTWcSUg== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-asyncapi-2" "^0.92.0" - "@swagger-api/apidom-parser-adapter-json" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-0.92.0.tgz#29eef57f3632570cdd4d8e8ba0b22fc8e046c44c" - integrity sha512-V5/VdDj0aeOKp+3AtvPSz2b0HosJfYkHPjNvPU5eafLSzqzMIR/evYq5BvKWoJL1IvLdjoEPqDVVaEZluHZTew== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-asyncapi-2" "^0.92.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-json@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-0.92.0.tgz#52af0254d3c27f601d6bee5af7f6e78c2b15f939" - integrity sha512-KA1Nn6FN0zTA5JhRazwYN9voTDlmExID7Jwz6GXmY826OXqeT4Yl0Egyo1aLYrfT0S73vhC4LVqpdORWLGdZtg== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-ast" "^0.92.0" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-error" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - tree-sitter "=0.20.4" - tree-sitter-json "=0.20.1" - web-tree-sitter "=0.20.3" - -"@swagger-api/apidom-parser-adapter-openapi-json-2@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-0.92.0.tgz#ccaac1c6129f284aad40d6ff75a2559cbd3bcd73" - integrity sha512-8OlvjcvI/GuOFJJxN+Mc4tJSo9UWuJdzQtQOtO4k3QwWwS28hGvRTjQ5PpsXAVZoLJMAbDuRdREYD9qeIKvM2g== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-openapi-2" "^0.92.0" - "@swagger-api/apidom-parser-adapter-json" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-openapi-json-3-0@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-0.92.0.tgz#7115ba14ee1fd303ae0d40f6ee813c14bcd69819" - integrity sha512-kzE4COaNobKIUjGsdqqXgO/LruaQHs2kTzOzHPUTR1TH1ZlB2t8MTV+6LJzGNG3IB3QSfZDd7KBEYWklsCTyTA== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-openapi-3-0" "^0.92.0" - "@swagger-api/apidom-parser-adapter-json" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-openapi-json-3-1@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-0.92.0.tgz#f72ef7ddd55bd692d856e056795ee338ce0769e4" - integrity sha512-4gkIXfKGwEKZQ6+kxp4EdFBlAc7Kjq8GAgaC7ilGTSSxIaz5hBHBOJoe3cXWpQ/WlXiOyNCy7WdbuKRpUDKIdg== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-openapi-3-1" "^0.92.0" - "@swagger-api/apidom-parser-adapter-json" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-openapi-yaml-2@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-0.92.0.tgz#66449fcfc680ccd59c9d1023f407529b27f7e247" - integrity sha512-TIY9cytYhA3yUf+5PcwsH9UjzKy5V4nGUtK6n5RvcL4btaGQA2LUB5CiV/1nSvYLNjYjGxhtB3haZDbHe3/gyw== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-openapi-2" "^0.92.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-0.92.0.tgz#233ea2e347943c98cb0961ed025f16f6fe8f40f4" - integrity sha512-AUwtAxeautYtiwifNCmv6Kjs7ksptRFxcQ3sgLv2bP3f9t5jzcI9NhmgJNdbRfohHYaHMwTuUESrfsTdBgKlAA== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-openapi-3-0" "^0.92.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-0.92.0.tgz#96a4a4f3baeaf2349043ba8bb2b4b5a22717a26b" - integrity sha512-gMR4zUZ/RrjVJVr6DnqwsCsnlplGXJk6O9UKbkoBsiom81dkcHx68BmWA2oM2lYVGKx+G8WVmVDo2EJaZvZYGg== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-openapi-3-1" "^0.92.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-workflows-json-1@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-workflows-json-1/-/apidom-parser-adapter-workflows-json-1-0.92.0.tgz#e31454a5b5a6ec38281a8aa4aeaf430b8fd61db7" - integrity sha512-tyLiSxEKeU6mhClFjNxrTQJA2aSgfEF7LJ/ZcJgvREsvyk6ns3op9wN2SXw4UmD+657IgN0aUPihh92aEXKovA== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-workflows-1" "^0.92.0" - "@swagger-api/apidom-parser-adapter-json" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-workflows-yaml-1@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-workflows-yaml-1/-/apidom-parser-adapter-workflows-yaml-1-0.92.0.tgz#c4bde8ebf67f1a7bde3998145830dfa6b81ce245" - integrity sha512-0Nr+5oAocuw3SZXcO8WEqnU7GGWP7O6GrsFafD6KLBL05v3I0erPfmnWQjWh6jBeXv8r5W69WEQItzES0DBJjA== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-ns-workflows-1" "^0.92.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.0.0" - -"@swagger-api/apidom-parser-adapter-yaml-1-2@^0.92.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-0.92.0.tgz#52cf595aa07289a4eadd1850e58d796e0ff0c59e" - integrity sha512-cFLqlhehMuY5WRdU1780Vno6iWpjMlr7CfOOloZW1rKf2lvojn0c4eDsyfWFaB2DgE+Xd4CWl55McuaPZMngsw== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-ast" "^0.92.0" - "@swagger-api/apidom-core" "^0.92.0" - "@swagger-api/apidom-error" "^0.92.0" - "@types/ramda" "~0.29.6" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - tree-sitter "=0.20.4" - tree-sitter-yaml "=0.5.0" - web-tree-sitter "=0.20.3" - -"@swagger-api/apidom-reference@>=0.90.0 <1.0.0": - version "0.92.0" - resolved "https://registry.yarnpkg.com/@swagger-api/apidom-reference/-/apidom-reference-0.92.0.tgz#11054a13e438bf15736200c6826cae845c12e465" - integrity sha512-G/qJBTpXCdwPsc5dqPjX+vAfhvtnhIFqnKtEZ71wnEvF7TpIxdeZKKfqpg+Zxi7MSuZD/Gpkr4J/eP0lO0fAdA== - dependencies: - "@babel/runtime-corejs3" "^7.20.7" - "@swagger-api/apidom-core" "^0.92.0" - "@types/ramda" "~0.29.6" - axios "^1.4.0" - minimatch "^7.4.3" - process "^0.11.10" - ramda "~0.29.1" - ramda-adjunct "^4.1.1" - stampit "^4.3.2" - optionalDependencies: - "@swagger-api/apidom-error" "^0.92.0" - "@swagger-api/apidom-json-pointer" "^0.92.0" - "@swagger-api/apidom-ns-asyncapi-2" "^0.92.0" - "@swagger-api/apidom-ns-openapi-2" "^0.92.0" - "@swagger-api/apidom-ns-openapi-3-0" "^0.92.0" - "@swagger-api/apidom-ns-openapi-3-1" "^0.92.0" - "@swagger-api/apidom-ns-workflows-1" "^0.92.0" - "@swagger-api/apidom-parser-adapter-api-design-systems-json" "^0.92.0" - "@swagger-api/apidom-parser-adapter-api-design-systems-yaml" "^0.92.0" - "@swagger-api/apidom-parser-adapter-asyncapi-json-2" "^0.92.0" - "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2" "^0.92.0" - "@swagger-api/apidom-parser-adapter-json" "^0.92.0" - "@swagger-api/apidom-parser-adapter-openapi-json-2" "^0.92.0" - "@swagger-api/apidom-parser-adapter-openapi-json-3-0" "^0.92.0" - "@swagger-api/apidom-parser-adapter-openapi-json-3-1" "^0.92.0" - "@swagger-api/apidom-parser-adapter-openapi-yaml-2" "^0.92.0" - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0" "^0.92.0" - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1" "^0.92.0" - "@swagger-api/apidom-parser-adapter-workflows-json-1" "^0.92.0" - "@swagger-api/apidom-parser-adapter-workflows-yaml-1" "^0.92.0" - "@swagger-api/apidom-parser-adapter-yaml-1-2" "^0.92.0" - "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" @@ -4077,6 +3685,14 @@ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.1" + resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/html-minifier-terser@^6.0.0": version "6.0.0" resolved "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.0.0.tgz" @@ -4170,18 +3786,21 @@ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== -"@types/ramda@~0.29.6": - version "0.29.9" - resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.29.9.tgz#a4c1a9d056249268ffe16c2f6d198e42c2fc994a" - integrity sha512-X3yEG6tQCWBcUAql+RPC/O1Hm9BSU+MXu2wJnCETuAgUlrEDwTA1kIOdEEE4YXDtf0zfQLHa9CCE7WYp9kqPIQ== - dependencies: - types-ramda "^0.29.6" - "@types/range-parser@*": version "1.2.4" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== +"@types/react-redux@^7.1.20": + version "7.1.20" + resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz" + integrity sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + "@types/react-router-config@*": version "5.0.3" resolved "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.3.tgz" @@ -4287,11 +3906,6 @@ resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== -"@types/use-sync-external-store@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43" - integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== - "@types/ws@^8.5.1": version "8.5.4" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" @@ -4442,11 +4056,6 @@ resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -"@yarnpkg/lockfile@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== - accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -4714,11 +4323,6 @@ async-validator@^4.0.2: resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-4.0.7.tgz#034a0fd2103a6b2ebf010da75183bec299247afe" integrity sha512-Pj2IR7u8hmUEDOwB++su6baaRi+QvsgajuFB9j95foM1N2gy5HM4z60hfusIO0fBPG5uLAEl6yCJr1jNSVugEQ== -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" @@ -4750,15 +4354,6 @@ axios@^0.25.0: dependencies: follow-redirects "^1.14.7" -axios@^1.4.0: - version "1.6.5" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.5.tgz#2c090da14aeeab3770ad30c3a1461bc970fb0cd8" - integrity sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg== - dependencies: - follow-redirects "^1.15.4" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - babel-loader@^8.2.5: version "8.3.0" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" @@ -4904,15 +4499,6 @@ binary-extensions@^2.0.0: resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bl@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - body-parser@1.20.1: version "1.20.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" @@ -4982,13 +4568,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" @@ -5006,19 +4585,16 @@ browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.17.5, browserslist@^4 node-releases "^2.0.8" update-browserslist-db "^1.0.10" +btoa@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz" + integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -5058,15 +4634,6 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" -call-bind@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" - integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== - dependencies: - function-bind "^1.1.2" - get-intrinsic "^1.2.1" - set-function-length "^1.1.1" - callsites@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" @@ -5202,11 +4769,6 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" @@ -5222,15 +4784,10 @@ ci-info@^3.2.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== -ci-info@^3.7.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1, classnames@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" - integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== +classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" + integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== clean-css@^5.1.5: version "5.2.2" @@ -5356,13 +4913,6 @@ combine-promises@^1.1.0: resolved "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz" integrity sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg== -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - comma-separated-tokens@^1.0.0: version "1.0.8" resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz" @@ -5479,10 +5029,10 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== -cookie@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== +cookie@~0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== copy-anything@^2.0.1: version "2.0.6" @@ -5496,20 +5046,13 @@ copy-text-to-clipboard@^3.0.1: resolved "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz" integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== -copy-to-clipboard@^3.2.0: +copy-to-clipboard@^3, copy-to-clipboard@^3.2.0: version "3.3.1" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== dependencies: toggle-selection "^1.0.6" -copy-to-clipboard@^3.3.1: - version "3.3.3" - resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" - integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== - dependencies: - toggle-selection "^1.0.6" - copy-webpack-plugin@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" @@ -5537,10 +5080,15 @@ core-js-compat@^3.25.1: dependencies: browserslist "^4.21.5" -core-js-pure@^3.30.2: - version "3.35.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.35.0.tgz#4660033304a050215ae82e476bd2513a419fbb34" - integrity sha512-f+eRYmkou59uh7BPcyJ8MC76DiGhspj1KMxVIcF24tzP8NA9HVa1uC7BTW2tgx7E1QVCzDzsgp7kArrzhlz8Ew== +core-js-pure@^3.20.2: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" + integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== + +core-js-pure@^3.25.1: + version "3.29.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.29.1.tgz#1be6ca2b8772f6b4df7fc4621743286e676c6162" + integrity sha512-4En6zYVi0i0XlXHVz/bi6l1XDjCqkKRq765NXuX+SnaIatlE96Odt5lMLjdxUiNI1v9OXI5DSLWYPlmTfkTktg== core-js@^3.23.3: version "3.29.1" @@ -5574,7 +5122,7 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" -cross-fetch@^3.0.4: +cross-fetch@^3.0.4, cross-fetch@^3.1.4: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== @@ -5782,6 +5330,14 @@ csstype@^3.0.2: resolved "https://registry.npmjs.org/csstype/-/csstype-3.0.9.tgz" integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw== +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/d/-/d-1.0.1.tgz" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + date-fns@2.x: version "2.28.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.28.0.tgz#9570d656f5fc13143e50c975a3b6bbeb46cd08b2" @@ -5820,14 +5376,7 @@ decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" -decompress-response@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" - integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== - dependencies: - mimic-response "^3.1.0" - -deep-extend@0.6.0, deep-extend@^0.6.0: +deep-extend@0.6.0, deep-extend@^0.6.0, deep-extend@~0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== @@ -5837,11 +5386,6 @@ deepmerge@^4.2.2: resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== -deepmerge@~4.3.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - default-gateway@^6.0.3: version "6.0.3" resolved "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz" @@ -5854,15 +5398,6 @@ defer-to-connect@^1.0.1: resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== -define-data-property@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" - integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== - dependencies: - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" @@ -5889,11 +5424,6 @@ del@^6.1.1: rimraf "^3.0.2" slash "^3.0.0" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -5916,11 +5446,6 @@ detab@2.0.4: dependencies: repeat-string "^1.5.4" -detect-libc@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d" - integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw== - detect-node@^2.0.4: version "2.1.0" resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz" @@ -6033,10 +5558,10 @@ domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: dependencies: domelementtype "^2.3.0" -dompurify@=3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.6.tgz#925ebd576d54a9531b5d76f0a5bef32548351dae" - integrity sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w== +dompurify@=2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.3.3.tgz" + integrity sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg== domutils@^1.7.0: version "1.7.0" @@ -6079,11 +5604,6 @@ dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" -drange@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/drange/-/drange-1.1.1.tgz#b2aecec2aab82fcef11dbbd7b9e32b83f8f6c0b8" - integrity sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA== - duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" @@ -6148,7 +5668,7 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -6232,6 +5752,42 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: + version "0.10.53" + resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-iterator@^2.0.3, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +es6-weak-map@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" @@ -6310,6 +5866,14 @@ eval@^0.1.8: "@types/node" "*" require-like ">= 0.1.1" +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + dependencies: + d "1" + es5-ext "~0.10.14" + eventemitter3@^4.0.0: version "4.0.7" resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" @@ -6335,11 +5899,6 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -expand-template@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" - integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== - express@^4.17.3: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" @@ -6377,6 +5936,13 @@ express@^4.17.3: utils-merge "1.0.1" vary "~1.1.2" +ext@^1.1.2: + version "1.6.0" + resolved "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz" + integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== + dependencies: + type "^2.5.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" @@ -6567,13 +6133,6 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -find-yarn-workspace-root@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" - integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== - dependencies: - micromatch "^4.0.2" - flux@^4.0.1: version "4.0.2" resolved "https://registry.npmjs.org/flux/-/flux-4.0.2.tgz" @@ -6587,11 +6146,6 @@ follow-redirects@^1.0.0, follow-redirects@^1.14.7: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf" integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw== -follow-redirects@^1.15.4: - version "1.15.5" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" - integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== - fork-ts-checker-webpack-plugin@^6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" @@ -6611,20 +6165,24 @@ fork-ts-checker-webpack-plugin@^6.5.0: semver "^7.3.2" tapable "^1.0.0" -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" +form-data-encoder@^1.4.3: + version "1.7.1" + resolved "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz" + integrity sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg== format@^0.2.0: version "0.2.2" resolved "https://registry.npmjs.org/format/-/format-0.2.2.tgz" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= +formdata-node@^4.0.0: + version "4.3.1" + resolved "https://registry.npmjs.org/formdata-node/-/formdata-node-4.3.1.tgz" + integrity sha512-8xKSa9et4zb+yziWsD/bI+EYjdg1z2p9EpKr+o+Yk12F/wP66bmDdvjj2ZXd2K/MJlR3HBzWnuV7f82jzHRqCA== + dependencies: + node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.1" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -6640,11 +6198,6 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - fs-extra@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" @@ -6684,11 +6237,6 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" @@ -6712,16 +6260,6 @@ get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" - integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== - dependencies: - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" @@ -6759,11 +6297,6 @@ github-buttons@^2.8.0: resolved "https://registry.yarnpkg.com/github-buttons/-/github-buttons-2.21.1.tgz#9e55eb83b70c9149a21c235db2e971c53d4d98a2" integrity sha512-n9bCQ8sj+5oX1YH5NeyWGbAclRDtHEhMBzqw2ctsWpdEHOwVgfruRu0VIVy01Ah10dd/iFajMHYU71L7IBWBOw== -github-from-package@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" - integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== - github-slugger@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz" @@ -6863,13 +6396,6 @@ globby@^13.1.1: merge2 "^1.4.1" slash "^4.0.0" -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - got@^9.6.0: version "9.6.0" resolved "https://registry.npmjs.org/got/-/got-9.6.0.tgz" @@ -6887,11 +6413,6 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.11: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.9" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" @@ -6934,18 +6455,6 @@ has-flag@^4.0.0: resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== - dependencies: - get-intrinsic "^1.2.2" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - has-symbols@^1.0.1, has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" @@ -6975,13 +6484,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== - dependencies: - function-bind "^1.1.2" - hast-to-hyperscript@^9.0.0: version "9.0.1" resolved "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz" @@ -7072,7 +6574,7 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -7241,7 +6743,7 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -7314,7 +6816,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -7458,6 +6960,14 @@ is-docker@^2.0.0, is-docker@^2.1.1: resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== +is-dom@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-dom/-/is-dom-1.1.0.tgz" + integrity sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ== + dependencies: + is-object "^1.0.1" + is-window "^1.0.2" + is-extendable@^0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" @@ -7525,6 +7035,11 @@ is-obj@^2.0.0: resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== +is-object@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz" + integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== + is-path-cwd@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz" @@ -7552,10 +7067,10 @@ is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== +is-promise@^2.2.2: + version "2.2.2" + resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== is-regex@^1.1.4: version "1.1.4" @@ -7621,12 +7136,17 @@ is-whitespace-character@^1.0.0: resolved "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz" integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== +is-window@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-window/-/is-window-1.0.2.tgz" + integrity sha1-LIlspT25feRdPDMTOmXYyfVjSA0= + is-word-character@^1.0.0: version "1.0.4" resolved "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz" integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== -is-wsl@^2.1.1, is-wsl@^2.2.0: +is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== @@ -7643,11 +7163,6 @@ isarray@0.0.1: resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - isarray@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" @@ -7760,16 +7275,6 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-stable-stringify@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz#52d4361b47d49168bcc4e564189a42e5a7439454" - integrity sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg== - dependencies: - call-bind "^1.0.5" - isarray "^2.0.5" - jsonify "^0.0.1" - object-keys "^1.1.1" - json2mq@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/json2mq/-/json2mq-0.2.0.tgz#b637bd3ba9eabe122c83e9720483aeb10d2c904a" @@ -7796,11 +7301,6 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jsonify@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== - keyv@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" @@ -7813,13 +7313,6 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -klaw-sync@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" - integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== - dependencies: - graceful-fs "^4.1.11" - kleur@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" @@ -7942,7 +7435,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0: resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.15.0, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: +lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -7993,6 +7486,13 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz" + integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= + dependencies: + es5-ext "~0.10.2" + make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -8085,6 +7585,20 @@ memoize-one@^6.0.0: resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== +memoizee@^0.4.15: + version "0.4.15" + resolved "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz" + integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.53" + es6-weak-map "^2.0.3" + event-emitter "^0.3.5" + is-promise "^2.2.2" + lru-queue "^0.1.0" + next-tick "^1.1.0" + timers-ext "^0.1.7" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -8143,7 +7657,7 @@ mime-types@2.1.18: dependencies: mime-db "~1.33.0" -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -8170,11 +7684,6 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -mimic-response@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" - integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== - mini-css-extract-plugin@^2.6.1: version "2.7.3" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.3.tgz#794aa4d598bf178a66b2a35fe287c3df3eac394e" @@ -8182,13 +7691,6 @@ mini-css-extract-plugin@^2.6.1: dependencies: schema-utils "^4.0.0" -minim@~0.23.8: - version "0.23.8" - resolved "https://registry.yarnpkg.com/minim/-/minim-0.23.8.tgz#a529837afe1654f119dfb68ce7487dd8d4866b9c" - integrity sha512-bjdr2xW1dBCMsMGGsUeqM4eFI60m94+szhxWys+B1ztIt6gWSfeGBdSVCIawezeHYLYn0j6zrsXdQS/JllBzww== - dependencies: - lodash "^4.15.0" - minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" @@ -8208,28 +7710,11 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimatch@^7.4.3: - version "7.4.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-7.4.6.tgz#845d6f254d8f4a5e4fd6baf44d5f10c8448365fb" - integrity sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw== - dependencies: - brace-expansion "^2.0.1" - minimist@^1.2.0, minimist@^1.2.5: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== -minimist@^1.2.3, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" @@ -8265,21 +7750,11 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" -nan@^2.14.0, nan@^2.17.0, nan@^2.18.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.18.0.tgz#26a6faae7ffbeb293a39660e88a76b82e30b7554" - integrity sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w== - nanoid@^3.3.6: version "3.3.6" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== -napi-build-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" - integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== - needle@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/needle/-/needle-3.2.0.tgz#07d240ebcabfd65c76c03afae7f6defe6469df44" @@ -8299,6 +7774,16 @@ neo-async@^2.6.2: resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +next-tick@1, next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + no-case@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" @@ -8307,21 +7792,9 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" -node-abi@^3.3.0: - version "3.54.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.54.0.tgz#f6386f7548817acac6434c6cba02999c9aebcc69" - integrity sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA== - dependencies: - semver "^7.3.5" - -node-abort-controller@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" - integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== - -node-domexception@^1.0.0: +node-domexception@1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== node-emoji@^1.10.0: @@ -8331,14 +7804,6 @@ node-emoji@^1.10.0: dependencies: lodash "^4.17.21" -node-fetch-commonjs@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/node-fetch-commonjs/-/node-fetch-commonjs-3.3.2.tgz#0dd0fd4c4a314c5234f496ff7b5d9ce5a6c8feaa" - integrity sha512-VBlAiynj3VMLrotgwOS3OyECFxas5y7ltLcK4t41lMUZeaK15Ym4QRkqN0EQKAFL42q9i21EPKjzLUPfltR72A== - dependencies: - node-domexception "^1.0.0" - web-streams-polyfill "^3.0.3" - node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -8488,14 +7953,6 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -open@^7.4.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - open@^8.0.9, open@^8.4.0: version "8.4.0" resolved "https://registry.npmjs.org/open/-/open-8.4.0.tgz" @@ -8510,11 +7967,6 @@ opener@^1.5.2: resolved "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" @@ -8665,27 +8117,6 @@ pascal-case@^3.1.2: no-case "^3.0.4" tslib "^2.0.3" -patch-package@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.0.tgz#d191e2f1b6e06a4624a0116bcb88edd6714ede61" - integrity sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^4.1.2" - ci-info "^3.7.0" - cross-spawn "^7.0.3" - find-yarn-workspace-root "^2.0.0" - fs-extra "^9.0.0" - json-stable-stringify "^1.0.2" - klaw-sync "^6.0.0" - minimist "^1.2.6" - open "^7.4.2" - rimraf "^2.6.3" - semver "^7.5.3" - slash "^2.0.0" - tmp "^0.0.33" - yaml "^2.2.2" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" @@ -9075,24 +8506,6 @@ postcss@^8.3.11, postcss@^8.4.14, postcss@^8.4.17, postcss@^8.4.7: picocolors "^1.0.0" source-map-js "^1.0.2" -prebuild-install@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45" - integrity sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw== - dependencies: - detect-libc "^2.0.0" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.3" - mkdirp-classic "^0.5.3" - napi-build-utils "^1.0.1" - node-abi "^3.3.0" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^4.0.0" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" @@ -9121,26 +8534,16 @@ prism-react-renderer@^1.3.5: resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz#786bb69aa6f73c32ba1ee813fbe17a0115435085" integrity sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg== -prismjs@^1.27.0, prismjs@^1.28.0: +prismjs@^1.28.0: version "1.29.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== -prismjs@~1.27.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" - integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - promise@^7.1.1: version "7.3.1" resolved "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz" @@ -9156,14 +8559,14 @@ prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== +prop-types@^15.0.0, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2: + version "15.7.2" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== dependencies: loose-envify "^1.4.0" object-assign "^4.1.1" - react-is "^16.13.1" + react-is "^16.8.1" property-information@^5.0.0, property-information@^5.3.0: version "5.6.0" @@ -9180,11 +8583,6 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -9198,6 +8596,11 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + punycode@^1.3.2: version "1.4.1" resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" @@ -9225,19 +8628,17 @@ q@^1.1.2: resolved "https://registry.npmjs.org/q/-/q-1.5.1.tgz" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qs@6.11.0: +qs@6.11.0, qs@^6.9.4: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" -qs@^6.10.2: - version "6.11.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" - integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== - dependencies: - side-channel "^1.0.4" +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= querystringify@^2.1.1: version "2.2.0" @@ -9256,24 +8657,6 @@ queue@6.0.2: dependencies: inherits "~2.0.3" -ramda-adjunct@^4.0.0, ramda-adjunct@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ramda-adjunct/-/ramda-adjunct-4.1.1.tgz#085ca9a7bf19857378eff648f9852b15136dc66f" - integrity sha512-BnCGsZybQZMDGram9y7RiryoRHS5uwx8YeGuUeDKuZuvK38XO6JJfmK85BwRWAKFA6pZ5nZBO/HBFtExVaf31w== - -ramda@~0.29.1: - version "0.29.1" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.1.tgz#408a6165b9555b7ba2fc62555804b6c5a2eca196" - integrity sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA== - -randexp@^0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.5.3.tgz#f31c2de3148b30bdeb84b7c3f59b0ebb9fec3738" - integrity sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w== - dependencies: - drange "^1.0.2" - ret "^0.2.0" - randombytes@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" @@ -9689,7 +9072,7 @@ rc-virtual-list@^3.2.0, rc-virtual-list@^3.4.1: rc-resize-observer "^1.0.0" rc-util "^5.0.7" -rc@^1.2.7, rc@^1.2.8: +rc@^1.2.8: version "1.2.8" resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -9709,21 +9092,21 @@ react-base16-styling@^0.6.0: lodash.flow "^3.3.0" pure-color "^1.2.0" -react-copy-to-clipboard@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz#09aae5ec4c62750ccb2e6421a58725eabc41255c" - integrity sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A== +react-copy-to-clipboard@5.0.4: + version "5.0.4" + resolved "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.4.tgz" + integrity sha512-IeVAiNVKjSPeGax/Gmkqfa/+PuMTBhutEvFUaMQLwE2tS0EXrAdgOpWDX26bWTXF3HrioorR7lr08NqeYUWQCQ== dependencies: - copy-to-clipboard "^3.3.1" - prop-types "^15.8.1" + copy-to-clipboard "^3" + prop-types "^15.5.8" -react-debounce-input@=3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/react-debounce-input/-/react-debounce-input-3.3.0.tgz#85e3ebcaa41f2016e50613134a1ec9fe3cdb422e" - integrity sha512-VEqkvs8JvY/IIZvh71Z0TC+mdbxERvYF33RcebnodlsUZ8RSgyKe2VWaHXv4+/8aoOgXLxWrdsYs2hDhcwbUgA== +react-debounce-input@=3.2.4: + version "3.2.4" + resolved "https://registry.npmjs.org/react-debounce-input/-/react-debounce-input-3.2.4.tgz" + integrity sha512-fX70bNj0fLEYO2Zcvuh7eh9wOUQ29GIx6r8IxIJlc0i0mpUH++9ax0BhfAYfzndADli3RAMROrZQ014J01owrg== dependencies: lodash.debounce "^4" - prop-types "^15.8.1" + prop-types "^15.7.2" react-dev-utils@^12.0.1: version "12.0.1" @@ -9815,16 +9198,25 @@ react-immutable-pure-component@^2.2.0: resolved "https://registry.npmjs.org/react-immutable-pure-component/-/react-immutable-pure-component-2.2.2.tgz" integrity sha512-vkgoMJUDqHZfXXnjVlG3keCxSO/U6WeDQ5/Sl0GK2cH8TOxEzQ5jXqDXHEL/jqk6fsNxV05oH5kD7VNMUE2k+A== -react-inspector@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-6.0.2.tgz#aa3028803550cb6dbd7344816d5c80bf39d07e9d" - integrity sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ== +react-inspector@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz" + integrity sha512-GURDaYzoLbW8pMGXwYPDBIv6nqei4kK7LPRZ9q9HCZF54wqXz/dnylBp/kfE9XmekBhHvLDdcYeyIwSrvtOiWg== + dependencies: + "@babel/runtime" "^7.0.0" + is-dom "^1.0.0" + prop-types "^15.0.0" -react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: +react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.2: + version "17.0.2" + resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-json-view@^1.21.3: version "1.21.3" resolved "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz" @@ -9847,13 +9239,17 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: dependencies: "@babel/runtime" "^7.10.3" -react-redux@^9.0.4: - version "9.1.0" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.1.0.tgz#46a46d4cfed4e534ce5452bb39ba18e1d98a8197" - integrity sha512-6qoDzIO+gbrza8h3hjMA9aq4nwVFCKFtY2iLxCtVT38Swyy2C/dJCGBXHeHLtx6qlg/8qzc2MrhOeduf5K32wQ== +react-redux@^7.2.4: + version "7.2.6" + resolved "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz" + integrity sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ== dependencies: - "@types/use-sync-external-store" "^0.0.3" - use-sync-external-store "^1.0.0" + "@babel/runtime" "^7.15.4" + "@types/react-redux" "^7.1.20" + hoist-non-react-statics "^3.3.2" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-is "^17.0.2" react-router-config@^5.1.1: version "5.1.1" @@ -9890,16 +9286,16 @@ react-router@5.3.4, react-router@^5.3.3: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-syntax-highlighter@^15.5.0: - version "15.5.0" - resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz#4b3eccc2325fa2ec8eff1e2d6c18fa4a9e07ab20" - integrity sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg== +react-syntax-highlighter@^15.4.5: + version "15.4.5" + resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.4.5.tgz" + integrity sha512-RC90KQTxZ/b7+9iE6s9nmiFLFjWswUcfULi4GwVzdFVKVMQySkJWBuOmJFfjwjMVCo0IUUuJrWebNKyviKpwLQ== dependencies: "@babel/runtime" "^7.3.1" highlight.js "^10.4.1" lowlight "^1.17.0" - prismjs "^1.27.0" - refractor "^3.6.0" + prismjs "^1.28.0" + refractor "^3.2.0" react-textarea-autosize@^8.3.2: version "8.3.3" @@ -9940,15 +9336,6 @@ readable-stream@^3.0.6: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^3.1.1, readable-stream@^3.4.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" @@ -9980,19 +9367,21 @@ redux-immutable@^4.0.0: resolved "https://registry.npmjs.org/redux-immutable/-/redux-immutable-4.0.0.tgz" integrity sha1-Ohoy32Y2ZGK2NpHw4dw15HK7yfM= -redux@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b" - integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== +redux@^4.0.0, redux@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz" + integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw== + dependencies: + "@babel/runtime" "^7.9.2" -refractor@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" - integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== +refractor@^3.2.0: + version "3.5.0" + resolved "https://registry.npmjs.org/refractor/-/refractor-3.5.0.tgz" + integrity sha512-QwPJd3ferTZ4cSPPjdP5bsYHMytwWYnAN5EEnLtGvkqp/FCCnGsBgxrm9EuIDnjUC3Uc/kETtvVi7fSIVC74Dg== dependencies: hastscript "^6.0.0" parse-entities "^2.0.0" - prismjs "~1.27.0" + prismjs "~1.28.0" regenerate-unicode-properties@^10.1.0: version "10.1.0" @@ -10023,11 +9412,6 @@ regenerator-runtime@^0.13.4: resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - regenerator-transform@^0.14.2: version "0.14.5" resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" @@ -10200,10 +9584,10 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= -reselect@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.0.tgz#c479139ab9dd91be4d9c764a7f3868210ef8cd21" - integrity sha512-aw7jcGLDpSgNDyWBQLv2cedml85qd95/iszJjN988zX1t7AVRJi19d9kto5+W7oCfQ94gyo40dVbT6g2k4/kXg== +reselect@^4.0.0: + version "4.1.5" + resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz" + integrity sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ== resize-observer-polyfill@^1.5.0, resize-observer-polyfill@^1.5.1: version "1.5.1" @@ -10244,11 +9628,6 @@ responselike@^1.0.2: dependencies: lowercase-keys "^1.0.0" -ret@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c" - integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ== - retry@^0.13.1: version "0.13.1" resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" @@ -10259,13 +9638,6 @@ reusify@^1.0.4: resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" @@ -10416,7 +9788,7 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: +semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -10500,17 +9872,6 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" -set-function-length@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.0.tgz#2f81dc6c16c7059bda5ab7c82c11f03a515ed8e1" - integrity sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w== - dependencies: - define-data-property "^1.1.1" - function-bind "^1.1.2" - get-intrinsic "^1.2.2" - gopd "^1.0.1" - has-property-descriptors "^1.0.1" - setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" @@ -10572,11 +9933,6 @@ shelljs@^0.8.5: interpret "^1.0.0" rechoir "^0.6.2" -short-unique-id@^5.0.2: - version "5.0.3" - resolved "https://registry.yarnpkg.com/short-unique-id/-/short-unique-id-5.0.3.tgz#bc6975dc5e8b296960ff5ac91ddabbc7ddb693d9" - integrity sha512-yhniEILouC0s4lpH0h7rJsfylZdca10W9mDJRAFh3EpcSUanCHGb0R7kcFOIUCZYSAPo0PUD5ZxWQdW0T4xaug== - side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -10591,20 +9947,6 @@ signal-exit@^3.0.2, signal-exit@^3.0.3: resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz" integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== -simple-concat@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" - integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== - -simple-get@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" - integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== - dependencies: - decompress-response "^6.0.0" - once "^1.3.1" - simple-concat "^1.0.0" - sirv@^1.0.7: version "1.0.18" resolved "https://registry.npmjs.org/sirv/-/sirv-1.0.18.tgz" @@ -10629,11 +9971,6 @@ sitemap@^7.1.1: arg "^5.0.0" sax "^1.2.4" -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - slash@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" @@ -10719,11 +10056,6 @@ stable@^0.1.8: resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -stampit@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/stampit/-/stampit-4.3.2.tgz#cfd3f607dd628a161ce6305621597994b4d56573" - integrity sha512-pE2org1+ZWQBnIxRPrBM2gVupkuDD0TTNIo1H6GdT/vO82NXli2z8lRE8cu/nBIHrcOCXFBAHpb9ZldrB2/qOA== - state-toggle@^1.0.0: version "1.0.3" resolved "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz" @@ -10925,64 +10257,60 @@ svgo@^2.5.0, svgo@^2.7.0: picocolors "^1.0.0" stable "^0.1.8" -swagger-client@^3.25.0: - version "3.25.0" - resolved "https://registry.yarnpkg.com/swagger-client/-/swagger-client-3.25.0.tgz#c59b181bed7172475d275487e6ab8365bd3f06ec" - integrity sha512-p143zWkIhgyh2E5+3HPFMlCw3WkV9RbX9HyftfBdiccCbOlmHdcJC0XEJZxcm+ZA+80DORs0F30/mzk7sx4iwA== - dependencies: - "@babel/runtime-corejs3" "^7.22.15" - "@swagger-api/apidom-core" ">=0.90.0 <1.0.0" - "@swagger-api/apidom-error" ">=0.90.0 <1.0.0" - "@swagger-api/apidom-json-pointer" ">=0.90.0 <1.0.0" - "@swagger-api/apidom-ns-openapi-3-1" ">=0.90.0 <1.0.0" - "@swagger-api/apidom-reference" ">=0.90.0 <1.0.0" - cookie "~0.6.0" - deepmerge "~4.3.0" +swagger-client@^3.17.0: + version "3.17.0" + resolved "https://registry.npmjs.org/swagger-client/-/swagger-client-3.17.0.tgz" + integrity sha512-d8DOEME49wTXm+uT+lBAjJ5D6IDjEHdbkqa7MbcslR2c+oHIhi13ObwleVWGfr89MPkWgBl6RBq9VUHmrBJRbg== + dependencies: + "@babel/runtime-corejs3" "^7.11.2" + btoa "^1.2.1" + cookie "~0.4.1" + cross-fetch "^3.1.4" + deep-extend "~0.6.0" fast-json-patch "^3.0.0-1" - is-plain-object "^5.0.0" + form-data-encoder "^1.4.3" + formdata-node "^4.0.0" js-yaml "^4.1.0" - node-abort-controller "^3.1.1" - node-fetch-commonjs "^3.3.1" - qs "^6.10.2" + lodash "^4.17.21" + qs "^6.9.4" traverse "~0.6.6" - undici "^5.24.0" + url "~0.11.0" -swagger-ui-react@^5.11.0: - version "5.11.0" - resolved "https://registry.yarnpkg.com/swagger-ui-react/-/swagger-ui-react-5.11.0.tgz#ed50f61ce7aa2c322b3a2435f2aa38396668431d" - integrity sha512-iqc5/Z8nvqOdjU2LuWYbREnDmKj5gndZSESTH9dXfymlzLc2NoPQmXZAw02U8kFgHyciX0yDMp3oaCw1zBdPSA== +swagger-ui-react@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/swagger-ui-react/-/swagger-ui-react-4.1.3.tgz#a722ecbe54ef237fa9080447a7c708c4c72d846a" + integrity sha512-o1AoXUTNH40cxWus0QOeWQ8x9tSIEmrLBrOgAOHDnvWJ1qyjT8PjgHjPbUVjMbja18coyuaAAeUdyLKvLGmlDA== dependencies: - "@babel/runtime-corejs3" "^7.23.7" - "@braintree/sanitize-url" "=7.0.0" + "@babel/runtime-corejs3" "^7.16.3" + "@braintree/sanitize-url" "^5.0.2" base64-js "^1.5.1" - classnames "^2.5.1" + classnames "^2.3.1" css.escape "1.5.1" deep-extend "0.6.0" - dompurify "=3.0.6" + dompurify "=2.3.3" ieee754 "^1.2.1" immutable "^3.x.x" js-file-download "^0.4.12" js-yaml "=4.1.0" lodash "^4.17.21" - patch-package "^8.0.0" - prop-types "^15.8.1" - randexp "^0.5.3" + memoizee "^0.4.15" + prop-types "^15.7.2" randombytes "^2.1.0" - react-copy-to-clipboard "5.1.0" - react-debounce-input "=3.3.0" + react-copy-to-clipboard "5.0.4" + react-debounce-input "=3.2.4" react-immutable-proptypes "2.2.0" react-immutable-pure-component "^2.2.0" - react-inspector "^6.0.1" - react-redux "^9.0.4" - react-syntax-highlighter "^15.5.0" - redux "^5.0.0" + react-inspector "^5.1.1" + react-redux "^7.2.4" + react-syntax-highlighter "^15.4.5" + redux "^4.1.2" redux-immutable "^4.0.0" remarkable "^2.0.1" - reselect "^5.0.1" + reselect "^4.0.0" serialize-error "^8.1.0" sha.js "^2.4.11" - swagger-client "^3.25.0" - url-parse "^1.5.10" + swagger-client "^3.17.0" + url-parse "^1.5.3" xml "=1.0.1" xml-but-prettier "^1.0.1" zenscroll "^4.0.2" @@ -10997,27 +10325,6 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar-fs@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" - integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.1.4" - -tar-stream@^2.1.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.3: version "5.3.7" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz#ef760632d24991760f339fe9290deb936ad1ffc7" @@ -11059,6 +10366,14 @@ thunky@^1.0.2: resolved "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== +timers-ext@^0.1.7: + version "0.1.7" + resolved "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== + dependencies: + es5-ext "~0.10.46" + next-tick "1" + tiny-invariant@^1.0.2: version "1.2.0" resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz" @@ -11069,13 +10384,6 @@ tiny-warning@^1.0.0: resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" @@ -11118,28 +10426,6 @@ traverse@~0.6.6: resolved "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz" integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= -tree-sitter-json@=0.20.1: - version "0.20.1" - resolved "https://registry.yarnpkg.com/tree-sitter-json/-/tree-sitter-json-0.20.1.tgz#d1fe6c59571dd3a987ebb3f5aeef404f37b3a453" - integrity sha512-482hf7J+aBwhksSw8yWaqI8nyP1DrSwnS4IMBShsnkFWD3SE8oalHnsEik59fEVi3orcTCUtMzSjZx+0Tpa6Vw== - dependencies: - nan "^2.18.0" - -tree-sitter-yaml@=0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/tree-sitter-yaml/-/tree-sitter-yaml-0.5.0.tgz#c617ba72837399d8105ec10cdb4c360e1ed76076" - integrity sha512-POJ4ZNXXSWIG/W4Rjuyg36MkUD4d769YRUGKRqN+sVaj/VCo6Dh6Pkssn1Rtewd5kybx+jT1BWMyWN0CijXnMA== - dependencies: - nan "^2.14.0" - -tree-sitter@=0.20.4: - version "0.20.4" - resolved "https://registry.yarnpkg.com/tree-sitter/-/tree-sitter-0.20.4.tgz#7d9d4f769fc05342ef43e5559f7ff34b0fc48327" - integrity sha512-rjfR5dc4knG3jnJNN/giJ9WOoN1zL/kZyrS0ILh+eqq8RNcIbiXA63JsMEgluug0aNvfQvK4BfCErN1vIzvKog== - dependencies: - nan "^2.17.0" - prebuild-install "^7.1.1" - trim-trailing-lines@^1.0.0: version "1.1.4" resolved "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz" @@ -11160,11 +10446,6 @@ ts-essentials@^2.0.3: resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-2.0.12.tgz" integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w== -ts-toolbelt@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz#50a25426cfed500d4a09bd1b3afb6f28879edfd5" - integrity sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w== - tslib@^1.9.3: version "1.14.1" resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" @@ -11175,13 +10456,6 @@ tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== - dependencies: - safe-buffer "^5.0.1" - type-fest@^0.20.2: version "0.20.2" resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" @@ -11200,6 +10474,16 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +type@^1.0.1: + version "1.2.0" + resolved "https://registry.npmjs.org/type/-/type-1.2.0.tgz" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.5.0: + version "2.5.0" + resolved "https://registry.npmjs.org/type/-/type-2.5.0.tgz" + integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" @@ -11207,13 +10491,6 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -types-ramda@^0.29.6: - version "0.29.6" - resolved "https://registry.yarnpkg.com/types-ramda/-/types-ramda-0.29.6.tgz#a1d2a3c15a48e27d35832d7194d93369975f1427" - integrity sha512-VJoOk1uYNh9ZguGd3eZvqkdhD4hTGtnjRBUx5Zc0U9ftmnCgiWcSj/lsahzKunbiwRje1MxxNkEy1UdcXRCpYw== - dependencies: - ts-toolbelt "^9.6.0" - typescript@^5.3.3: version "5.3.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" @@ -11234,13 +10511,6 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" -undici@^5.24.0: - version "5.28.2" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.2.tgz#fea200eac65fc7ecaff80a023d1a0543423b4c91" - integrity sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w== - dependencies: - "@fastify/busboy" "^2.0.0" - unherit@^1.0.4: version "1.1.3" resolved "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz" @@ -11381,11 +10651,6 @@ unquote@~1.1.1: resolved "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz" integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= -unraw@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unraw/-/unraw-3.0.0.tgz#73443ed70d2ab09ccbac2b00525602d5991fbbe3" - integrity sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg== - update-browserslist-db@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" @@ -11437,7 +10702,7 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -url-parse@^1.5.10: +url-parse@^1.5.3: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== @@ -11445,6 +10710,14 @@ url-parse@^1.5.10: querystringify "^2.1.1" requires-port "^1.0.0" +url@~0.11.0: + version "0.11.0" + resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + use-composed-ref@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.1.0.tgz" @@ -11464,7 +10737,7 @@ use-latest@^1.0.0: dependencies: use-isomorphic-layout-effect "^1.0.0" -use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.0: +use-sync-external-store@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== @@ -11568,15 +10841,10 @@ web-namespaces@^1.0.0: resolved "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== -web-streams-polyfill@^3.0.3: - version "3.3.2" - resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz#32e26522e05128203a7de59519be3c648004343b" - integrity sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ== - -web-tree-sitter@=0.20.3: - version "0.20.3" - resolved "https://registry.yarnpkg.com/web-tree-sitter/-/web-tree-sitter-0.20.3.tgz#3dd17b283ad63b1d8c07c5ea814f0fefb2b1f776" - integrity sha512-zKGJW9r23y3BcJusbgvnOH2OYAW40MXAOi9bi3Gcc7T4Gms9WWgXF8m6adsJWpGJEhgOzCrfiz1IzKowJWrtYw== +web-streams-polyfill@4.0.0-beta.1: + version "4.0.0-beta.1" + resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.1.tgz" + integrity sha512-3ux37gEX670UUphBF9AMCq8XM6iQ8Ac6A+DSRRjDoRBm1ufCkaCDdNVbaqq60PsEkdNlLKrGtv/YBP4EJXqNtQ== webidl-conversions@^3.0.0: version "3.0.1" @@ -11880,11 +11148,6 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yaml@^2.2.2: - version "2.3.4" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" - integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" From f63e66be01cd0b0aee3ac3245ec677e2e5d93c78 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:21:14 -0300 Subject: [PATCH 05/39] refactor: Removes the deprecated VERSIONED_EXPORT feature flag (#26347) --- RESOURCES/FEATURE_FLAGS.md | 1 - UPDATING.md | 1 + .../src/utils/featureFlags.ts | 1 - .../src/features/charts/ChartCard.tsx | 3 +- .../src/pages/ChartList/index.tsx | 31 +- .../src/pages/DashboardList/index.tsx | 31 +- .../src/pages/DatabaseList/index.tsx | 5 +- .../src/pages/DatasetList/index.tsx | 33 +- .../src/pages/SavedQueryList/index.tsx | 5 +- superset/cli/importexport.py | 661 +++++++++--------- superset/config.py | 1 - superset/dashboards/api.py | 67 +- superset/datasets/api.py | 69 +- superset/initialization/__init__.py | 15 - superset/views/core.py | 51 -- tests/integration_tests/cli_tests.py | 195 ------ .../integration_tests/dashboards/api_tests.py | 8 +- tests/integration_tests/security_tests.py | 1 - 18 files changed, 427 insertions(+), 752 deletions(-) diff --git a/RESOURCES/FEATURE_FLAGS.md b/RESOURCES/FEATURE_FLAGS.md index 6ce8c1c1ee2..ef05ab98db5 100644 --- a/RESOURCES/FEATURE_FLAGS.md +++ b/RESOURCES/FEATURE_FLAGS.md @@ -88,4 +88,3 @@ These features flags currently default to True and **will be removed in a future - ENABLE_JAVASCRIPT_CONTROLS - GENERIC_CHART_AXES - KV_STORE -- VERSIONED_EXPORT diff --git a/UPDATING.md b/UPDATING.md index b239866221e..f1f25667368 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -28,6 +28,7 @@ assists people when migrating to a new version. ### Breaking Changes +- [26347](https://github.com/apache/superset/issues/26347): Removes the deprecated `VERSIONED_EXPORT` feature flag. The previous value of the feature flag was `True` and now the feature is permanently enabled. - [26328](https://github.com/apache/superset/issues/26328): Removes the deprecated Filter Box code and it's associated dependencies `react-select` and `array-move`. It also removes the `DeprecatedSelect` and `AsyncSelect` components that were exclusively used by filter boxes. Existing filter boxes will be automatically migrated to native filters. - [26330](https://github.com/apache/superset/issues/26330): Removes the deprecated `DASHBOARD_FILTERS_EXPERIMENTAL` feature flag. The previous value of the feature flag was `False` and now the feature is permanently removed. - [26344](https://github.com/apache/superset/issues/26344): Removes the deprecated `ENABLE_EXPLORE_JSON_CSRF_PROTECTION` feature flag. The previous value of the feature flag was `False` and now the feature is permanently removed. diff --git a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts index 6d5935f04ea..ba9d0d6680f 100644 --- a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts +++ b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts @@ -57,7 +57,6 @@ export enum FeatureFlag { TAGGING_SYSTEM = 'TAGGING_SYSTEM', THUMBNAILS = 'THUMBNAILS', USE_ANALAGOUS_COLORS = 'USE_ANALAGOUS_COLORS', - VERSIONED_EXPORT = 'VERSIONED_EXPORT', } export type ScheduleQueriesProps = { JSONSCHEMA: { diff --git a/superset-frontend/src/features/charts/ChartCard.tsx b/superset-frontend/src/features/charts/ChartCard.tsx index 352f34d3590..38a46eb8987 100644 --- a/superset-frontend/src/features/charts/ChartCard.tsx +++ b/superset-frontend/src/features/charts/ChartCard.tsx @@ -67,8 +67,7 @@ export default function ChartCard({ const history = useHistory(); const canEdit = hasPerm('can_write'); const canDelete = hasPerm('can_write'); - const canExport = - hasPerm('can_export') && isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT); + const canExport = hasPerm('can_export'); const theme = useTheme(); const menu = ( diff --git a/superset-frontend/src/pages/ChartList/index.tsx b/superset-frontend/src/pages/ChartList/index.tsx index 50801966611..bfd945ea189 100644 --- a/superset-frontend/src/pages/ChartList/index.tsx +++ b/superset-frontend/src/pages/ChartList/index.tsx @@ -234,8 +234,7 @@ function ChartList(props: ChartListProps) { const canCreate = hasPerm('can_write'); const canEdit = hasPerm('can_write'); const canDelete = hasPerm('can_write'); - const canExport = - hasPerm('can_export') && isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT); + const canExport = hasPerm('can_export'); const initialSort = [{ id: 'changed_on_delta_humanized', desc: true }]; const handleBulkChartExport = (chartsToExport: Chart[]) => { const ids = chartsToExport.map(({ id }) => id); @@ -777,21 +776,19 @@ function ChartList(props: ChartListProps) { }, }); - if (isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT)) { - subMenuButtons.push({ - name: ( - - - - ), - buttonStyle: 'link', - onClick: openChartImportModal, - }); - } + subMenuButtons.push({ + name: ( + + + + ), + buttonStyle: 'link', + onClick: openChartImportModal, + }); } return ( diff --git a/superset-frontend/src/pages/DashboardList/index.tsx b/superset-frontend/src/pages/DashboardList/index.tsx index e82b7018599..76b34c6652b 100644 --- a/superset-frontend/src/pages/DashboardList/index.tsx +++ b/superset-frontend/src/pages/DashboardList/index.tsx @@ -183,8 +183,7 @@ function DashboardList(props: DashboardListProps) { const canCreate = hasPerm('can_write'); const canEdit = hasPerm('can_write'); const canDelete = hasPerm('can_write'); - const canExport = - hasPerm('can_export') && isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT); + const canExport = hasPerm('can_export'); const initialSort = [{ id: 'changed_on_delta_humanized', desc: true }]; @@ -659,21 +658,19 @@ function DashboardList(props: DashboardListProps) { }, }); - if (isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT)) { - subMenuButtons.push({ - name: ( - - - - ), - buttonStyle: 'link', - onClick: openDashboardImportModal, - }); - } + subMenuButtons.push({ + name: ( + + + + ), + buttonStyle: 'link', + onClick: openDashboardImportModal, + }); } return ( <> diff --git a/superset-frontend/src/pages/DatabaseList/index.tsx b/superset-frontend/src/pages/DatabaseList/index.tsx index 8c98392aca9..b30786941ea 100644 --- a/superset-frontend/src/pages/DatabaseList/index.tsx +++ b/superset-frontend/src/pages/DatabaseList/index.tsx @@ -17,8 +17,6 @@ * under the License. */ import { - isFeatureEnabled, - FeatureFlag, getExtensionsRegistry, styled, SupersetClient, @@ -216,8 +214,7 @@ function DatabaseList({ const canCreate = hasPerm('can_write'); const canEdit = hasPerm('can_write'); const canDelete = hasPerm('can_write'); - const canExport = - hasPerm('can_export') && isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT); + const canExport = hasPerm('can_export'); const { canUploadCSV, canUploadColumnar, canUploadExcel } = uploadUserPerms( roles, diff --git a/superset-frontend/src/pages/DatasetList/index.tsx b/superset-frontend/src/pages/DatasetList/index.tsx index 5aef13dbb61..2ec521ad450 100644 --- a/superset-frontend/src/pages/DatasetList/index.tsx +++ b/superset-frontend/src/pages/DatasetList/index.tsx @@ -17,8 +17,6 @@ * under the License. */ import { - isFeatureEnabled, - FeatureFlag, getExtensionsRegistry, styled, SupersetClient, @@ -207,8 +205,7 @@ const DatasetList: FunctionComponent = ({ const canDelete = hasPerm('can_write'); const canCreate = hasPerm('can_write'); const canDuplicate = hasPerm('can_duplicate'); - const canExport = - hasPerm('can_export') && isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT); + const canExport = hasPerm('can_export'); const initialSort = SORT_BY; @@ -654,21 +651,19 @@ const DatasetList: FunctionComponent = ({ buttonStyle: 'primary', }); - if (isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT)) { - buttonArr.push({ - name: ( - - - - ), - buttonStyle: 'link', - onClick: openDatasetImportModal, - }); - } + buttonArr.push({ + name: ( + + + + ), + buttonStyle: 'link', + onClick: openDatasetImportModal, + }); } menuData.buttons = buttonArr; diff --git a/superset-frontend/src/pages/SavedQueryList/index.tsx b/superset-frontend/src/pages/SavedQueryList/index.tsx index d48ffef8c90..958107aa5d2 100644 --- a/superset-frontend/src/pages/SavedQueryList/index.tsx +++ b/superset-frontend/src/pages/SavedQueryList/index.tsx @@ -159,8 +159,7 @@ function SavedQueryList({ const canCreate = hasPerm('can_write'); const canEdit = hasPerm('can_write'); const canDelete = hasPerm('can_write'); - const canExport = - hasPerm('can_export') && isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT); + const canExport = hasPerm('can_export'); const handleSavedQueryPreview = useCallback( (id: number) => { @@ -204,7 +203,7 @@ function SavedQueryList({ buttonStyle: 'primary', }); - if (canCreate && isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT)) { + if (canCreate) { subMenuButtons.push({ name: ( None: ) -if feature_flags.get("VERSIONED_EXPORT"): +@click.command() +@with_appcontext +@click.option( + "--dashboard-file", + "-f", + help="Specify the file to export to", +) +def export_dashboards(dashboard_file: Optional[str] = None) -> None: + """Export dashboards to ZIP file""" + # pylint: disable=import-outside-toplevel + from superset.commands.dashboard.export import ExportDashboardsCommand + from superset.models.dashboard import Dashboard + + g.user = security_manager.find_user(username="admin") + + dashboard_ids = [id_ for (id_,) in db.session.query(Dashboard.id).all()] + timestamp = datetime.now().strftime("%Y%m%dT%H%M%S") + root = f"dashboard_export_{timestamp}" + dashboard_file = dashboard_file or f"{root}.zip" + + try: + with ZipFile(dashboard_file, "w") as bundle: + for file_name, file_content in ExportDashboardsCommand(dashboard_ids).run(): + with bundle.open(f"{root}/{file_name}", "w") as fp: + fp.write(file_content.encode()) + except Exception: # pylint: disable=broad-except + logger.exception( + "There was an error when exporting the dashboards, please check " + "the exception traceback in the log" + ) + sys.exit(1) - @click.command() - @with_appcontext - @click.option( - "--dashboard-file", - "-f", - help="Specify the file to export to", - ) - def export_dashboards(dashboard_file: Optional[str] = None) -> None: - """Export dashboards to ZIP file""" - # pylint: disable=import-outside-toplevel - from superset.commands.dashboard.export import ExportDashboardsCommand - from superset.models.dashboard import Dashboard - - g.user = security_manager.find_user(username="admin") - - dashboard_ids = [id_ for (id_,) in db.session.query(Dashboard.id).all()] - timestamp = datetime.now().strftime("%Y%m%dT%H%M%S") - root = f"dashboard_export_{timestamp}" - dashboard_file = dashboard_file or f"{root}.zip" - - try: - with ZipFile(dashboard_file, "w") as bundle: - for file_name, file_content in ExportDashboardsCommand( - dashboard_ids - ).run(): - with bundle.open(f"{root}/{file_name}", "w") as fp: - fp.write(file_content.encode()) - except Exception: # pylint: disable=broad-except - logger.exception( - "There was an error when exporting the dashboards, please check " - "the exception traceback in the log" - ) - sys.exit(1) - - @click.command() - @with_appcontext - @click.option( - "--datasource-file", - "-f", - help="Specify the file to export to", - ) - def export_datasources(datasource_file: Optional[str] = None) -> None: - """Export datasources to ZIP file""" - # pylint: disable=import-outside-toplevel - from superset.commands.dataset.export import ExportDatasetsCommand - from superset.connectors.sqla.models import SqlaTable - - g.user = security_manager.find_user(username="admin") - - dataset_ids = [id_ for (id_,) in db.session.query(SqlaTable.id).all()] - timestamp = datetime.now().strftime("%Y%m%dT%H%M%S") - root = f"dataset_export_{timestamp}" - datasource_file = datasource_file or f"{root}.zip" - - try: - with ZipFile(datasource_file, "w") as bundle: - for file_name, file_content in ExportDatasetsCommand(dataset_ids).run(): - with bundle.open(f"{root}/{file_name}", "w") as fp: - fp.write(file_content.encode()) - except Exception: # pylint: disable=broad-except - logger.exception( - "There was an error when exporting the datasets, please check " - "the exception traceback in the log" - ) - sys.exit(1) - - @click.command() - @with_appcontext - @click.option( - "--path", - "-p", - help="Path to a single ZIP file", - ) - @click.option( - "--username", - "-u", - default=None, - help="Specify the user name to assign dashboards to", - ) - def import_dashboards(path: str, username: Optional[str]) -> None: - """Import dashboards from ZIP file""" - # pylint: disable=import-outside-toplevel - from superset.commands.dashboard.importers.dispatcher import ( - ImportDashboardsCommand, + +@click.command() +@with_appcontext +@click.option( + "--datasource-file", + "-f", + help="Specify the file to export to", +) +def export_datasources(datasource_file: Optional[str] = None) -> None: + """Export datasources to ZIP file""" + # pylint: disable=import-outside-toplevel + from superset.commands.dataset.export import ExportDatasetsCommand + from superset.connectors.sqla.models import SqlaTable + + g.user = security_manager.find_user(username="admin") + + dataset_ids = [id_ for (id_,) in db.session.query(SqlaTable.id).all()] + timestamp = datetime.now().strftime("%Y%m%dT%H%M%S") + root = f"dataset_export_{timestamp}" + datasource_file = datasource_file or f"{root}.zip" + + try: + with ZipFile(datasource_file, "w") as bundle: + for file_name, file_content in ExportDatasetsCommand(dataset_ids).run(): + with bundle.open(f"{root}/{file_name}", "w") as fp: + fp.write(file_content.encode()) + except Exception: # pylint: disable=broad-except + logger.exception( + "There was an error when exporting the datasets, please check " + "the exception traceback in the log" ) - from superset.commands.importers.v1.utils import get_contents_from_bundle - - if username is not None: - g.user = security_manager.find_user(username=username) - if is_zipfile(path): - with ZipFile(path) as bundle: - contents = get_contents_from_bundle(bundle) - else: - with open(path) as file: - contents = {path: file.read()} - try: - ImportDashboardsCommand(contents, overwrite=True).run() - except Exception: # pylint: disable=broad-except - logger.exception( - "There was an error when importing the dashboards(s), please check " - "the exception traceback in the log" - ) - sys.exit(1) - - @click.command() - @with_appcontext - @click.option( - "--path", - "-p", - help="Path to a single ZIP file", - ) - def import_datasources(path: str) -> None: - """Import datasources from ZIP file""" - # pylint: disable=import-outside-toplevel - from superset.commands.dataset.importers.dispatcher import ImportDatasetsCommand - from superset.commands.importers.v1.utils import get_contents_from_bundle - - if is_zipfile(path): - with ZipFile(path) as bundle: - contents = get_contents_from_bundle(bundle) - else: - with open(path) as file: - contents = {path: file.read()} - try: - ImportDatasetsCommand(contents, overwrite=True).run() - except Exception: # pylint: disable=broad-except - logger.exception( - "There was an error when importing the dataset(s), please check the " - "exception traceback in the log" - ) - sys.exit(1) - -else: - - @click.command() - @with_appcontext - @click.option( - "--dashboard-file", - "-f", - default=None, - help="Specify the file to export to", - ) - @click.option( - "--print_stdout", - "-p", - is_flag=True, - default=False, - help="Print JSON to stdout", - ) - def export_dashboards( - dashboard_file: Optional[str], print_stdout: bool = False - ) -> None: - """Export dashboards to JSON""" - # pylint: disable=import-outside-toplevel - from superset.utils import dashboard_import_export - - data = dashboard_import_export.export_dashboards(db.session) - if print_stdout or not dashboard_file: - print(data) - if dashboard_file: - logger.info("Exporting dashboards to %s", dashboard_file) - with open(dashboard_file, "w") as data_stream: - data_stream.write(data) - - @click.command() - @with_appcontext - @click.option( - "--datasource-file", - "-f", - default=None, - help="Specify the file to export to", - ) - @click.option( - "--print_stdout", - "-p", - is_flag=True, - default=False, - help="Print YAML to stdout", - ) - @click.option( - "--back-references", - "-b", - is_flag=True, - default=False, - help="Include parent back references", - ) - @click.option( - "--include-defaults", - "-d", - is_flag=True, - default=False, - help="Include fields containing defaults", - ) - def export_datasources( - datasource_file: Optional[str], - print_stdout: bool = False, - back_references: bool = False, - include_defaults: bool = False, - ) -> None: - """Export datasources to YAML""" - # pylint: disable=import-outside-toplevel - from superset.utils import dict_import_export - - data = dict_import_export.export_to_dict( - session=db.session, - recursive=True, - back_references=back_references, - include_defaults=include_defaults, + sys.exit(1) + + +@click.command() +@with_appcontext +@click.option( + "--path", + "-p", + help="Path to a single ZIP file", +) +@click.option( + "--username", + "-u", + default=None, + help="Specify the user name to assign dashboards to", +) +def import_dashboards(path: str, username: Optional[str]) -> None: + """Import dashboards from ZIP file""" + # pylint: disable=import-outside-toplevel + from superset.commands.dashboard.importers.dispatcher import ImportDashboardsCommand + from superset.commands.importers.v1.utils import get_contents_from_bundle + + if username is not None: + g.user = security_manager.find_user(username=username) + if is_zipfile(path): + with ZipFile(path) as bundle: + contents = get_contents_from_bundle(bundle) + else: + with open(path) as file: + contents = {path: file.read()} + try: + ImportDashboardsCommand(contents, overwrite=True).run() + except Exception: # pylint: disable=broad-except + logger.exception( + "There was an error when importing the dashboards(s), please check " + "the exception traceback in the log" ) - if print_stdout or not datasource_file: - yaml.safe_dump(data, sys.stdout, default_flow_style=False) - if datasource_file: - logger.info("Exporting datasources to %s", datasource_file) - with open(datasource_file, "w") as data_stream: - yaml.safe_dump(data, data_stream, default_flow_style=False) - - @click.command() - @with_appcontext - @click.option( - "--path", - "-p", - help="Path to a single JSON file or path containing multiple JSON " - "files to import (*.json)", - ) - @click.option( - "--recursive", - "-r", - is_flag=True, - default=False, - help="recursively search the path for json files", - ) - @click.option( - "--username", - "-u", - default=None, - help="Specify the user name to assign dashboards to", - ) - def import_dashboards(path: str, recursive: bool, username: str) -> None: - """Import dashboards from JSON file""" - # pylint: disable=import-outside-toplevel - from superset.commands.dashboard.importers.v0 import ImportDashboardsCommand - - path_object = Path(path) - files: list[Path] = [] - if path_object.is_file(): - files.append(path_object) - elif path_object.exists() and not recursive: - files.extend(path_object.glob("*.json")) - elif path_object.exists() and recursive: - files.extend(path_object.rglob("*.json")) - if username is not None: - g.user = security_manager.find_user(username=username) - contents = {} - for path_ in files: - with open(path_) as file: - contents[path_.name] = file.read() - try: - ImportDashboardsCommand(contents).run() - except Exception: # pylint: disable=broad-except - logger.exception("Error when importing dashboard") - sys.exit(1) - - @click.command() - @with_appcontext - @click.option( - "--path", - "-p", - help="Path to a single YAML file or path containing multiple YAML " - "files to import (*.yaml or *.yml)", - ) - @click.option( - "--sync", - "-s", - "sync", - default="", - help="comma separated list of element types to synchronize " - 'e.g. "metrics,columns" deletes metrics and columns in the DB ' - "that are not specified in the YAML file", - ) - @click.option( - "--recursive", - "-r", - is_flag=True, - default=False, - help="recursively search the path for yaml files", - ) - def import_datasources(path: str, sync: str, recursive: bool) -> None: - """Import datasources from YAML""" - # pylint: disable=import-outside-toplevel - from superset.commands.dataset.importers.v0 import ImportDatasetsCommand - - sync_array = sync.split(",") - sync_columns = "columns" in sync_array - sync_metrics = "metrics" in sync_array - - path_object = Path(path) - files: list[Path] = [] - if path_object.is_file(): - files.append(path_object) - elif path_object.exists() and not recursive: - files.extend(path_object.glob("*.yaml")) - files.extend(path_object.glob("*.yml")) - elif path_object.exists() and recursive: - files.extend(path_object.rglob("*.yaml")) - files.extend(path_object.rglob("*.yml")) - contents = {} - for path_ in files: - with open(path_) as file: - contents[path_.name] = file.read() - try: - ImportDatasetsCommand( - contents, sync_columns=sync_columns, sync_metrics=sync_metrics - ).run() - except Exception: # pylint: disable=broad-except - logger.exception("Error when importing dataset") - sys.exit(1) - - @click.command() - @with_appcontext - @click.option( - "--back-references", - "-b", - is_flag=True, - default=False, - help="Include parent back references", - ) - def export_datasource_schema(back_references: bool) -> None: - """Export datasource YAML schema to stdout""" - # pylint: disable=import-outside-toplevel - from superset.utils import dict_import_export + sys.exit(1) + + +@click.command() +@with_appcontext +@click.option( + "--path", + "-p", + help="Path to a single ZIP file", +) +def import_datasources(path: str) -> None: + """Import datasources from ZIP file""" + # pylint: disable=import-outside-toplevel + from superset.commands.dataset.importers.dispatcher import ImportDatasetsCommand + from superset.commands.importers.v1.utils import get_contents_from_bundle + + if is_zipfile(path): + with ZipFile(path) as bundle: + contents = get_contents_from_bundle(bundle) + else: + with open(path) as file: + contents = {path: file.read()} + try: + ImportDatasetsCommand(contents, overwrite=True).run() + except Exception: # pylint: disable=broad-except + logger.exception( + "There was an error when importing the dataset(s), please check the " + "exception traceback in the log" + ) + sys.exit(1) + + +@click.command() +@with_appcontext +@click.option( + "--dashboard-file", + "-f", + default=None, + help="Specify the file to export to", +) +@click.option( + "--print_stdout", + "-p", + is_flag=True, + default=False, + help="Print JSON to stdout", +) +def legacy_export_dashboards( + dashboard_file: Optional[str], print_stdout: bool = False +) -> None: + """Export dashboards to JSON""" + # pylint: disable=import-outside-toplevel + from superset.utils import dashboard_import_export + + data = dashboard_import_export.export_dashboards(db.session) + if print_stdout or not dashboard_file: + print(data) + if dashboard_file: + logger.info("Exporting dashboards to %s", dashboard_file) + with open(dashboard_file, "w") as data_stream: + data_stream.write(data) + + +@click.command() +@with_appcontext +@click.option( + "--datasource-file", + "-f", + default=None, + help="Specify the file to export to", +) +@click.option( + "--print_stdout", + "-p", + is_flag=True, + default=False, + help="Print YAML to stdout", +) +@click.option( + "--back-references", + "-b", + is_flag=True, + default=False, + help="Include parent back references", +) +@click.option( + "--include-defaults", + "-d", + is_flag=True, + default=False, + help="Include fields containing defaults", +) +def legacy_export_datasources( + datasource_file: Optional[str], + print_stdout: bool = False, + back_references: bool = False, + include_defaults: bool = False, +) -> None: + """Export datasources to YAML""" + # pylint: disable=import-outside-toplevel + from superset.utils import dict_import_export - data = dict_import_export.export_schema_to_dict(back_references=back_references) + data = dict_import_export.export_to_dict( + session=db.session, + recursive=True, + back_references=back_references, + include_defaults=include_defaults, + ) + if print_stdout or not datasource_file: yaml.safe_dump(data, sys.stdout, default_flow_style=False) + if datasource_file: + logger.info("Exporting datasources to %s", datasource_file) + with open(datasource_file, "w") as data_stream: + yaml.safe_dump(data, data_stream, default_flow_style=False) + + +@click.command() +@with_appcontext +@click.option( + "--path", + "-p", + help="Path to a single JSON file or path containing multiple JSON " + "files to import (*.json)", +) +@click.option( + "--recursive", + "-r", + is_flag=True, + default=False, + help="recursively search the path for json files", +) +@click.option( + "--username", + "-u", + default=None, + help="Specify the user name to assign dashboards to", +) +def legacy_import_dashboards(path: str, recursive: bool, username: str) -> None: + """Import dashboards from JSON file""" + # pylint: disable=import-outside-toplevel + from superset.commands.dashboard.importers.v0 import ImportDashboardsCommand + + path_object = Path(path) + files: list[Path] = [] + if path_object.is_file(): + files.append(path_object) + elif path_object.exists() and not recursive: + files.extend(path_object.glob("*.json")) + elif path_object.exists() and recursive: + files.extend(path_object.rglob("*.json")) + if username is not None: + g.user = security_manager.find_user(username=username) + contents = {} + for path_ in files: + with open(path_) as file: + contents[path_.name] = file.read() + try: + ImportDashboardsCommand(contents).run() + except Exception: # pylint: disable=broad-except + logger.exception("Error when importing dashboard") + sys.exit(1) + + +@click.command() +@with_appcontext +@click.option( + "--path", + "-p", + help="Path to a single YAML file or path containing multiple YAML " + "files to import (*.yaml or *.yml)", +) +@click.option( + "--sync", + "-s", + "sync", + default="", + help="comma separated list of element types to synchronize " + 'e.g. "metrics,columns" deletes metrics and columns in the DB ' + "that are not specified in the YAML file", +) +@click.option( + "--recursive", + "-r", + is_flag=True, + default=False, + help="recursively search the path for yaml files", +) +def legacy_import_datasources(path: str, sync: str, recursive: bool) -> None: + """Import datasources from YAML""" + # pylint: disable=import-outside-toplevel + from superset.commands.dataset.importers.v0 import ImportDatasetsCommand + + sync_array = sync.split(",") + sync_columns = "columns" in sync_array + sync_metrics = "metrics" in sync_array + + path_object = Path(path) + files: list[Path] = [] + if path_object.is_file(): + files.append(path_object) + elif path_object.exists() and not recursive: + files.extend(path_object.glob("*.yaml")) + files.extend(path_object.glob("*.yml")) + elif path_object.exists() and recursive: + files.extend(path_object.rglob("*.yaml")) + files.extend(path_object.rglob("*.yml")) + contents = {} + for path_ in files: + with open(path_) as file: + contents[path_.name] = file.read() + try: + ImportDatasetsCommand( + contents, sync_columns=sync_columns, sync_metrics=sync_metrics + ).run() + except Exception: # pylint: disable=broad-except + logger.exception("Error when importing dataset") + sys.exit(1) + + +@click.command() +@with_appcontext +@click.option( + "--back-references", + "-b", + is_flag=True, + default=False, + help="Include parent back references", +) +def legacy_export_datasource_schema(back_references: bool) -> None: + """Export datasource YAML schema to stdout""" + # pylint: disable=import-outside-toplevel + from superset.utils import dict_import_export + + data = dict_import_export.export_schema_to_dict(back_references=back_references) + yaml.safe_dump(data, sys.stdout, default_flow_style=False) diff --git a/superset/config.py b/superset/config.py index 474cb0b99b8..4d0eda4b2f0 100644 --- a/superset/config.py +++ b/superset/config.py @@ -432,7 +432,6 @@ class D3Format(TypedDict, total=False): "DASHBOARD_CROSS_FILTERS": True, # deprecated "DASHBOARD_VIRTUALIZATION": True, "GLOBAL_ASYNC_QUERIES": False, - "VERSIONED_EXPORT": True, # deprecated "EMBEDDED_SUPERSET": False, # Enables Alerts and reports new implementation "ALERT_REPORTS": False, diff --git a/superset/dashboards/api.py b/superset/dashboards/api.py index 783543e45de..e719a27fc74 100644 --- a/superset/dashboards/api.py +++ b/superset/dashboards/api.py @@ -23,7 +23,7 @@ from typing import Any, Callable, cast, Optional from zipfile import is_zipfile, ZipFile -from flask import make_response, redirect, request, Response, send_file, url_for +from flask import redirect, request, Response, send_file, url_for from flask_appbuilder import permission_name from flask_appbuilder.api import expose, protect, rison, safe from flask_appbuilder.hooks import before_request @@ -85,7 +85,6 @@ from superset.tasks.utils import get_current_user from superset.utils.screenshots import DashboardScreenshot from superset.utils.urls import get_url_path -from superset.views.base import generate_download_headers from superset.views.base_api import ( BaseSupersetModelRestApi, RelatedFieldFilter, @@ -714,7 +713,7 @@ def bulk_delete(self, **kwargs: Any) -> Response: action=lambda self, *args, **kwargs: f"{self.__class__.__name__}.export", log_to_statsd=False, ) - def export(self, **kwargs: Any) -> Response: # pylint: disable=too-many-locals + def export(self, **kwargs: Any) -> Response: """Download multiple dashboards as YAML files. --- get: @@ -745,50 +744,32 @@ def export(self, **kwargs: Any) -> Response: # pylint: disable=too-many-locals $ref: '#/components/responses/500' """ requested_ids = kwargs["rison"] - token = request.args.get("token") - if is_feature_enabled("VERSIONED_EXPORT"): - timestamp = datetime.now().strftime("%Y%m%dT%H%M%S") - root = f"dashboard_export_{timestamp}" - filename = f"{root}.zip" + timestamp = datetime.now().strftime("%Y%m%dT%H%M%S") + root = f"dashboard_export_{timestamp}" + filename = f"{root}.zip" - buf = BytesIO() - with ZipFile(buf, "w") as bundle: - try: - for file_name, file_content in ExportDashboardsCommand( - requested_ids - ).run(): - with bundle.open(f"{root}/{file_name}", "w") as fp: - fp.write(file_content.encode()) - except DashboardNotFoundError: - return self.response_404() - buf.seek(0) + buf = BytesIO() + with ZipFile(buf, "w") as bundle: + try: + for file_name, file_content in ExportDashboardsCommand( + requested_ids + ).run(): + with bundle.open(f"{root}/{file_name}", "w") as fp: + fp.write(file_content.encode()) + except DashboardNotFoundError: + return self.response_404() + buf.seek(0) - response = send_file( - buf, - mimetype="application/zip", - as_attachment=True, - download_name=filename, - ) - if token: - response.set_cookie(token, "done", max_age=600) - return response - - query = self.datamodel.session.query(Dashboard).filter( - Dashboard.id.in_(requested_ids) + response = send_file( + buf, + mimetype="application/zip", + as_attachment=True, + download_name=filename, ) - query = self._base_filters.apply_all(query) - ids = {item.id for item in query.all()} - if not ids: - return self.response_404() - export = Dashboard.export_dashboards(ids) - resp = make_response(export, 200) - resp.headers["Content-Disposition"] = generate_download_headers("json")[ - "Content-Disposition" - ] - if token: - resp.set_cookie(token, "done", max_age=600) - return resp + if token := request.args.get("token"): + response.set_cookie(token, "done", max_age=600) + return response @expose("//thumbnail//", methods=("GET",)) @protect() diff --git a/superset/datasets/api.py b/superset/datasets/api.py index 809074e10dd..8cc1b2df630 100644 --- a/superset/datasets/api.py +++ b/superset/datasets/api.py @@ -22,14 +22,13 @@ from typing import Any from zipfile import is_zipfile, ZipFile -import yaml from flask import request, Response, send_file from flask_appbuilder.api import expose, protect, rison, safe from flask_appbuilder.models.sqla.interface import SQLAInterface from flask_babel import ngettext from marshmallow import ValidationError -from superset import event_logger, is_feature_enabled +from superset import event_logger from superset.commands.dataset.create import CreateDatasetCommand from superset.commands.dataset.delete import DeleteDatasetCommand from superset.commands.dataset.duplicate import DuplicateDatasetCommand @@ -68,7 +67,7 @@ openapi_spec_methods_override, ) from superset.utils.core import parse_boolean_string -from superset.views.base import DatasourceFilter, generate_download_headers +from superset.views.base import DatasourceFilter from superset.views.base_api import ( BaseSupersetModelRestApi, RelatedFieldFilter, @@ -489,7 +488,7 @@ def delete(self, pk: int) -> Response: action=lambda self, *args, **kwargs: f"{self.__class__.__name__}.export", log_to_statsd=False, ) - def export(self, **kwargs: Any) -> Response: # pylint: disable=too-many-locals + def export(self, **kwargs: Any) -> Response: """Download multiple datasets as YAML files. --- get: @@ -519,49 +518,31 @@ def export(self, **kwargs: Any) -> Response: # pylint: disable=too-many-locals """ requested_ids = kwargs["rison"] - if is_feature_enabled("VERSIONED_EXPORT"): - token = request.args.get("token") - timestamp = datetime.now().strftime("%Y%m%dT%H%M%S") - root = f"dataset_export_{timestamp}" - filename = f"{root}.zip" + timestamp = datetime.now().strftime("%Y%m%dT%H%M%S") + root = f"dataset_export_{timestamp}" + filename = f"{root}.zip" - buf = BytesIO() - with ZipFile(buf, "w") as bundle: - try: - for file_name, file_content in ExportDatasetsCommand( - requested_ids - ).run(): - with bundle.open(f"{root}/{file_name}", "w") as fp: - fp.write(file_content.encode()) - except DatasetNotFoundError: - return self.response_404() - buf.seek(0) + buf = BytesIO() + with ZipFile(buf, "w") as bundle: + try: + for file_name, file_content in ExportDatasetsCommand( + requested_ids + ).run(): + with bundle.open(f"{root}/{file_name}", "w") as fp: + fp.write(file_content.encode()) + except DatasetNotFoundError: + return self.response_404() + buf.seek(0) - response = send_file( - buf, - mimetype="application/zip", - as_attachment=True, - download_name=filename, - ) - if token: - response.set_cookie(token, "done", max_age=600) - return response - - query = self.datamodel.session.query(SqlaTable).filter( - SqlaTable.id.in_(requested_ids) - ) - query = self._base_filters.apply_all(query) - items = query.all() - ids = [item.id for item in items] - if len(ids) != len(requested_ids): - return self.response_404() - - data = [t.export_to_dict() for t in items] - return Response( - yaml.safe_dump(data), - headers=generate_download_headers("yaml"), - mimetype="application/text", + response = send_file( + buf, + mimetype="application/zip", + as_attachment=True, + download_name=filename, ) + if token := request.args.get("token"): + response.set_cookie(token, "done", max_age=600) + return response @expose("/duplicate", methods=("POST",)) @protect() diff --git a/superset/initialization/__init__.py b/superset/initialization/__init__.py index 807f430ee44..2e5f5a716a6 100644 --- a/superset/initialization/__init__.py +++ b/superset/initialization/__init__.py @@ -118,7 +118,6 @@ def init_views(self) -> None: # the global Flask app # # pylint: disable=import-outside-toplevel,too-many-locals,too-many-statements - from superset import security_manager from superset.advanced_data_type.api import AdvancedDataTypeRestApi from superset.annotation_layers.annotations.api import AnnotationRestApi from superset.annotation_layers.api import AnnotationLayerRestApi @@ -327,20 +326,6 @@ def init_views(self) -> None: # # Add links # - appbuilder.add_link( - "Import Dashboards", - label=__("Import Dashboards"), - href="/superset/import_dashboards/", - icon="fa-cloud-upload", - category="Manage", - category_label=__("Manage"), - category_icon="fa-wrench", - cond=lambda: ( - security_manager.can_access("can_import_dashboards", "Superset") - and not feature_flag_manager.is_feature_enabled("VERSIONED_EXPORT") - ), - ) - appbuilder.add_link( "SQL Editor", label=__("SQL Lab"), diff --git a/superset/views/core.py b/superset/views/core.py index 330d517a37d..307cd08c641 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -47,7 +47,6 @@ from superset.async_events.async_query_manager import AsyncQueryTokenException from superset.commands.chart.exceptions import ChartNotFoundError from superset.commands.chart.warm_up_cache import ChartWarmUpCacheCommand -from superset.commands.dashboard.importers.v0 import ImportDashboardsCommand from superset.commands.dashboard.permalink.get import GetDashboardPermalinkCommand from superset.commands.dataset.exceptions import DatasetNotFoundError from superset.commands.explore.form_data.create import CreateFormDataCommand @@ -61,7 +60,6 @@ from superset.dashboards.permalink.exceptions import DashboardPermalinkGetFailedError from superset.exceptions import ( CacheLoadError, - DatabaseNotFound, SupersetException, SupersetSecurityException, ) @@ -345,55 +343,6 @@ def explore_json( except SupersetException as ex: return json_error_response(utils.error_msg_from_exception(ex), 400) - @has_access - @event_logger.log_this - @expose( - "/import_dashboards/", - methods=( - "GET", - "POST", - ), - ) - def import_dashboards(self) -> FlaskResponse: - """Overrides the dashboards using json instances from the file.""" - import_file = request.files.get("file") - if request.method == "POST" and import_file: - success = False - database_id = request.form.get("db_id") - try: - ImportDashboardsCommand( - {import_file.filename: import_file.read()}, database_id - ).run() - success = True - except DatabaseNotFound as ex: - logger.exception(ex) - flash( - _( - "Cannot import dashboard: %(db_error)s.\n" - "Make sure to create the database before " - "importing the dashboard.", - db_error=ex, - ), - "danger", - ) - except Exception as ex: # pylint: disable=broad-except - logger.exception(ex) - flash( - _( - "An unknown error occurred. " - "Please contact your Superset administrator" - ), - "danger", - ) - if success: - flash("Dashboard(s) have been imported", "success") - return redirect("/dashboard/list/") - - databases = db.session.query(Database).all() - return self.render_template( - "superset/import_dashboards.html", databases=databases - ) - @staticmethod def get_redirect_url() -> str: """Assembles the redirect URL to the new endpoint. It also replaces diff --git a/tests/integration_tests/cli_tests.py b/tests/integration_tests/cli_tests.py index 55557ab32de..2441809b0da 100644 --- a/tests/integration_tests/cli_tests.py +++ b/tests/integration_tests/cli_tests.py @@ -16,7 +16,6 @@ # under the License. import importlib -import json import logging from pathlib import Path from unittest import mock @@ -49,69 +48,7 @@ def assert_cli_fails_properly(response, caplog): assert caplog.records[-1].levelname == "ERROR" -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": False}, clear=True -) -@pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") -def test_export_dashboards_original(app_context, fs): - """ - Test that a JSON file is exported. - """ - # pylint: disable=reimported, redefined-outer-name - import superset.cli.importexport # noqa: F811 - - # reload to define export_dashboards correctly based on the - # feature flags - importlib.reload(superset.cli.importexport) - - runner = app.test_cli_runner() - response = runner.invoke( - superset.cli.importexport.export_dashboards, ("-f", "dashboards.json") - ) - - assert response.exit_code == 0 - assert Path("dashboards.json").exists() - - # check that file is valid JSON - with open("dashboards.json") as fp: - contents = fp.read() - json.loads(contents) - - -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": False}, clear=True -) -@pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") -def test_export_datasources_original(app_context, fs): - """ - Test that a YAML file is exported. - """ - # pylint: disable=reimported, redefined-outer-name - import superset.cli.importexport # noqa: F811 - - # reload to define export_dashboards correctly based on the - # feature flags - importlib.reload(superset.cli.importexport) - - runner = app.test_cli_runner() - response = runner.invoke( - superset.cli.importexport.export_datasources, ("-f", "datasources.yaml") - ) - - assert response.exit_code == 0 - - assert Path("datasources.yaml").exists() - - # check that file is valid JSON - with open("datasources.yaml") as fp: - contents = fp.read() - yaml.safe_load(contents) - - @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": True}, clear=True -) def test_export_dashboards_versioned_export(app_context, fs): """ Test that a ZIP file is exported. @@ -133,9 +70,6 @@ def test_export_dashboards_versioned_export(app_context, fs): assert is_zipfile("dashboard_export_20210101T000000.zip") -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": True}, clear=True -) @mock.patch( "superset.commands.dashboard.export.ExportDashboardsCommand.run", side_effect=Exception(), @@ -163,9 +97,6 @@ def test_failing_export_dashboards_versioned_export( @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": True}, clear=True -) def test_export_datasources_versioned_export(app_context, fs): """ Test that a ZIP file is exported. @@ -187,9 +118,6 @@ def test_export_datasources_versioned_export(app_context, fs): assert is_zipfile("dataset_export_20210101T000000.zip") -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": True}, clear=True -) @mock.patch( "superset.commands.dashboard.export.ExportDatasetsCommand.run", side_effect=Exception(), @@ -214,9 +142,6 @@ def test_failing_export_datasources_versioned_export( assert_cli_fails_properly(response, caplog) -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": True}, clear=True -) @mock.patch("superset.commands.dashboard.importers.dispatcher.ImportDashboardsCommand") def test_import_dashboards_versioned_export(import_dashboards_command, app_context, fs): """ @@ -257,9 +182,6 @@ def test_import_dashboards_versioned_export(import_dashboards_command, app_conte import_dashboards_command.assert_called_with(expected_contents, overwrite=True) -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": True}, clear=True -) @mock.patch( "superset.commands.dashboard.importers.dispatcher.ImportDashboardsCommand.run", side_effect=Exception(), @@ -301,9 +223,6 @@ def test_failing_import_dashboards_versioned_export( assert_cli_fails_properly(response, caplog) -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": True}, clear=True -) @mock.patch("superset.commands.dataset.importers.dispatcher.ImportDatasetsCommand") def test_import_datasets_versioned_export(import_datasets_command, app_context, fs): """ @@ -344,120 +263,6 @@ def test_import_datasets_versioned_export(import_datasets_command, app_context, import_datasets_command.assert_called_with(expected_contents, overwrite=True) -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": False}, clear=True -) -@mock.patch("superset.commands.dataset.importers.v0.ImportDatasetsCommand") -def test_import_datasets_sync_argument_columns_metrics( - import_datasets_command, app_context, fs -): - """ - Test that the --sync command line argument syncs dataset in superset - with YAML file. Using both columns and metrics with the --sync flag - """ - # pylint: disable=reimported, redefined-outer-name - import superset.cli.importexport # noqa: F811 - - # reload to define export_datasets correctly based on the - # feature flags - importlib.reload(superset.cli.importexport) - - # write YAML file - with open("dataset.yaml", "w") as fp: - fp.write("hello: world") - - runner = app.test_cli_runner() - response = runner.invoke( - superset.cli.importexport.import_datasources, - ["-p", "dataset.yaml", "-s", "metrics,columns"], - ) - - assert response.exit_code == 0 - expected_contents = {"dataset.yaml": "hello: world"} - import_datasets_command.assert_called_with( - expected_contents, - sync_columns=True, - sync_metrics=True, - ) - - -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": False}, clear=True -) -@mock.patch("superset.commands.dataset.importers.v0.ImportDatasetsCommand") -def test_import_datasets_sync_argument_columns( - import_datasets_command, app_context, fs -): - """ - Test that the --sync command line argument syncs dataset in superset - with YAML file. Using only columns with the --sync flag - """ - # pylint: disable=reimported, redefined-outer-name - import superset.cli.importexport # noqa: F811 - - # reload to define export_datasets correctly based on the - # feature flags - importlib.reload(superset.cli.importexport) - - # write YAML file - with open("dataset.yaml", "w") as fp: - fp.write("hello: world") - - runner = app.test_cli_runner() - response = runner.invoke( - superset.cli.importexport.import_datasources, - ["-p", "dataset.yaml", "-s", "columns"], - ) - - assert response.exit_code == 0 - expected_contents = {"dataset.yaml": "hello: world"} - import_datasets_command.assert_called_with( - expected_contents, - sync_columns=True, - sync_metrics=False, - ) - - -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": False}, clear=True -) -@mock.patch("superset.commands.dataset.importers.v0.ImportDatasetsCommand") -def test_import_datasets_sync_argument_metrics( - import_datasets_command, app_context, fs -): - """ - Test that the --sync command line argument syncs dataset in superset - with YAML file. Using only metrics with the --sync flag - """ - # pylint: disable=reimported, redefined-outer-name - import superset.cli.importexport # noqa: F811 - - # reload to define export_datasets correctly based on the - # feature flags - importlib.reload(superset.cli.importexport) - - # write YAML file - with open("dataset.yaml", "w") as fp: - fp.write("hello: world") - - runner = app.test_cli_runner() - response = runner.invoke( - superset.cli.importexport.import_datasources, - ["-p", "dataset.yaml", "-s", "metrics"], - ) - - assert response.exit_code == 0 - expected_contents = {"dataset.yaml": "hello: world"} - import_datasets_command.assert_called_with( - expected_contents, - sync_columns=False, - sync_metrics=True, - ) - - -@mock.patch.dict( - "superset.cli.lib.feature_flags", {"VERSIONED_EXPORT": True}, clear=True -) @mock.patch( "superset.commands.dataset.importers.dispatcher.ImportDatasetsCommand.run", side_effect=Exception(), diff --git a/tests/integration_tests/dashboards/api_tests.py b/tests/integration_tests/dashboards/api_tests.py index 6b435da997f..d809880bf7d 100644 --- a/tests/integration_tests/dashboards/api_tests.py +++ b/tests/integration_tests/dashboards/api_tests.py @@ -36,7 +36,6 @@ from superset.reports.models import ReportSchedule, ReportScheduleType from superset.models.slice import Slice from superset.utils.core import backend, override_user -from superset.views.base import generate_download_headers from tests.integration_tests.conftest import with_feature_flags from tests.integration_tests.base_api_tests import ApiOwnersTestCaseMixin @@ -1652,11 +1651,6 @@ def test_update_dashboard_not_owned(self): db.session.delete(user_alpha2) db.session.commit() - @patch.dict( - "superset.extensions.feature_flag_manager._feature_flags", - {"VERSIONED_EXPORT": False}, - clear=True, - ) @pytest.mark.usefixtures( "load_world_bank_dashboard_with_slices", "load_birth_names_dashboard_with_slices", @@ -1671,8 +1665,8 @@ def test_export(self): uri = f"api/v1/dashboard/export/?q={prison.dumps(dashboards_ids)}" rv = self.get_assert_metric(uri, "export") - headers = generate_download_headers("json")["Content-Disposition"] + headers = f"attachment; filename=dashboard_export_20220101T000000.zip" assert rv.status_code == 200 assert rv.headers["Content-Disposition"] == headers diff --git a/tests/integration_tests/security_tests.py b/tests/integration_tests/security_tests.py index c9d2a41057b..395aebf29c6 100644 --- a/tests/integration_tests/security_tests.py +++ b/tests/integration_tests/security_tests.py @@ -1348,7 +1348,6 @@ def assert_can_alpha(self, perm_set): self.assert_can_all("CssTemplate", perm_set) self.assert_can_all("Dataset", perm_set) self.assert_can_read("Database", perm_set) - self.assertIn(("can_import_dashboards", "Superset"), perm_set) self.assertIn(("can_this_form_post", "CsvToDatabaseView"), perm_set) self.assertIn(("can_this_form_get", "CsvToDatabaseView"), perm_set) self.assert_can_menu("Manage", perm_set) From 3acda145f1d15bb93db2dcbaf1f283b4b9840e8c Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Fri, 19 Jan 2024 12:46:44 -0700 Subject: [PATCH 06/39] fix: Revert "build(deps): bump @mdx-js/react from 1.6.22 to 3.0.0 in /docs" (#26682) --- docs/package.json | 2 +- docs/yarn.lock | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/docs/package.json b/docs/package.json index 747063d5bad..9bcde81fa72 100644 --- a/docs/package.json +++ b/docs/package.json @@ -25,7 +25,7 @@ "@docusaurus/preset-classic": "^2.4.3", "@emotion/core": "^10.1.1", "@emotion/styled": "^10.0.27", - "@mdx-js/react": "^3.0.0", + "@mdx-js/react": "^1.6.22", "@saucelabs/theme-github-codeblock": "^0.1.1", "@superset-ui/style": "^0.14.23", "@svgr/webpack": "^5.5.0", diff --git a/docs/yarn.lock b/docs/yarn.lock index 60b67abfac1..3a666ab6619 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -3286,13 +3286,6 @@ resolved "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz" integrity sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg== -"@mdx-js/react@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.0.0.tgz#eaccaa8d6a7736b19080aff5a70448a7ba692271" - integrity sha512-nDctevR9KyYFyV+m+/+S4cpzCWHqj+iHDHq3QrsWezcC+B17uZdIWgCguESUkwFhM3n/56KxWVE3V6EokrmONQ== - dependencies: - "@types/mdx" "^2.0.0" - "@mdx-js/util@1.6.22": version "1.6.22" resolved "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz" @@ -3736,11 +3729,6 @@ dependencies: "@types/unist" "*" -"@types/mdx@^2.0.0": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.10.tgz#0d7b57fb1d83e27656156e4ee0dfba96532930e4" - integrity sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg== - "@types/mime@*": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" From 69b57016b3b48b35e20537f07b71c6151e72265b Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Fri, 19 Jan 2024 17:07:38 -0300 Subject: [PATCH 07/39] refactor: Removes the deprecated DASHBOARD_NATIVE_FILTERS feature flag (#26329) --- RESOURCES/FEATURE_FLAGS.md | 1 - UPDATING.md | 1 + .../src/utils/featureFlags.ts | 1 - .../src/plugin/controls/pagination.tsx | 32 +++++----- .../plugin-chart-table/src/controlPanel.tsx | 31 ++++------ .../DashboardBuilder.test.tsx | 44 +++++--------- .../DashboardBuilder/DashboardContainer.tsx | 7 +-- .../components/DashboardBuilder/state.ts | 4 +- .../FiltersBadge/FiltersBadge.test.tsx | 4 -- .../HeaderActionsDropdown.test.tsx | 60 +++---------------- .../Header/HeaderActionsDropdown/index.jsx | 27 +++------ .../FilterBar/FilterBar.test.tsx | 11 +--- .../FilterControls/FilterControls.tsx | 31 +++++----- .../nativeFilters/FilterBar/Header/index.tsx | 11 +--- .../nativeFilters/FilterBar/Horizontal.tsx | 12 +--- .../FilterBar/HorizontalFilterBar.test.tsx | 8 +-- .../nativeFilters/FilterBar/Vertical.tsx | 11 +--- .../components/nativeFilters/selectors.ts | 51 ++++++++-------- .../components/nativeFilters/utils.test.ts | 36 +---------- superset-frontend/src/dataMask/actions.ts | 14 +---- superset/config.py | 1 - .../integration_tests/superset_test_config.py | 1 - 22 files changed, 110 insertions(+), 289 deletions(-) diff --git a/RESOURCES/FEATURE_FLAGS.md b/RESOURCES/FEATURE_FLAGS.md index ef05ab98db5..d782c10cbec 100644 --- a/RESOURCES/FEATURE_FLAGS.md +++ b/RESOURCES/FEATURE_FLAGS.md @@ -84,7 +84,6 @@ These features flags currently default to True and **will be removed in a future [//]: # "PLEASE KEEP THE LIST SORTED ALPHABETICALLY" - DASHBOARD_CROSS_FILTERS -- DASHBOARD_NATIVE_FILTERS - ENABLE_JAVASCRIPT_CONTROLS - GENERIC_CHART_AXES - KV_STORE diff --git a/UPDATING.md b/UPDATING.md index f1f25667368..804b7cdd24f 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -43,6 +43,7 @@ assists people when migrating to a new version. - [26637](https://github.com/apache/superset/issues/26637): Sets the `DRILL_BY` feature flag to `True` by default given that the feature has been tested for a while and reached a stable state. - [26462](https://github.com/apache/superset/issues/26462): Removes the Profile feature given that it's not actively maintained and not widely used. - [26377](https://github.com/apache/superset/pull/26377): Removes the deprecated Redirect API that supported short URLs used before the permalink feature. +- [26329](https://github.com/apache/superset/issues/26329): Removes the deprecated `DASHBOARD_NATIVE_FILTERS` feature flag. The previous value of the feature flag was `True` and now the feature is permanently enabled. ### Potential Downtime diff --git a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts index ba9d0d6680f..f993e451f3b 100644 --- a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts +++ b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts @@ -29,7 +29,6 @@ export enum FeatureFlag { CONFIRM_DASHBOARD_DIFF = 'CONFIRM_DASHBOARD_DIFF', /** @deprecated */ DASHBOARD_CROSS_FILTERS = 'DASHBOARD_CROSS_FILTERS', - DASHBOARD_NATIVE_FILTERS = 'DASHBOARD_NATIVE_FILTERS', DASHBOARD_VIRTUALIZATION = 'DASHBOARD_VIRTUALIZATION', DASHBOARD_RBAC = 'DASHBOARD_RBAC', DATAPANEL_CLOSED_BY_DEFAULT = 'DATAPANEL_CLOSED_BY_DEFAULT', diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/pagination.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/pagination.tsx index bf4c1207174..97a8206a113 100644 --- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/pagination.tsx +++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/pagination.tsx @@ -21,26 +21,22 @@ import { ControlSetItem, ControlSetRow, } from '@superset-ui/chart-controls'; -import { FeatureFlag, isFeatureEnabled, t } from '@superset-ui/core'; +import { t } from '@superset-ui/core'; import { PAGE_SIZE_OPTIONS } from '../../consts'; -export const serverPaginationControlSetRow: ControlSetRow = - isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS) || - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) - ? [ - { - name: 'server_pagination', - config: { - type: 'CheckboxControl', - label: t('Server pagination'), - description: t( - 'Enable server side pagination of results (experimental feature)', - ), - default: false, - }, - }, - ] - : []; +export const serverPaginationControlSetRow: ControlSetRow = [ + { + name: 'server_pagination', + config: { + type: 'CheckboxControl', + label: t('Server pagination'), + description: t( + 'Enable server side pagination of results (experimental feature)', + ), + default: false, + }, + }, +]; export const serverPageLengthControlSetItem: ControlSetItem = { name: 'server_page_length', diff --git a/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx index a59ade460a5..c3fe7282e69 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx @@ -21,11 +21,9 @@ import React from 'react'; import { ChartDataResponseResult, ensureIsArray, - FeatureFlag, GenericDataType, hasGenericChartAxes, isAdhocColumn, - isFeatureEnabled, isPhysicalColumn, QueryFormColumn, QueryMode, @@ -290,22 +288,19 @@ const config: ControlPanelConfig = { }, }, ], - isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS) || - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) - ? [ - { - name: 'server_pagination', - config: { - type: 'CheckboxControl', - label: t('Server pagination'), - description: t( - 'Enable server side pagination of results (experimental feature)', - ), - default: false, - }, - }, - ] - : [], + [ + { + name: 'server_pagination', + config: { + type: 'CheckboxControl', + label: t('Server pagination'), + description: t( + 'Enable server side pagination of results (experimental feature)', + ), + default: false, + }, + }, + ], [ { name: 'row_limit', diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx index 179c03c996f..08cfed16f62 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx @@ -20,7 +20,6 @@ import React from 'react'; import fetchMock from 'fetch-mock'; import { render } from 'spec/helpers/testing-library'; import { fireEvent, within } from '@testing-library/react'; -import * as uiCore from '@superset-ui/core'; import DashboardBuilder from 'src/dashboard/components/DashboardBuilder/DashboardBuilder'; import useStoredSidebarWidth from 'src/components/ResizableSidebar/useStoredSidebarWidth'; import { @@ -247,35 +246,20 @@ describe('DashboardBuilder', () => { expect(await findByAltText('Loading...')).toBeVisible(); }); - describe('when nativeFiltersEnabled', () => { - let isFeatureEnabledMock: jest.MockInstance; - beforeAll(() => { - isFeatureEnabledMock = jest - .spyOn(uiCore, 'isFeatureEnabled') - .mockImplementation( - flag => flag === uiCore.FeatureFlag.DASHBOARD_NATIVE_FILTERS, - ); - }); - - afterAll(() => { - isFeatureEnabledMock.mockRestore(); - }); - - it('should set FilterBar width by useStoredSidebarWidth', () => { - const expectedValue = 200; - const setter = jest.fn(); - (useStoredSidebarWidth as jest.Mock).mockImplementation(() => [ - expectedValue, - setter, - ]); - const { getByTestId } = setup({ - dashboardInfo: { - ...mockState.dashboardInfo, - dash_edit_perm: true, - }, - }); - const filterbar = getByTestId('dashboard-filters-panel'); - expect(filterbar).toHaveStyleRule('width', `${expectedValue}px`); + it('should set FilterBar width by useStoredSidebarWidth', () => { + const expectedValue = 200; + const setter = jest.fn(); + (useStoredSidebarWidth as jest.Mock).mockImplementation(() => [ + expectedValue, + setter, + ]); + const { getByTestId } = setup({ + dashboardInfo: { + ...mockState.dashboardInfo, + dash_edit_perm: true, + }, }); + const filterbar = getByTestId('dashboard-filters-panel'); + expect(filterbar).toHaveStyleRule('width', `${expectedValue}px`); }); }); diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx index f3f214468e8..5f03eeaf1a8 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx @@ -21,11 +21,9 @@ import React, { FC, useCallback, useEffect, useMemo, useRef } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { - FeatureFlag, Filter, Filters, getCategoricalSchemeRegistry, - isFeatureEnabled, SupersetClient, useComponentDidUpdate, } from '@superset-ui/core'; @@ -104,10 +102,7 @@ const DashboardContainer: FC = ({ topLevelTabs }) => { }, [dashboardLayout, directPathToChild]); useEffect(() => { - if ( - !isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) || - nativeFilterScopes.length === 0 - ) { + if (nativeFilterScopes.length === 0) { return; } const scopes = nativeFilterScopes.map(filterScope => { diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts b/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts index 1936e331c3d..9b8af1dda30 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts @@ -17,7 +17,6 @@ * under the License. */ import { useSelector } from 'react-redux'; -import { isFeatureEnabled, FeatureFlag } from '@superset-ui/core'; import { useCallback, useEffect, useState } from 'react'; import { URL_PARAMS } from 'src/constants'; import { getUrlParam } from 'src/utils/urlUtils'; @@ -42,8 +41,7 @@ export const useNativeFilters = () => { ); const nativeFiltersEnabled = - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && - (canEdit || (!canEdit && filterValues.length !== 0)); + canEdit || (!canEdit && filterValues.length !== 0); const requiredFirstFilter = filterValues.filter( filter => filter.requiredFirst, diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/FiltersBadge.test.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/FiltersBadge.test.tsx index 058c5329b6b..c5e0d0df9c3 100644 --- a/superset-frontend/src/dashboard/components/FiltersBadge/FiltersBadge.test.tsx +++ b/superset-frontend/src/dashboard/components/FiltersBadge/FiltersBadge.test.tsx @@ -133,10 +133,6 @@ describe('FiltersBadge', () => { }); it('shows the indicator when filters have been applied', () => { - // @ts-ignore - global.featureFlags = { - [SupersetUI.FeatureFlag.DASHBOARD_NATIVE_FILTERS]: true, - }; const store = getMockStoreWithNativeFilters(); // start with basic dashboard state, dispatch an event to simulate query completion store.dispatch({ diff --git a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx index deea296d4c0..cefdbafa73d 100644 --- a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx +++ b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx @@ -24,12 +24,8 @@ import userEvent from '@testing-library/user-event'; import fetchMock from 'fetch-mock'; import { HeaderDropdownProps } from 'src/dashboard/components/Header/types'; import injectCustomCss from 'src/dashboard/util/injectCustomCss'; -import { FeatureFlag } from '@superset-ui/core'; -import * as uiCore from '@superset-ui/core'; import HeaderActionsDropdown from '.'; -let isFeatureEnabledMock: jest.MockInstance; - const createProps = () => ({ addSuccessToast: jest.fn(), addDangerToast: jest.fn(), @@ -135,7 +131,7 @@ test('should render the menu items', async () => { test('should render the menu items in edit mode', async () => { setup(editModeOnProps); - expect(screen.getAllByRole('menuitem')).toHaveLength(5); + expect(screen.getAllByRole('menuitem')).toHaveLength(4); expect(screen.getByText('Set auto-refresh interval')).toBeInTheDocument(); expect(screen.getByText('Edit properties')).toBeInTheDocument(); expect(screen.getByText('Edit CSS')).toBeInTheDocument(); @@ -150,56 +146,14 @@ test('should render the menu items in Embedded mode', async () => { expect(screen.getByText('Set auto-refresh interval')).toBeInTheDocument(); }); -describe('with native filters feature flag disabled', () => { - beforeAll(() => { - isFeatureEnabledMock = jest - .spyOn(uiCore, 'isFeatureEnabled') - .mockImplementation( - (featureFlag: FeatureFlag) => - featureFlag !== FeatureFlag.DASHBOARD_NATIVE_FILTERS, - ); - }); - - afterAll(() => { - // @ts-ignore - isFeatureEnabledMock.restore(); - }); - - it('should render filter mapping in edit mode if explicit filter scopes undefined', async () => { - setup(editModeOnProps); - expect(screen.getByText('Set filter mapping')).toBeInTheDocument(); - }); - - it('should render filter mapping in edit mode if explicit filter scopes defined', async () => { - setup(editModeOnWithFilterScopesProps); - expect(screen.getByText('Set filter mapping')).toBeInTheDocument(); - }); +test('should not render filter mapping in edit mode if explicit filter scopes undefined', async () => { + setup(editModeOnProps); + expect(screen.queryByText('Set filter mapping')).not.toBeInTheDocument(); }); -describe('with native filters feature flag enabled', () => { - beforeAll(() => { - isFeatureEnabledMock = jest - .spyOn(uiCore, 'isFeatureEnabled') - .mockImplementation( - (featureFlag: FeatureFlag) => - featureFlag === FeatureFlag.DASHBOARD_NATIVE_FILTERS, - ); - }); - - afterAll(() => { - // @ts-ignore - isFeatureEnabledMock.restore(); - }); - - it('should not render filter mapping in edit mode if explicit filter scopes undefined', async () => { - setup(editModeOnProps); - expect(screen.queryByText('Set filter mapping')).not.toBeInTheDocument(); - }); - - it('should render filter mapping in edit mode if explicit filter scopes defined', async () => { - setup(editModeOnWithFilterScopesProps); - expect(screen.getByText('Set filter mapping')).toBeInTheDocument(); - }); +test('should render filter mapping in edit mode if explicit filter scopes defined', async () => { + setup(editModeOnWithFilterScopesProps); + expect(screen.getByText('Set filter mapping')).toBeInTheDocument(); }); test('should show the share actions', async () => { diff --git a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx index b0d3fc251e9..f1a3f59039b 100644 --- a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx +++ b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx @@ -19,12 +19,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { isEmpty } from 'lodash'; -import { - isFeatureEnabled, - FeatureFlag, - SupersetClient, - t, -} from '@superset-ui/core'; +import { SupersetClient, t } from '@superset-ui/core'; import { Menu } from 'src/components/Menu'; import { URL_PARAMS } from 'src/constants'; import ShareMenuItems from 'src/dashboard/components/menu/ShareMenuItems'; @@ -361,18 +356,14 @@ class HeaderActionsDropdown extends React.PureComponent { ) ) : null} - {editMode && - !( - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && - isEmpty(dashboardInfo?.metadata?.filter_scopes) - ) && ( - - - - )} + {editMode && !isEmpty(dashboardInfo?.metadata?.filter_scopes) && ( + + + + )} (FILTERS_CONFIG_MODAL_TEST_ID, true); const FILTER_NAME = 'Time filter 1'; -// @ts-ignore -global.featureFlags = { - [FeatureFlag.DASHBOARD_NATIVE_FILTERS]: true, -}; - const addFilterFlow = async () => { // open filter config modal userEvent.click(screen.getByTestId(getTestId('collapsable'))); @@ -291,10 +286,6 @@ describe('FilterBar', () => { }); it('create filter and apply it flow', async () => { - // @ts-ignore - global.featureFlags = { - [FeatureFlag.DASHBOARD_NATIVE_FILTERS]: true, - }; renderWrapper(openedBarProps, stateWithoutNativeFilters); expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled(); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx index c74d1b08a96..629ec75cb00 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx @@ -212,23 +212,20 @@ const FilterControls: FC = ({ selectedCrossFilters.at(-1), ), })); - if (isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS)) { - const nativeFiltersInScope = filtersInScope.map((filter, index) => ({ - id: filter.id, - element: ( -
- {renderer(filter, index)} -
- ), - })); - return [...crossFilters, ...nativeFiltersInScope]; - } - return [...crossFilters]; + const nativeFiltersInScope = filtersInScope.map((filter, index) => ({ + id: filter.id, + element: ( +
+ {renderer(filter, index)} +
+ ), + })); + return [...crossFilters, ...nativeFiltersInScope]; }, [filtersInScope, renderer, rendererCrossFilter, selectedCrossFilters]); const renderHorizontalContent = () => ( diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx index d839cd4d394..7cd4877d11e 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx @@ -17,14 +17,7 @@ * under the License. */ /* eslint-disable no-param-reassign */ -import { - FeatureFlag, - css, - isFeatureEnabled, - styled, - t, - useTheme, -} from '@superset-ui/core'; +import { css, styled, t, useTheme } from '@superset-ui/core'; import React, { FC, useMemo } from 'react'; import Icons from 'src/components/Icons'; import Button from 'src/components/Button'; @@ -124,7 +117,7 @@ const Header: FC = ({ toggleFiltersBar }) => { - {canEdit && isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && ( + {canEdit && ( = ({ : []; const hasFilters = filterValues.length > 0 || selectedCrossFilters.length > 0; - const actionsElement = useMemo( - () => - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) ? actions : null, - [actions], - ); - return ( @@ -143,7 +137,7 @@ const HorizontalFilterBar: React.FC = ({ ) : ( <> - {canEdit && isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && ( + {canEdit && ( = ({ onFilterSelectionChange={onSelectionChange} /> )} - {actionsElement} + {actions} )} diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/HorizontalFilterBar.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/HorizontalFilterBar.test.tsx index efad04a0388..09625151a2c 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/HorizontalFilterBar.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/HorizontalFilterBar.test.tsx @@ -16,8 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - -import { FeatureFlag, NativeFilterType } from '@superset-ui/core'; +import { NativeFilterType } from '@superset-ui/core'; import React from 'react'; import { render, screen, waitFor } from 'spec/helpers/testing-library'; import HorizontalBar from './Horizontal'; @@ -32,11 +31,6 @@ const defaultProps = { onSelectionChange: jest.fn(), }; -// @ts-ignore -global.featureFlags = { - [FeatureFlag.DASHBOARD_NATIVE_FILTERS]: true, -}; - const renderWrapper = (overrideProps?: Record) => waitFor(() => render(, { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx index b2da4605029..998c460dfc0 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx @@ -196,12 +196,6 @@ const VerticalFilterBar: React.FC = ({ [], ); - const actionsElement = useMemo( - () => - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) ? actions : null, - [actions], - ); - return ( = ({
<> {crossFilters} - {isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && - filterControls} + {filterControls}
)} - {actionsElement} + {actions}
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/selectors.ts b/superset-frontend/src/dashboard/components/nativeFilters/selectors.ts index a8bfafd8341..ae8a2f7a4df 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/selectors.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/selectors.ts @@ -358,34 +358,31 @@ export const selectNativeIndicatorsForChart = ( return cachedNativeIndicatorsForChart[chartId]; } - let nativeFilterIndicators: any = []; - if (isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS)) { - nativeFilterIndicators = - nativeFilters && - Object.values(nativeFilters) - .filter( - nativeFilter => - nativeFilter.type === NativeFilterType.NATIVE_FILTER && - nativeFilter.chartsInScope?.includes(chartId), - ) - .map(nativeFilter => { - const column = nativeFilter.targets?.[0]?.column?.name; - const filterState = dataMask[nativeFilter.id]?.filterState; - const label = extractLabel(filterState); - return { + const nativeFilterIndicators = + nativeFilters && + Object.values(nativeFilters) + .filter( + nativeFilter => + nativeFilter.type === NativeFilterType.NATIVE_FILTER && + nativeFilter.chartsInScope?.includes(chartId), + ) + .map(nativeFilter => { + const column = nativeFilter.targets?.[0]?.column?.name; + const filterState = dataMask[nativeFilter.id]?.filterState; + const label = extractLabel(filterState); + return { + column, + name: nativeFilter.name, + path: [nativeFilter.id], + status: getStatus({ + label, column, - name: nativeFilter.name, - path: [nativeFilter.id], - status: getStatus({ - label, - column, - rejectedColumns, - appliedColumns, - }), - value: label, - }; - }); - } + rejectedColumns, + appliedColumns, + }), + value: label, + }; + }); let crossFilterIndicators: any = []; if (isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS)) { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/utils.test.ts b/superset-frontend/src/dashboard/components/nativeFilters/utils.test.ts index 0388565595f..be636bf17a4 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/utils.test.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/utils.test.ts @@ -55,41 +55,7 @@ describe('nativeFilterGate', () => { }); }); - describe('with only native filters feature flag enabled', () => { - beforeAll(() => { - isFeatureEnabledMock = jest - .spyOn(uiCore, 'isFeatureEnabled') - .mockImplementation( - (featureFlag: FeatureFlag) => - featureFlag === FeatureFlag.DASHBOARD_NATIVE_FILTERS, - ); - }); - - afterAll(() => { - // @ts-ignore - isFeatureEnabledMock.restore(); - }); - - it('should return true for regular chart', () => { - expect(nativeFilterGate([])).toEqual(true); - }); - - it('should return true for cross filter chart', () => { - expect(nativeFilterGate([Behavior.INTERACTIVE_CHART])).toEqual(true); - }); - - it('should return false for native filter chart with cross filter support', () => { - expect( - nativeFilterGate([Behavior.NATIVE_FILTER, Behavior.INTERACTIVE_CHART]), - ).toEqual(false); - }); - - it('should return false for native filter behavior', () => { - expect(nativeFilterGate([Behavior.NATIVE_FILTER])).toEqual(false); - }); - }); - - describe('with native filters and experimental feature flag enabled', () => { + describe('with cross filters and experimental feature flag enabled', () => { beforeAll(() => { isFeatureEnabledMock = jest .spyOn(uiCore, 'isFeatureEnabled') diff --git a/superset-frontend/src/dataMask/actions.ts b/superset-frontend/src/dataMask/actions.ts index 7c41703a10b..cb7ed393d73 100644 --- a/superset-frontend/src/dataMask/actions.ts +++ b/superset-frontend/src/dataMask/actions.ts @@ -16,13 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { - DataMask, - isFeatureEnabled, - FeatureFlag, - FilterConfiguration, - Filters, -} from '@superset-ui/core'; +import { DataMask, FilterConfiguration, Filters } from '@superset-ui/core'; import { getInitialDataMask } from './reducer'; export const CLEAR_DATA_MASK_STATE = 'CLEAR_DATA_MASK_STATE'; @@ -73,14 +67,10 @@ export function updateDataMask( filterId: string | number, dataMask: DataMask, ): UpdateDataMask { - // Only apply data mask if one of the relevant features is enabled - const isFeatureFlagActive = - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) || - isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS); return { type: UPDATE_DATA_MASK, filterId, - dataMask: isFeatureFlagActive ? dataMask : {}, + dataMask, }; } diff --git a/superset/config.py b/superset/config.py index 4d0eda4b2f0..1d6409deb8a 100644 --- a/superset/config.py +++ b/superset/config.py @@ -428,7 +428,6 @@ class D3Format(TypedDict, total=False): "LISTVIEWS_DEFAULT_CARD_VIEW": False, # When True, this escapes HTML (rather than rendering it) in Markdown components "ESCAPE_MARKDOWN_HTML": False, - "DASHBOARD_NATIVE_FILTERS": True, # deprecated "DASHBOARD_CROSS_FILTERS": True, # deprecated "DASHBOARD_VIRTUALIZATION": True, "GLOBAL_ASYNC_QUERIES": False, diff --git a/tests/integration_tests/superset_test_config.py b/tests/integration_tests/superset_test_config.py index 89287be663e..2aeeb3004e1 100644 --- a/tests/integration_tests/superset_test_config.py +++ b/tests/integration_tests/superset_test_config.py @@ -69,7 +69,6 @@ "SHARE_QUERIES_VIA_KV_STORE": True, "ENABLE_TEMPLATE_PROCESSING": True, "ALERT_REPORTS": True, - "DASHBOARD_NATIVE_FILTERS": True, "DRILL_TO_DETAIL": True, "DRILL_BY": True, "HORIZONTAL_FILTER_BAR": True, From effd73f2cc5bd4afbc830ae98feca568c773e4a5 Mon Sep 17 00:00:00 2001 From: Pieter Ennes Date: Sat, 20 Jan 2024 00:00:43 +0100 Subject: [PATCH 08/39] fix: Catch ImportErrors for Google SDKs (#25550) --- superset/db_engine_specs/bigquery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset/db_engine_specs/bigquery.py b/superset/db_engine_specs/bigquery.py index f3b9c486e98..8e7ed0bf7d0 100644 --- a/superset/db_engine_specs/bigquery.py +++ b/superset/db_engine_specs/bigquery.py @@ -52,7 +52,7 @@ from google.oauth2 import service_account dependencies_installed = True -except ModuleNotFoundError: +except ImportError: dependencies_installed = False try: From 12838038449d4c4efdad749a2fe8f6d936e4375e Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Fri, 19 Jan 2024 15:12:54 -0800 Subject: [PATCH 09/39] chore: add unique constraint to tagged_objects (#26654) --- superset/daos/tag.py | 21 ++++- superset/migrations/__init__.py | 7 ++ superset/migrations/migration_utils.py | 46 +++++++++ ...e3017c6_tagged_object_unique_constraint.py | 89 ++++++++++++++++++ ...18_12-12_15a2c68a2e6b_merging_two_heads.py | 38 ++++++++ .../2024-01-19_08-42_1cf8e4344e2b_merging.py | 38 ++++++++ superset/tags/models.py | 93 +++++++++++++++---- tests/integration_tests/tags/api_tests.py | 22 +++-- .../integration_tests/tags/commands_tests.py | 12 +-- 9 files changed, 335 insertions(+), 31 deletions(-) create mode 100644 superset/migrations/migration_utils.py create mode 100644 superset/migrations/versions/2024-01-17_13-09_96164e3017c6_tagged_object_unique_constraint.py create mode 100644 superset/migrations/versions/2024-01-18_12-12_15a2c68a2e6b_merging_two_heads.py create mode 100644 superset/migrations/versions/2024-01-19_08-42_1cf8e4344e2b_merging.py diff --git a/superset/daos/tag.py b/superset/daos/tag.py index e4aa8918164..46a1d2538f1 100644 --- a/superset/daos/tag.py +++ b/superset/daos/tag.py @@ -51,14 +51,29 @@ def create_custom_tagged_objects( object_type: ObjectType, object_id: int, tag_names: list[str] ) -> None: tagged_objects = [] - for name in tag_names: + + # striping and de-dupping + clean_tag_names: set[str] = {tag.strip() for tag in tag_names} + + for name in clean_tag_names: type_ = TagType.custom - tag_name = name.strip() - tag = TagDAO.get_by_name(tag_name, type_) + tag = TagDAO.get_by_name(name, type_) tagged_objects.append( TaggedObject(object_id=object_id, object_type=object_type, tag=tag) ) + # Check if the association already exists + existing_tagged_object = ( + db.session.query(TaggedObject) + .filter_by(object_id=object_id, object_type=object_type, tag=tag) + .first() + ) + + if not existing_tagged_object: + tagged_objects.append( + TaggedObject(object_id=object_id, object_type=object_type, tag=tag) + ) + db.session.add_all(tagged_objects) db.session.commit() diff --git a/superset/migrations/__init__.py b/superset/migrations/__init__.py index 13a83393a91..b083f44bb43 100644 --- a/superset/migrations/__init__.py +++ b/superset/migrations/__init__.py @@ -14,3 +14,10 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. + +import os +import sys + +# hack to be able to import / reuse migration_utils.py in revisions +module_dir = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(module_dir) diff --git a/superset/migrations/migration_utils.py b/superset/migrations/migration_utils.py new file mode 100644 index 00000000000..c754669a1af --- /dev/null +++ b/superset/migrations/migration_utils.py @@ -0,0 +1,46 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from alembic.operations import BatchOperations, Operations + +naming_convention = { + "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", + "uq": "uq_%(table_name)s_%(column_0_name)s", +} + + +def create_unique_constraint( + op: Operations, index_id: str, table_name: str, uix_columns: list[str] +) -> None: + with op.batch_alter_table( + table_name, naming_convention=naming_convention + ) as batch_op: + batch_op.create_unique_constraint(index_id, uix_columns) + + +def drop_unique_constraint(op: Operations, index_id: str, table_name: str) -> None: + dialect = op.get_bind().dialect.name + + with op.batch_alter_table( + table_name, naming_convention=naming_convention + ) as batch_op: + if dialect == "mysql": + # MySQL requires specifying the type of constraint + batch_op.drop_constraint(index_id, type_="unique") + else: + # For other databases, a standard drop_constraint call is sufficient + batch_op.drop_constraint(index_id) diff --git a/superset/migrations/versions/2024-01-17_13-09_96164e3017c6_tagged_object_unique_constraint.py b/superset/migrations/versions/2024-01-17_13-09_96164e3017c6_tagged_object_unique_constraint.py new file mode 100644 index 00000000000..0b67ad5024f --- /dev/null +++ b/superset/migrations/versions/2024-01-17_13-09_96164e3017c6_tagged_object_unique_constraint.py @@ -0,0 +1,89 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +import enum + +import migration_utils as utils +import sqlalchemy as sa +from alembic import op +from sqlalchemy import Column, Enum, Integer, MetaData, Table +from sqlalchemy.sql import and_, func, select + +# revision identifiers, used by Alembic. +revision = "96164e3017c6" +down_revision = "59a1450b3c10" + + +class ObjectType(enum.Enum): + # pylint: disable=invalid-name + query = 1 + chart = 2 + dashboard = 3 + dataset = 4 + + +# Define the tagged_object table structure +metadata = MetaData() +tagged_object_table = Table( + "tagged_object", + metadata, + Column("id", Integer, primary_key=True), + Column("tag_id", Integer), + Column("object_id", Integer), + Column("object_type", Enum(ObjectType)), # Replace ObjectType with your Enum +) + +index_id = "uix_tagged_object" +table_name = "tagged_object" +uix_columns = ["tag_id", "object_id", "object_type"] + + +def upgrade(): + bind = op.get_bind() # Get the database connection bind + + # Reflect the current database state to get existing tables + metadata.reflect(bind=bind) + + # Delete duplicates if any + min_id_subquery = ( + select( + [ + func.min(tagged_object_table.c.id).label("min_id"), + tagged_object_table.c.tag_id, + tagged_object_table.c.object_id, + tagged_object_table.c.object_type, + ] + ) + .group_by( + tagged_object_table.c.tag_id, + tagged_object_table.c.object_id, + tagged_object_table.c.object_type, + ) + .alias("min_ids") + ) + + delete_query = tagged_object_table.delete().where( + tagged_object_table.c.id.notin_(select([min_id_subquery.c.min_id])) + ) + + bind.execute(delete_query) + + # Create unique constraint + utils.create_unique_constraint(op, index_id, table_name, uix_columns) + + +def downgrade(): + utils.drop_unique_constraint(op, index_id, table_name) diff --git a/superset/migrations/versions/2024-01-18_12-12_15a2c68a2e6b_merging_two_heads.py b/superset/migrations/versions/2024-01-18_12-12_15a2c68a2e6b_merging_two_heads.py new file mode 100644 index 00000000000..7904d9298df --- /dev/null +++ b/superset/migrations/versions/2024-01-18_12-12_15a2c68a2e6b_merging_two_heads.py @@ -0,0 +1,38 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""merging two heads + +Revision ID: 15a2c68a2e6b +Revises: ('96164e3017c6', 'a32e0c4d8646') +Create Date: 2024-01-18 12:12:52.174742 + +""" + +# revision identifiers, used by Alembic. +revision = "15a2c68a2e6b" +down_revision = ("96164e3017c6", "a32e0c4d8646") + +import sqlalchemy as sa +from alembic import op + + +def upgrade(): + pass + + +def downgrade(): + pass diff --git a/superset/migrations/versions/2024-01-19_08-42_1cf8e4344e2b_merging.py b/superset/migrations/versions/2024-01-19_08-42_1cf8e4344e2b_merging.py new file mode 100644 index 00000000000..9ac2a9b24ff --- /dev/null +++ b/superset/migrations/versions/2024-01-19_08-42_1cf8e4344e2b_merging.py @@ -0,0 +1,38 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""merging + +Revision ID: 1cf8e4344e2b +Revises: ('e863403c0c50', '15a2c68a2e6b') +Create Date: 2024-01-19 08:42:37.694192 + +""" + +# revision identifiers, used by Alembic. +revision = "1cf8e4344e2b" +down_revision = ("e863403c0c50", "15a2c68a2e6b") + +import sqlalchemy as sa +from alembic import op + + +def upgrade(): + pass + + +def downgrade(): + pass diff --git a/superset/tags/models.py b/superset/tags/models.py index bae4417507b..1e8ca7de1a3 100644 --- a/superset/tags/models.py +++ b/superset/tags/models.py @@ -21,10 +21,21 @@ from flask import escape from flask_appbuilder import Model -from sqlalchemy import Column, Enum, ForeignKey, Integer, orm, String, Table, Text +from sqlalchemy import ( + Column, + Enum, + exists, + ForeignKey, + Integer, + orm, + String, + Table, + Text, +) from sqlalchemy.engine.base import Connection from sqlalchemy.orm import relationship, sessionmaker from sqlalchemy.orm.mapper import Mapper +from sqlalchemy.schema import UniqueConstraint from superset import security_manager from superset.models.helpers import AuditMixinNullable @@ -110,6 +121,14 @@ class TaggedObject(Model, AuditMixinNullable): object_type = Column(Enum(ObjectType)) tag = relationship("Tag", back_populates="objects", overlaps="tags") + __table_args__ = ( + UniqueConstraint( + "tag_id", "object_id", "object_type", name="uix_tagged_object" + ), + ) + + def __str__(self) -> str: + return f"" def get_tag(name: str, session: orm.Session, type_: TagType) -> Tag: @@ -138,7 +157,7 @@ def get_object_type(class_name: str) -> ObjectType: class ObjectUpdater: - object_type: str | None = None + object_type: str = "default" @classmethod def get_owners_ids( @@ -146,6 +165,19 @@ def get_owners_ids( ) -> list[int]: raise NotImplementedError("Subclass should implement `get_owners_ids`") + @classmethod + def get_owner_tag_ids( + cls, + session: orm.Session, + target: Dashboard | FavStar | Slice | Query | SqlaTable, + ) -> set[int]: + tag_ids = set() + for owner_id in cls.get_owners_ids(target): + name = f"owner:{owner_id}" + tag = get_tag(name, session, TagType.owner) + tag_ids.add(tag.id) + return tag_ids + @classmethod def _add_owners( cls, @@ -153,10 +185,28 @@ def _add_owners( target: Dashboard | FavStar | Slice | Query | SqlaTable, ) -> None: for owner_id in cls.get_owners_ids(target): - name = f"owner:{owner_id}" + name: str = f"owner:{owner_id}" tag = get_tag(name, session, TagType.owner) + cls.add_tag_object_if_not_tagged( + session, tag_id=tag.id, object_id=target.id, object_type=cls.object_type + ) + + @classmethod + def add_tag_object_if_not_tagged( + cls, session: orm.Session, tag_id: int, object_id: int, object_type: str + ) -> None: + # Check if the object is already tagged + exists_query = exists().where( + TaggedObject.tag_id == tag_id, + TaggedObject.object_id == object_id, + TaggedObject.object_type == object_type, + ) + already_tagged = session.query(exists_query).scalar() + + # Add TaggedObject to the session if it isn't already tagged + if not already_tagged: tagged_object = TaggedObject( - tag_id=tag.id, object_id=target.id, object_type=cls.object_type + tag_id=tag_id, object_id=object_id, object_type=object_type ) session.add(tagged_object) @@ -173,10 +223,9 @@ def after_insert( # add `type:` tags tag = get_tag(f"type:{cls.object_type}", session, TagType.type) - tagged_object = TaggedObject( - tag_id=tag.id, object_id=target.id, object_type=cls.object_type + cls.add_tag_object_if_not_tagged( + session, tag_id=tag.id, object_id=target.id, object_type=cls.object_type ) - session.add(tagged_object) session.commit() @classmethod @@ -187,23 +236,35 @@ def after_update( target: Dashboard | FavStar | Slice | Query | SqlaTable, ) -> None: with Session(bind=connection) as session: - # delete current `owner:` tags - query = ( - session.query(TaggedObject.id) + # Fetch current owner tags + existing_tags = ( + session.query(TaggedObject) .join(Tag) .filter( TaggedObject.object_type == cls.object_type, TaggedObject.object_id == target.id, Tag.type == TagType.owner, ) + .all() ) - ids = [row[0] for row in query] - session.query(TaggedObject).filter(TaggedObject.id.in_(ids)).delete( - synchronize_session=False - ) + existing_owner_tag_ids = {tag.tag_id for tag in existing_tags} - # add `owner:` tags - cls._add_owners(session, target) + # Determine new owner IDs + new_owner_tag_ids = cls.get_owner_tag_ids(session, target) + + # Add missing tags + for owner_tag_id in new_owner_tag_ids - existing_owner_tag_ids: + tagged_object = TaggedObject( + tag_id=owner_tag_id, + object_id=target.id, + object_type=cls.object_type, + ) + session.add(tagged_object) + + # Remove unnecessary tags + for tag in existing_tags: + if tag.tag_id not in new_owner_tag_ids: + session.delete(tag) session.commit() @classmethod diff --git a/tests/integration_tests/tags/api_tests.py b/tests/integration_tests/tags/api_tests.py index 863288a3e73..d79261c2a30 100644 --- a/tests/integration_tests/tags/api_tests.py +++ b/tests/integration_tests/tags/api_tests.py @@ -577,15 +577,25 @@ def test_post_bulk_tag(self): result = TagDAO.get_tagged_objects_for_tags(tags, ["chart"]) assert len(result) == 1 - tagged_objects = db.session.query(TaggedObject).filter( - TaggedObject.object_id == dashboard.id, - TaggedObject.object_type == ObjectType.dashboard, + tagged_objects = ( + db.session.query(TaggedObject) + .join(Tag) + .filter( + TaggedObject.object_id == dashboard.id, + TaggedObject.object_type == ObjectType.dashboard, + Tag.type == TagType.custom, + ) ) assert tagged_objects.count() == 2 - tagged_objects = db.session.query(TaggedObject).filter( - TaggedObject.object_id == chart.id, - TaggedObject.object_type == ObjectType.chart, + tagged_objects = ( + db.session.query(TaggedObject) + .join(Tag) + .filter( + TaggedObject.object_id == chart.id, + TaggedObject.object_type == ObjectType.chart, + Tag.type == TagType.custom, + ) ) assert tagged_objects.count() == 2 diff --git a/tests/integration_tests/tags/commands_tests.py b/tests/integration_tests/tags/commands_tests.py index 83762f8f6e8..3644c076e6a 100644 --- a/tests/integration_tests/tags/commands_tests.py +++ b/tests/integration_tests/tags/commands_tests.py @@ -63,7 +63,7 @@ def test_create_custom_tag_command(self): example_dashboard = ( db.session.query(Dashboard).filter_by(slug="world_health").one() ) - example_tags = ["create custom tag example 1", "create custom tag example 2"] + example_tags = {"create custom tag example 1", "create custom tag example 2"} command = CreateCustomTagCommand( ObjectType.dashboard.value, example_dashboard.id, example_tags ) @@ -78,7 +78,7 @@ def test_create_custom_tag_command(self): ) .all() ) - assert example_tags == [tag.name for tag in created_tags] + assert example_tags == {tag.name for tag in created_tags} # cleanup tags = db.session.query(Tag).filter(Tag.name.in_(example_tags)) @@ -99,7 +99,7 @@ def test_delete_tags_command(self): .filter_by(dashboard_title="World Bank's Data") .one() ) - example_tags = ["create custom tag example 1", "create custom tag example 2"] + example_tags = {"create custom tag example 1", "create custom tag example 2"} command = CreateCustomTagCommand( ObjectType.dashboard.value, example_dashboard.id, example_tags ) @@ -115,7 +115,7 @@ def test_delete_tags_command(self): .order_by(Tag.name) .all() ) - assert example_tags == [tag.name for tag in created_tags] + assert example_tags == {tag.name for tag in created_tags} command = DeleteTagsCommand(example_tags) command.run() @@ -132,7 +132,7 @@ def test_delete_tags_command(self): example_dashboard = ( db.session.query(Dashboard).filter_by(slug="world_health").one() ) - example_tags = ["create custom tag example 1", "create custom tag example 2"] + example_tags = {"create custom tag example 1", "create custom tag example 2"} command = CreateCustomTagCommand( ObjectType.dashboard.value, example_dashboard.id, example_tags ) @@ -152,7 +152,7 @@ def test_delete_tags_command(self): command = DeleteTaggedObjectCommand( object_type=ObjectType.dashboard.value, object_id=example_dashboard.id, - tag=example_tags[0], + tag=list(example_tags)[0], ) command.run() tagged_objects = ( From e86d4d3c92b91da0aa09bc215908c23f261b4f9a Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Fri, 19 Jan 2024 15:13:18 -0800 Subject: [PATCH 10/39] fix(import): only import FORMULA annotations (#26652) --- superset/cli/importexport.py | 3 +- superset/commands/chart/importers/v1/utils.py | 18 ++++++++++ .../charts/commands_tests.py | 1 + tests/integration_tests/cli_tests.py | 12 ++++--- .../fixtures/importexport.py | 35 +++++++++++++++++++ .../commands/importers/v1/import_test.py | 19 ++++++++++ 6 files changed, 83 insertions(+), 5 deletions(-) diff --git a/superset/cli/importexport.py b/superset/cli/importexport.py index 3d4f87dd26b..fc6a9ad3c46 100755 --- a/superset/cli/importexport.py +++ b/superset/cli/importexport.py @@ -130,12 +130,13 @@ def export_datasources(datasource_file: Optional[str] = None) -> None: @click.option( "--path", "-p", + required=True, help="Path to a single ZIP file", ) @click.option( "--username", "-u", - default=None, + required=True, help="Specify the user name to assign dashboards to", ) def import_dashboards(path: str, username: Optional[str]) -> None: diff --git a/superset/commands/chart/importers/v1/utils.py b/superset/commands/chart/importers/v1/utils.py index d27b631f97f..f905f8cc3ad 100644 --- a/superset/commands/chart/importers/v1/utils.py +++ b/superset/commands/chart/importers/v1/utils.py @@ -28,6 +28,22 @@ from superset.migrations.shared.migrate_viz import processors from superset.migrations.shared.migrate_viz.base import MigrateViz from superset.models.slice import Slice +from superset.utils.core import AnnotationType + + +def filter_chart_annotations(chart_config: dict[str, Any]) -> None: + """ + Mutating the chart's config params to keep only the annotations of + type FORMULA. + TODO: + handle annotation dependencies on either other charts or + annotation layers objects. + """ + params = chart_config.get("params", {}) + als = params.get("annotation_layers", []) + params["annotation_layers"] = [ + al for al in als if al.get("annotationType") == AnnotationType.FORMULA + ] def import_chart( @@ -47,6 +63,8 @@ def import_chart( "Chart doesn't exist and user doesn't have permission to create charts" ) + filter_chart_annotations(config) + # TODO (betodealmeida): move this logic to import_from_dict config["params"] = json.dumps(config["params"]) diff --git a/tests/integration_tests/charts/commands_tests.py b/tests/integration_tests/charts/commands_tests.py index 87c7823ae5a..b6adf197f57 100644 --- a/tests/integration_tests/charts/commands_tests.py +++ b/tests/integration_tests/charts/commands_tests.py @@ -190,6 +190,7 @@ def test_import_v1_chart(self, sm_g, utils_g): ) dataset = chart.datasource assert json.loads(chart.params) == { + "annotation_layers": [], "color_picker": {"a": 1, "b": 135, "g": 122, "r": 0}, "datasource": dataset.uid, "js_columns": ["color"], diff --git a/tests/integration_tests/cli_tests.py b/tests/integration_tests/cli_tests.py index 2441809b0da..1b2c5f8b4ee 100644 --- a/tests/integration_tests/cli_tests.py +++ b/tests/integration_tests/cli_tests.py @@ -160,7 +160,8 @@ def test_import_dashboards_versioned_export(import_dashboards_command, app_conte runner = app.test_cli_runner() response = runner.invoke( - superset.cli.importexport.import_dashboards, ("-p", "dashboards.json") + superset.cli.importexport.import_dashboards, + ("-p", "dashboards.json", "-u", "admin"), ) assert response.exit_code == 0 @@ -174,7 +175,8 @@ def test_import_dashboards_versioned_export(import_dashboards_command, app_conte runner = app.test_cli_runner() response = runner.invoke( - superset.cli.importexport.import_dashboards, ("-p", "dashboards.zip") + superset.cli.importexport.import_dashboards, + ("-p", "dashboards.zip", "-u", "admin"), ) assert response.exit_code == 0 @@ -205,7 +207,8 @@ def test_failing_import_dashboards_versioned_export( runner = app.test_cli_runner() response = runner.invoke( - superset.cli.importexport.import_dashboards, ("-p", "dashboards.json") + superset.cli.importexport.import_dashboards, + ("-p", "dashboards.json", "-u", "admin"), ) assert_cli_fails_properly(response, caplog) @@ -217,7 +220,8 @@ def test_failing_import_dashboards_versioned_export( runner = app.test_cli_runner() response = runner.invoke( - superset.cli.importexport.import_dashboards, ("-p", "dashboards.zip") + superset.cli.importexport.import_dashboards, + ("-p", "dashboards.zip", "-u", "admin"), ) assert_cli_fails_properly(response, caplog) diff --git a/tests/integration_tests/fixtures/importexport.py b/tests/integration_tests/fixtures/importexport.py index 8fa61539dcc..5096c272335 100644 --- a/tests/integration_tests/fixtures/importexport.py +++ b/tests/integration_tests/fixtures/importexport.py @@ -14,6 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +from copy import deepcopy from typing import Any # example V0 import/export format @@ -575,6 +576,40 @@ "version": "1.0.0", "dataset_uuid": "10808100-158b-42c4-842e-f32b99d88dfb", } +chart_config_with_mixed_annotations: dict[str, Any] = deepcopy(chart_config) +chart_config_with_mixed_annotations["params"]["annotation_layers"] = [ + { + "name": "Formula test layer", + "annotationType": "FORMULA", + "color": None, + "descriptionColumns": [], + "hideLine": False, + "opacity": "", + "overrides": {"time_range": None}, + "show": True, + "showLabel": False, + "showMarkers": False, + "style": "solid", + "value": "100000", + "width": 1, + }, + { + "name": "Native layer to be removed on import", + "annotationType": "EVENT", + "sourceType": "NATIVE", + "color": None, + "opacity": "", + "style": "solid", + "width": 1, + "showMarkers": False, + "hideLine": False, + "value": 2, + "overrides": {"time_range": None}, + "show": True, + "showLabel": False, + "descriptionColumns": [], + }, +] dashboard_config: dict[str, Any] = { "dashboard_title": "Test dash", diff --git a/tests/unit_tests/charts/commands/importers/v1/import_test.py b/tests/unit_tests/charts/commands/importers/v1/import_test.py index f0d142644df..903b7468baf 100644 --- a/tests/unit_tests/charts/commands/importers/v1/import_test.py +++ b/tests/unit_tests/charts/commands/importers/v1/import_test.py @@ -108,3 +108,22 @@ def test_import_chart_without_permission( str(excinfo.value) == "Chart doesn't exist and user doesn't have permission to create charts" ) + + +def test_filter_chart_annotations(mocker: MockFixture, session: Session) -> None: + """ + Test importing a chart. + """ + from superset import security_manager + from superset.commands.chart.importers.v1.utils import filter_chart_annotations + from tests.integration_tests.fixtures.importexport import ( + chart_config_with_mixed_annotations, + ) + + config = copy.deepcopy(chart_config_with_mixed_annotations) + filter_chart_annotations(config) + params = config["params"] + annotation_layers = params["annotation_layers"] + + assert len(annotation_layers) == 1 + assert all([al["annotationType"] == "FORMULA" for al in annotation_layers]) From d34874cf2bbd6385d2ca6f38856d3d10d6fd745b Mon Sep 17 00:00:00 2001 From: Denis Krivenko Date: Sun, 21 Jan 2024 18:43:17 +0100 Subject: [PATCH 11/39] feat(helm): Upgrade default Superset version to 3.1.0 (#26707) --- helm/superset/Chart.yaml | 4 ++-- helm/superset/README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/helm/superset/Chart.yaml b/helm/superset/Chart.yaml index cbca9425693..019b2a5159f 100644 --- a/helm/superset/Chart.yaml +++ b/helm/superset/Chart.yaml @@ -15,7 +15,7 @@ # limitations under the License. # apiVersion: v2 -appVersion: "3.0.1" +appVersion: "3.1.0" description: Apache Superset is a modern, enterprise-ready business intelligence web application name: superset icon: https://artifacthub.io/image/68c1d717-0e97-491f-b046-754e46f46922@2x @@ -29,7 +29,7 @@ maintainers: - name: craig-rueda email: craig@craigrueda.com url: https://github.com/craig-rueda -version: 0.11.2 +version: 0.12.0 dependencies: - name: postgresql version: 12.1.6 diff --git a/helm/superset/README.md b/helm/superset/README.md index 1eaf4928c15..acb8f10716d 100644 --- a/helm/superset/README.md +++ b/helm/superset/README.md @@ -23,7 +23,7 @@ NOTE: This file is generated by helm-docs: https://github.com/norwoodj/helm-docs # superset -![Version: 0.11.2](https://img.shields.io/badge/Version-0.11.2-informational?style=flat-square) +![Version: 0.12.0](https://img.shields.io/badge/Version-0.12.0-informational?style=flat-square) Apache Superset is a modern, enterprise-ready business intelligence web application From c0b57bd1c3d487a661315a1944aca9f9ce728d51 Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Mon, 22 Jan 2024 11:16:50 -0500 Subject: [PATCH 12/39] feat(sqlparse): improve table parsing (#26476) --- requirements/base.txt | 15 +- requirements/testing.txt | 6 +- setup.py | 1 + superset/commands/dataset/duplicate.py | 5 +- superset/commands/sql_lab/export.py | 5 +- superset/connectors/sqla/models.py | 2 +- superset/connectors/sqla/utils.py | 2 +- superset/db_engine_specs/base.py | 12 +- superset/db_engine_specs/bigquery.py | 2 +- superset/models/helpers.py | 2 +- superset/models/sql_lab.py | 6 +- superset/security/manager.py | 5 +- superset/sql_lab.py | 11 +- superset/sql_parse.py | 246 +++++++++++++++++-------- superset/sql_validators/presto_db.py | 4 +- superset/sqllab/query_render.py | 6 +- tests/unit_tests/sql_parse_tests.py | 55 ++++-- 17 files changed, 265 insertions(+), 120 deletions(-) diff --git a/requirements/base.txt b/requirements/base.txt index 98d2a8094ee..b198a5c9cee 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -141,7 +141,9 @@ geographiclib==1.52 geopy==2.2.0 # via apache-superset greenlet==2.0.2 - # via shillelagh + # via + # shillelagh + # sqlalchemy gunicorn==21.2.0 # via apache-superset hashids==1.3.1 @@ -155,7 +157,10 @@ idna==3.2 # email-validator # requests importlib-metadata==6.6.0 - # via apache-superset + # via + # apache-superset + # flask + # shillelagh importlib-resources==5.12.0 # via limits isodate==0.6.0 @@ -327,6 +332,8 @@ sqlalchemy-utils==0.38.3 # via # apache-superset # flask-appbuilder +sqlglot==20.8.0 + # via apache-superset sqlparse==0.4.4 # via apache-superset sshtunnel==0.4.0 @@ -376,7 +383,9 @@ wtforms-json==0.3.5 xlsxwriter==3.0.7 # via apache-superset zipp==3.15.0 - # via importlib-metadata + # via + # importlib-metadata + # importlib-resources # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/requirements/testing.txt b/requirements/testing.txt index 3bf3c78d037..b40497c8fc1 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -24,10 +24,6 @@ db-dtypes==1.1.1 # via pandas-gbq docker==6.1.1 # via -r requirements/testing.in -exceptiongroup==1.1.1 - # via pytest -ephem==4.1.4 - # via lunarcalendar flask-testing==0.8.1 # via -r requirements/testing.in fonttools==4.39.4 @@ -121,6 +117,8 @@ pyee==9.0.4 # via playwright pyfakefs==5.2.2 # via -r requirements/testing.in +pyhive[presto]==0.7.0 + # via apache-superset pytest==7.3.1 # via # -r requirements/testing.in diff --git a/setup.py b/setup.py index fd2a9f8c80c..cb02a7f4909 100644 --- a/setup.py +++ b/setup.py @@ -125,6 +125,7 @@ def get_git_sha() -> str: "slack_sdk>=3.19.0, <4", "sqlalchemy>=1.4, <2", "sqlalchemy-utils>=0.38.3, <0.39", + "sqlglot>=20,<21", "sqlparse>=0.4.4, <0.5", "tabulate>=0.8.9, <0.9", "typing-extensions>=4, <5", diff --git a/superset/commands/dataset/duplicate.py b/superset/commands/dataset/duplicate.py index 0ae47c35bca..850290422e1 100644 --- a/superset/commands/dataset/duplicate.py +++ b/superset/commands/dataset/duplicate.py @@ -70,7 +70,10 @@ def run(self) -> Model: table.normalize_columns = self._base_model.normalize_columns table.always_filter_main_dttm = self._base_model.always_filter_main_dttm table.is_sqllab_view = True - table.sql = ParsedQuery(self._base_model.sql).stripped() + table.sql = ParsedQuery( + self._base_model.sql, + engine=database.db_engine_spec.engine, + ).stripped() db.session.add(table) cols = [] for config_ in self._base_model.columns: diff --git a/superset/commands/sql_lab/export.py b/superset/commands/sql_lab/export.py index 1b9b0e03442..aa6050f27f9 100644 --- a/superset/commands/sql_lab/export.py +++ b/superset/commands/sql_lab/export.py @@ -115,7 +115,10 @@ def run( limit = None else: sql = self._query.executed_sql - limit = ParsedQuery(sql).limit + limit = ParsedQuery( + sql, + engine=self._query.database.db_engine_spec.engine, + ).limit if limit is not None and self._query.limiting_factor in { LimitingFactor.QUERY, LimitingFactor.DROPDOWN, diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py index 624eb2ce5a5..08dc923c21b 100644 --- a/superset/connectors/sqla/models.py +++ b/superset/connectors/sqla/models.py @@ -1457,7 +1457,7 @@ def get_from_clause( return self.get_sqla_table(), None from_sql = self.get_rendered_sql(template_processor) - parsed_query = ParsedQuery(from_sql) + parsed_query = ParsedQuery(from_sql, engine=self.db_engine_spec.engine) if not ( parsed_query.is_unknown() or self.db_engine_spec.is_readonly_query(parsed_query) diff --git a/superset/connectors/sqla/utils.py b/superset/connectors/sqla/utils.py index 66594084c82..688be535150 100644 --- a/superset/connectors/sqla/utils.py +++ b/superset/connectors/sqla/utils.py @@ -111,7 +111,7 @@ def get_virtual_table_metadata(dataset: SqlaTable) -> list[ResultSetColumnType]: sql = dataset.get_template_processor().process_template( dataset.sql, **dataset.template_params_dict ) - parsed_query = ParsedQuery(sql) + parsed_query = ParsedQuery(sql, engine=db_engine_spec.engine) if not db_engine_spec.is_readonly_query(parsed_query): raise SupersetSecurityException( SupersetError( diff --git a/superset/db_engine_specs/base.py b/superset/db_engine_specs/base.py index 48e44064acf..3b8bb2bd332 100644 --- a/superset/db_engine_specs/base.py +++ b/superset/db_engine_specs/base.py @@ -899,7 +899,7 @@ def apply_limit_to_sql( return database.compile_sqla_query(qry) if cls.limit_method == LimitMethod.FORCE_LIMIT: - parsed_query = sql_parse.ParsedQuery(sql) + parsed_query = sql_parse.ParsedQuery(sql, engine=cls.engine) sql = parsed_query.set_or_update_query_limit(limit, force=force) return sql @@ -980,7 +980,7 @@ def get_limit_from_sql(cls, sql: str) -> int | None: :param sql: SQL query :return: Value of limit clause in query """ - parsed_query = sql_parse.ParsedQuery(sql) + parsed_query = sql_parse.ParsedQuery(sql, engine=cls.engine) return parsed_query.limit @classmethod @@ -992,7 +992,7 @@ def set_or_update_query_limit(cls, sql: str, limit: int) -> str: :param limit: New limit to insert/replace into query :return: Query with new limit """ - parsed_query = sql_parse.ParsedQuery(sql) + parsed_query = sql_parse.ParsedQuery(sql, engine=cls.engine) return parsed_query.set_or_update_query_limit(limit) @classmethod @@ -1487,7 +1487,7 @@ def process_statement(cls, statement: str, database: Database) -> str: :param database: Database instance :return: Dictionary with different costs """ - parsed_query = ParsedQuery(statement) + parsed_query = ParsedQuery(statement, engine=cls.engine) sql = parsed_query.stripped() sql_query_mutator = current_app.config["SQL_QUERY_MUTATOR"] mutate_after_split = current_app.config["MUTATE_AFTER_SPLIT"] @@ -1522,7 +1522,7 @@ def estimate_query_cost( "Database does not support cost estimation" ) - parsed_query = sql_parse.ParsedQuery(sql) + parsed_query = sql_parse.ParsedQuery(sql, engine=cls.engine) statements = parsed_query.get_statements() costs = [] @@ -1583,7 +1583,7 @@ def execute( # pylint: disable=unused-argument :return: """ if not cls.allows_sql_comments: - query = sql_parse.strip_comments_from_sql(query) + query = sql_parse.strip_comments_from_sql(query, engine=cls.engine) if cls.arraysize: cursor.arraysize = cls.arraysize diff --git a/superset/db_engine_specs/bigquery.py b/superset/db_engine_specs/bigquery.py index 8e7ed0bf7d0..a8d834276e6 100644 --- a/superset/db_engine_specs/bigquery.py +++ b/superset/db_engine_specs/bigquery.py @@ -435,7 +435,7 @@ def estimate_query_cost( if not cls.get_allow_cost_estimate(extra): raise SupersetException("Database does not support cost estimation") - parsed_query = sql_parse.ParsedQuery(sql) + parsed_query = sql_parse.ParsedQuery(sql, engine=cls.engine) statements = parsed_query.get_statements() costs = [] for statement in statements: diff --git a/superset/models/helpers.py b/superset/models/helpers.py index a6d879b785e..9c8e83147e9 100644 --- a/superset/models/helpers.py +++ b/superset/models/helpers.py @@ -1093,7 +1093,7 @@ def get_from_clause( """ from_sql = self.get_rendered_sql(template_processor) - parsed_query = ParsedQuery(from_sql) + parsed_query = ParsedQuery(from_sql, engine=self.db_engine_spec.engine) if not ( parsed_query.is_unknown() or self.db_engine_spec.is_readonly_query(parsed_query) diff --git a/superset/models/sql_lab.py b/superset/models/sql_lab.py index ca530ff8b97..a0e9fa6b6eb 100644 --- a/superset/models/sql_lab.py +++ b/superset/models/sql_lab.py @@ -183,7 +183,7 @@ def username(self) -> str: @property def sql_tables(self) -> list[Table]: - return list(ParsedQuery(self.sql).tables) + return list(ParsedQuery(self.sql, engine=self.db_engine_spec.engine).tables) @property def columns(self) -> list["TableColumn"]: @@ -427,7 +427,9 @@ def url(self) -> str: @property def sql_tables(self) -> list[Table]: - return list(ParsedQuery(self.sql).tables) + return list( + ParsedQuery(self.sql, engine=self.database.db_engine_spec.engine).tables + ) @property def last_run_humanized(self) -> str: diff --git a/superset/security/manager.py b/superset/security/manager.py index 618a7e2808a..7e1b697840a 100644 --- a/superset/security/manager.py +++ b/superset/security/manager.py @@ -1876,7 +1876,10 @@ def raise_for_access( default_schema = database.get_default_schema_for_query(query) tables = { Table(table_.table, table_.schema or default_schema) - for table_ in sql_parse.ParsedQuery(query.sql).tables + for table_ in sql_parse.ParsedQuery( + query.sql, + engine=database.db_engine_spec.engine, + ).tables } elif table: tables = {table} diff --git a/superset/sql_lab.py b/superset/sql_lab.py index 1029ff402ca..1b883a77cfb 100644 --- a/superset/sql_lab.py +++ b/superset/sql_lab.py @@ -199,7 +199,7 @@ def execute_sql_statement( database: Database = query.database db_engine_spec = database.db_engine_spec - parsed_query = ParsedQuery(sql_statement) + parsed_query = ParsedQuery(sql_statement, engine=db_engine_spec.engine) if is_feature_enabled("RLS_IN_SQLLAB"): # There are two ways to insert RLS: either replacing the table with a subquery # that has the RLS, or appending the RLS to the ``WHERE`` clause. The former is @@ -219,7 +219,8 @@ def execute_sql_statement( database.id, query.schema, ) - ) + ), + engine=db_engine_spec.engine, ) sql = parsed_query.stripped() @@ -409,7 +410,11 @@ def execute_sql_statements( ) # Breaking down into multiple statements - parsed_query = ParsedQuery(rendered_query, strip_comments=True) + parsed_query = ParsedQuery( + rendered_query, + strip_comments=True, + engine=db_engine_spec.engine, + ) if not db_engine_spec.run_multiple_statements_as_one: statements = parsed_query.get_statements() logger.info( diff --git a/superset/sql_parse.py b/superset/sql_parse.py index cecd6732769..07704171dee 100644 --- a/superset/sql_parse.py +++ b/superset/sql_parse.py @@ -14,15 +14,22 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. + +# pylint: disable=too-many-lines + import logging import re -from collections.abc import Iterator +import urllib.parse +from collections.abc import Iterable, Iterator from dataclasses import dataclass from typing import Any, cast, Optional -from urllib import parse import sqlparse from sqlalchemy import and_ +from sqlglot import exp, parse, parse_one +from sqlglot.dialects import Dialects +from sqlglot.errors import ParseError +from sqlglot.optimizer.scope import Scope, ScopeType, traverse_scope from sqlparse import keywords from sqlparse.lexer import Lexer from sqlparse.sql import ( @@ -53,7 +60,7 @@ try: from sqloxide import parse_sql as sqloxide_parse -except: # pylint: disable=bare-except +except (ImportError, ModuleNotFoundError): sqloxide_parse = None RESULT_OPERATIONS = {"UNION", "INTERSECT", "EXCEPT", "SELECT"} @@ -72,6 +79,59 @@ lex.set_SQL_REGEX(sqlparser_sql_regex) +# mapping between DB engine specs and sqlglot dialects +SQLGLOT_DIALECTS = { + "ascend": Dialects.HIVE, + "awsathena": Dialects.PRESTO, + "bigquery": Dialects.BIGQUERY, + "clickhouse": Dialects.CLICKHOUSE, + "clickhousedb": Dialects.CLICKHOUSE, + "cockroachdb": Dialects.POSTGRES, + # "crate": ??? + # "databend": ??? + "databricks": Dialects.DATABRICKS, + # "db2": ??? + # "dremio": ??? + "drill": Dialects.DRILL, + # "druid": ??? + "duckdb": Dialects.DUCKDB, + # "dynamodb": ??? + # "elasticsearch": ??? + # "exa": ??? + # "firebird": ??? + # "firebolt": ??? + "gsheets": Dialects.SQLITE, + "hana": Dialects.POSTGRES, + "hive": Dialects.HIVE, + # "ibmi": ??? + # "impala": ??? + # "kustokql": ??? + # "kylin": ??? + # "mssql": ??? + "mysql": Dialects.MYSQL, + "netezza": Dialects.POSTGRES, + # "ocient": ??? + # "odelasticsearch": ??? + "oracle": Dialects.ORACLE, + # "pinot": ??? + "postgresql": Dialects.POSTGRES, + "presto": Dialects.PRESTO, + "pydoris": Dialects.DORIS, + "redshift": Dialects.REDSHIFT, + # "risingwave": ??? + # "rockset": ??? + "shillelagh": Dialects.SQLITE, + "snowflake": Dialects.SNOWFLAKE, + # "solr": ??? + "sqlite": Dialects.SQLITE, + "starrocks": Dialects.STARROCKS, + "superset": Dialects.SQLITE, + "teradatasql": Dialects.TERADATA, + "trino": Dialects.TRINO, + "vertica": Dialects.POSTGRES, +} + + class CtasMethod(StrEnum): TABLE = "TABLE" VIEW = "VIEW" @@ -150,7 +210,7 @@ def get_cte_remainder_query(sql: str) -> tuple[Optional[str], str]: return cte, remainder -def strip_comments_from_sql(statement: str) -> str: +def strip_comments_from_sql(statement: str, engine: Optional[str] = None) -> str: """ Strips comments from a SQL statement, does a simple test first to avoid always instantiating the expensive ParsedQuery constructor @@ -160,7 +220,11 @@ def strip_comments_from_sql(statement: str) -> str: :param statement: A string with the SQL statement :return: SQL statement without comments """ - return ParsedQuery(statement).strip_comments() if "--" in statement else statement + return ( + ParsedQuery(statement, engine=engine).strip_comments() + if "--" in statement + else statement + ) @dataclass(eq=True, frozen=True) @@ -179,7 +243,7 @@ def __str__(self) -> str: """ return ".".join( - parse.quote(part, safe="").replace(".", "%2E") + urllib.parse.quote(part, safe="").replace(".", "%2E") for part in [self.catalog, self.schema, self.table] if part ) @@ -189,11 +253,17 @@ def __eq__(self, __o: object) -> bool: class ParsedQuery: - def __init__(self, sql_statement: str, strip_comments: bool = False): + def __init__( + self, + sql_statement: str, + strip_comments: bool = False, + engine: Optional[str] = None, + ): if strip_comments: sql_statement = sqlparse.format(sql_statement, strip_comments=True) self.sql: str = sql_statement + self._dialect = SQLGLOT_DIALECTS.get(engine) if engine else None self._tables: set[Table] = set() self._alias_names: set[str] = set() self._limit: Optional[int] = None @@ -206,14 +276,94 @@ def __init__(self, sql_statement: str, strip_comments: bool = False): @property def tables(self) -> set[Table]: if not self._tables: - for statement in self._parsed: - self._extract_from_token(statement) - - self._tables = { - table for table in self._tables if str(table) not in self._alias_names - } + self._tables = self._extract_tables_from_sql() return self._tables + def _extract_tables_from_sql(self) -> set[Table]: + """ + Extract all table references in a query. + + Note: this uses sqlglot, since it's better at catching more edge cases. + """ + try: + statements = parse(self.sql, dialect=self._dialect) + except ParseError: + logger.warning("Unable to parse SQL (%s): %s", self._dialect, self.sql) + return set() + + return { + table + for statement in statements + for table in self._extract_tables_from_statement(statement) + if statement + } + + def _extract_tables_from_statement(self, statement: exp.Expression) -> set[Table]: + """ + Extract all table references in a single statement. + + Please not that this is not trivial; consider the following queries: + + DESCRIBE some_table; + SHOW PARTITIONS FROM some_table; + WITH masked_name AS (SELECT * FROM some_table) SELECT * FROM masked_name; + + See the unit tests for other tricky cases. + """ + sources: Iterable[exp.Table] + + if isinstance(statement, exp.Describe): + # A `DESCRIBE` query has no sources in sqlglot, so we need to explicitly + # query for all tables. + sources = statement.find_all(exp.Table) + elif isinstance(statement, exp.Command): + # Commands, like `SHOW COLUMNS FROM foo`, have to be converted into a + # `SELECT` statetement in order to extract tables. + literal = statement.find(exp.Literal) + if not literal: + return set() + + pseudo_query = parse_one(f"SELECT {literal.this}", dialect=self._dialect) + sources = pseudo_query.find_all(exp.Table) + else: + sources = [ + source + for scope in traverse_scope(statement) + for source in scope.sources.values() + if isinstance(source, exp.Table) and not self._is_cte(source, scope) + ] + + return { + Table( + source.name, + source.db if source.db != "" else None, + source.catalog if source.catalog != "" else None, + ) + for source in sources + } + + def _is_cte(self, source: exp.Table, scope: Scope) -> bool: + """ + Is the source a CTE? + + CTEs in the parent scope look like tables (and are represented by + exp.Table objects), but should not be considered as such; + otherwise a user with access to table `foo` could access any table + with a query like this: + + WITH foo AS (SELECT * FROM target_table) SELECT * FROM foo + + """ + parent_sources = scope.parent.sources if scope.parent else {} + ctes_in_scope = { + name + for name, parent_scope in parent_sources.items() + if isinstance(parent_scope, Scope) + and parent_scope.scope_type == ScopeType.CTE + } + + return source.name in ctes_in_scope + @property def limit(self) -> Optional[int]: return self._limit @@ -393,28 +543,6 @@ def get_table(tlist: TokenList) -> Optional[Table]: def _is_identifier(token: Token) -> bool: return isinstance(token, (IdentifierList, Identifier)) - def _process_tokenlist(self, token_list: TokenList) -> None: - """ - Add table names to table set - - :param token_list: TokenList to be processed - """ - # exclude subselects - if "(" not in str(token_list): - table = self.get_table(token_list) - if table and not table.table.startswith(CTE_PREFIX): - self._tables.add(table) - return - - # store aliases - if token_list.has_alias(): - self._alias_names.add(token_list.get_alias()) - - # some aliases are not parsed properly - if token_list.tokens[0].ttype == Name: - self._alias_names.add(token_list.tokens[0].value) - self._extract_from_token(token_list) - def as_create_table( self, table_name: str, @@ -441,50 +569,6 @@ def as_create_table( exec_sql += f"CREATE {method} {full_table_name} AS \n{sql}" return exec_sql - def _extract_from_token(self, token: Token) -> None: - """ - store a list of subtokens and store lists of - subtoken list. - - It extracts and from :param token: and loops - through all subtokens recursively. It finds table_name_preceding_token and - passes and to self._process_tokenlist to populate - self._tables. - - :param token: instance of Token or child class, e.g. TokenList, to be processed - """ - if not hasattr(token, "tokens"): - return - - table_name_preceding_token = False - - for item in token.tokens: - if item.is_group and ( - not self._is_identifier(item) or isinstance(item.tokens[0], Parenthesis) - ): - self._extract_from_token(item) - - if item.ttype in Keyword and ( - item.normalized in PRECEDES_TABLE_NAME - or item.normalized.endswith(" JOIN") - ): - table_name_preceding_token = True - continue - - if item.ttype in Keyword: - table_name_preceding_token = False - continue - if table_name_preceding_token: - if isinstance(item, Identifier): - self._process_tokenlist(item) - elif isinstance(item, IdentifierList): - for token2 in item.get_identifiers(): - if isinstance(token2, TokenList): - self._process_tokenlist(token2) - elif isinstance(item, IdentifierList): - if any(not self._is_identifier(token2) for token2 in item.tokens): - self._extract_from_token(item) - def set_or_update_query_limit(self, new_limit: int, force: bool = False) -> str: """Returns the query with the specified limit. @@ -881,7 +965,7 @@ def insert_rls_in_predicate( # mapping between sqloxide and SQLAlchemy dialects -SQLOXITE_DIALECTS = { +SQLOXIDE_DIALECTS = { "ansi": {"trino", "trinonative", "presto"}, "hive": {"hive", "databricks"}, "ms": {"mssql"}, @@ -914,7 +998,7 @@ def extract_table_references( tree = None if sqloxide_parse: - for dialect, sqla_dialects in SQLOXITE_DIALECTS.items(): + for dialect, sqla_dialects in SQLOXIDE_DIALECTS.items(): if sqla_dialect in sqla_dialects: break sql_text = RE_JINJA_BLOCK.sub(" ", sql_text) diff --git a/superset/sql_validators/presto_db.py b/superset/sql_validators/presto_db.py index c01b9386718..fed1ff3bfae 100644 --- a/superset/sql_validators/presto_db.py +++ b/superset/sql_validators/presto_db.py @@ -50,7 +50,7 @@ def validate_statement( ) -> Optional[SQLValidationAnnotation]: # pylint: disable=too-many-locals db_engine_spec = database.db_engine_spec - parsed_query = ParsedQuery(statement) + parsed_query = ParsedQuery(statement, engine=db_engine_spec.engine) sql = parsed_query.stripped() # Hook to allow environment-specific mutation (usually comments) to the SQL @@ -154,7 +154,7 @@ def validate( For example, "SELECT 1 FROM default.mytable" becomes "EXPLAIN (TYPE VALIDATE) SELECT 1 FROM default.mytable. """ - parsed_query = ParsedQuery(sql) + parsed_query = ParsedQuery(sql, engine=database.db_engine_spec.engine) statements = parsed_query.get_statements() logger.info("Validating %i statement(s)", len(statements)) diff --git a/superset/sqllab/query_render.py b/superset/sqllab/query_render.py index f4c1c26c6eb..5597bcb086d 100644 --- a/superset/sqllab/query_render.py +++ b/superset/sqllab/query_render.py @@ -58,7 +58,11 @@ def render(self, execution_context: SqlJsonExecutionContext) -> str: database=query_model.database, query=query_model ) - parsed_query = ParsedQuery(query_model.sql, strip_comments=True) + parsed_query = ParsedQuery( + query_model.sql, + strip_comments=True, + engine=query_model.database.db_engine_spec.engine, + ) rendered_query = sql_template_processor.process_template( parsed_query.stripped(), **execution_context.template_params ) diff --git a/tests/unit_tests/sql_parse_tests.py b/tests/unit_tests/sql_parse_tests.py index efd88381014..f650b77734f 100644 --- a/tests/unit_tests/sql_parse_tests.py +++ b/tests/unit_tests/sql_parse_tests.py @@ -40,11 +40,11 @@ ) -def extract_tables(query: str) -> set[Table]: +def extract_tables(query: str, engine: Optional[str] = None) -> set[Table]: """ Helper function to extract tables referenced in a query. """ - return ParsedQuery(query).tables + return ParsedQuery(query, engine=engine).tables def test_table() -> None: @@ -96,8 +96,13 @@ def test_extract_tables() -> None: Table("left_table") } - # reverse select - assert extract_tables("FROM t1 SELECT field") == {Table("t1")} + assert extract_tables( + "SELECT FROM (SELECT FROM forbidden_table) AS forbidden_table;" + ) == {Table("forbidden_table")} + + assert extract_tables( + "select * from (select * from forbidden_table) forbidden_table" + ) == {Table("forbidden_table")} def test_extract_tables_subselect() -> None: @@ -263,14 +268,16 @@ def test_extract_tables_illdefined() -> None: assert extract_tables("SELECT * FROM schemaname.") == set() assert extract_tables("SELECT * FROM catalogname.schemaname.") == set() assert extract_tables("SELECT * FROM catalogname..") == set() - assert extract_tables("SELECT * FROM catalogname..tbname") == set() + assert extract_tables("SELECT * FROM catalogname..tbname") == { + Table(table="tbname", schema=None, catalog="catalogname") + } def test_extract_tables_show_tables_from() -> None: """ Test ``SHOW TABLES FROM``. """ - assert extract_tables("SHOW TABLES FROM s1 like '%order%'") == set() + assert extract_tables("SHOW TABLES FROM s1 like '%order%'", "mysql") == set() def test_extract_tables_show_columns_from() -> None: @@ -311,7 +318,7 @@ def test_extract_tables_where_subquery() -> None: """ SELECT name FROM t1 -WHERE regionkey EXISTS (SELECT regionkey FROM t2) +WHERE EXISTS (SELECT 1 FROM t2 WHERE t1.regionkey = t2.regionkey); """ ) == {Table("t1"), Table("t2")} @@ -526,6 +533,18 @@ def test_extract_tables_reusing_aliases() -> None: == {Table("src")} ) + # weird query with circular dependency + assert ( + extract_tables( + """ +with src as ( select key from q2 where key = '5'), +q2 as ( select key from src where key = '5') +select * from (select key from src) a +""" + ) + == set() + ) + def test_extract_tables_multistatement() -> None: """ @@ -665,7 +684,8 @@ def test_extract_tables_nested_select() -> None: select (extractvalue(1,concat(0x7e,(select GROUP_CONCAT(TABLE_NAME) from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA like "%bi%"),0x7e))); -""" +""", + "mysql", ) == {Table("COLUMNS", "INFORMATION_SCHEMA")} ) @@ -676,7 +696,8 @@ def test_extract_tables_nested_select() -> None: select (extractvalue(1,concat(0x7e,(select GROUP_CONCAT(COLUMN_NAME) from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME="bi_achievement_daily"),0x7e))); -""" +""", + "mysql", ) == {Table("COLUMNS", "INFORMATION_SCHEMA")} ) @@ -1306,6 +1327,14 @@ def test_sqlparse_issue_652(): "(SELECT table_name FROM /**/ information_schema.tables WHERE table_name LIKE '%user%' LIMIT 1)", True, ), + ( + "SELECT FROM (SELECT FROM forbidden_table) AS forbidden_table;", + True, + ), + ( + "SELECT * FROM (SELECT * FROM forbidden_table) forbidden_table", + True, + ), ], ) def test_has_table_query(sql: str, expected: bool) -> None: @@ -1790,13 +1819,17 @@ def test_extract_table_references(mocker: MockerFixture) -> None: assert extract_table_references( sql, "trino", - ) == {Table(table="other_table", schema=None, catalog=None)} + ) == { + Table(table="table", schema=None, catalog=None), + Table(table="other_table", schema=None, catalog=None), + } logger.warning.assert_called_once() logger = mocker.patch("superset.migrations.shared.utils.logger") sql = "SELECT * FROM table UNION ALL SELECT * FROM other_table" assert extract_table_references(sql, "trino", show_warning=False) == { - Table(table="other_table", schema=None, catalog=None) + Table(table="table", schema=None, catalog=None), + Table(table="other_table", schema=None, catalog=None), } logger.warning.assert_not_called() From ce26ecbd9091467e3f4662d7bb00ca0a24ed7a05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 09:59:17 -0700 Subject: [PATCH 13/39] build(deps-dev): bump @types/node from 20.11.1 to 20.11.5 in /superset-websocket (#26733) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- superset-websocket/package-lock.json | 14 +++++++------- superset-websocket/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/superset-websocket/package-lock.json b/superset-websocket/package-lock.json index 3266cd9deb9..aaeff29d0e7 100644 --- a/superset-websocket/package-lock.json +++ b/superset-websocket/package-lock.json @@ -24,7 +24,7 @@ "@types/ioredis": "^4.27.8", "@types/jest": "^27.0.2", "@types/jsonwebtoken": "^9.0.5", - "@types/node": "^20.11.1", + "@types/node": "^20.11.5", "@types/uuid": "^9.0.7", "@types/ws": "^8.5.10", "@typescript-eslint/eslint-plugin": "^5.61.0", @@ -1429,9 +1429,9 @@ "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==" }, "node_modules/@types/node": { - "version": "20.11.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.1.tgz", - "integrity": "sha512-DsXojJUES2M+FE8CpptJTKpg+r54moV9ZEncPstni1WHFmTcCzeFLnMFfyhCVS8XNOy/OQG+8lVxRLRrVHmV5A==", + "version": "20.11.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", + "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -7283,9 +7283,9 @@ "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==" }, "@types/node": { - "version": "20.11.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.1.tgz", - "integrity": "sha512-DsXojJUES2M+FE8CpptJTKpg+r54moV9ZEncPstni1WHFmTcCzeFLnMFfyhCVS8XNOy/OQG+8lVxRLRrVHmV5A==", + "version": "20.11.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", + "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", "dev": true, "requires": { "undici-types": "~5.26.4" diff --git a/superset-websocket/package.json b/superset-websocket/package.json index 07ada42282a..301aad75d16 100644 --- a/superset-websocket/package.json +++ b/superset-websocket/package.json @@ -31,7 +31,7 @@ "@types/ioredis": "^4.27.8", "@types/jest": "^27.0.2", "@types/jsonwebtoken": "^9.0.5", - "@types/node": "^20.11.1", + "@types/node": "^20.11.5", "@types/uuid": "^9.0.7", "@types/ws": "^8.5.10", "@typescript-eslint/eslint-plugin": "^5.61.0", From f46121dba9e6c316e93959e5a8e082f56cecb82b Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Mon, 22 Jan 2024 09:20:48 -0800 Subject: [PATCH 14/39] chore: silence SECRET_KEY warning when running tests (#26703) --- tests/integration_tests/superset_test_config.py | 1 + tests/integration_tests/superset_test_config_thumbnails.py | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/integration_tests/superset_test_config.py b/tests/integration_tests/superset_test_config.py index 2aeeb3004e1..31d57b06e00 100644 --- a/tests/integration_tests/superset_test_config.py +++ b/tests/integration_tests/superset_test_config.py @@ -31,6 +31,7 @@ logging.getLogger("flask_appbuilder.security.sqla.manager").setLevel(logging.WARNING) logging.getLogger("sqlalchemy.engine.Engine").setLevel(logging.WARNING) +SECRET_KEY = "dummy_secret_key_for_test_to_silence_warnings" AUTH_USER_REGISTRATION_ROLE = "alpha" SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join( DATA_DIR, "unittests.integration_tests.db" diff --git a/tests/integration_tests/superset_test_config_thumbnails.py b/tests/integration_tests/superset_test_config_thumbnails.py index a761ef6611b..245d91382ea 100644 --- a/tests/integration_tests/superset_test_config_thumbnails.py +++ b/tests/integration_tests/superset_test_config_thumbnails.py @@ -19,6 +19,7 @@ from superset.config import * +SECRET_KEY = "dummy_secret_key_for_test_to_silence_warnings" AUTH_USER_REGISTRATION_ROLE = "alpha" SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join( DATA_DIR, "unittests.integration_tests.db" From 4a27e79001bae2b1b42216566c0ff8709efd98a0 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 10:56:56 -0700 Subject: [PATCH 15/39] chore(dependencies): npm audit fix for superset-ui-demo (#26691) --- superset-frontend/package-lock.json | 1189 +++++++++++---------------- 1 file changed, 503 insertions(+), 686 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 7b8073e9860..d94297ae7f3 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -1617,16 +1617,52 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.22.6", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz", @@ -1724,11 +1760,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -1863,20 +1899,20 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -2019,17 +2055,17 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } @@ -2070,12 +2106,12 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -2150,9 +2186,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "bin": { "parser": "bin/babel-parser.js" }, @@ -3834,32 +3870,32 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -3867,12 +3903,19 @@ } }, "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/@babel/traverse/node_modules/ms": { @@ -3881,12 +3924,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -18708,18 +18751,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/@svgr/plugin-jsx": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.0.1.tgz", @@ -21254,7 +21285,7 @@ "node_modules/@vx/axis": { "version": "0.0.140", "resolved": "https://registry.npmjs.org/@vx/axis/-/axis-0.0.140.tgz", - "integrity": "sha1-qtVXwoHGzCHBUWl3MBVSxwUuUiQ=", + "integrity": "sha512-lxMgWySkSh7ew8XS25Kpn95HH4d8dpL2vLv1UvASJY2VxdczQayTUUvQLecesJI4bbJV2R7Fasm64EBlJAezTw==", "dependencies": { "@vx/group": "0.0.140", "@vx/point": "0.0.136", @@ -21269,7 +21300,7 @@ "node_modules/@vx/axis/node_modules/prop-types": { "version": "15.5.10", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", - "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "integrity": "sha512-vCFzoUFaZkVNeFkhK1KbSq4cn97GDrpfBt9K2qLkGnPAEFhEv3M61Lk5t+B7c0QfMLWo0fPkowk/4SuXerh26Q==", "dependencies": { "fbjs": "^0.8.9", "loose-envify": "^1.3.1" @@ -25220,28 +25251,39 @@ } }, "node_modules/cheerio": { - "version": "1.0.0-rc.3", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", - "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", "dependencies": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.1", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash": "^4.15.0", - "parse5": "^3.0.1" + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, - "node_modules/cheerio/node_modules/dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", "dependencies": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, "node_modules/chokidar": { @@ -25993,11 +26035,12 @@ } }, "node_modules/comma-separated-tokens": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", - "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", - "dependencies": { - "trim": "0.0.1" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, "node_modules/commander": { @@ -26879,7 +26922,7 @@ "node_modules/cpy/node_modules/glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "dependencies": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -27369,18 +27412,6 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, "node_modules/css-minimizer-webpack-plugin/node_modules/domhandler": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", @@ -27448,18 +27479,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/css-minimizer-webpack-plugin/node_modules/nth-check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", - "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, "node_modules/css-minimizer-webpack-plugin/node_modules/postcss-calc": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.0.0.tgz", @@ -27966,14 +27985,18 @@ } }, "node_modules/css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "dependencies": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, "node_modules/css-tree": { @@ -27996,11 +28019,14 @@ "dev": true }, "node_modules/css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "engines": { - "node": "*" + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, "node_modules/css.escape": { @@ -29600,19 +29626,18 @@ } }, "node_modules/dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dependencies": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/dom-serializer/node_modules/domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" - }, "node_modules/dom-to-image": { "version": "2.6.0", "resolved": "git+ssh://git@github.com/dmapper/dom-to-image.git#a7c386a8ea813930f05449ac71ab4be0c262dff3", @@ -29647,9 +29672,15 @@ } }, "node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] }, "node_modules/domexception": { "version": "4.0.0", @@ -29673,11 +29704,17 @@ } }, "node_modules/domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dependencies": { - "domelementtype": "1" + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, "node_modules/dompurify": { @@ -29686,12 +29723,16 @@ "integrity": "sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg==" }, "node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, "node_modules/dot-case": { @@ -30129,9 +30170,15 @@ } }, "node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } }, "node_modules/env-ci": { "version": "5.5.0", @@ -32376,9 +32423,9 @@ } }, "node_modules/fbjs": { - "version": "0.8.17", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", - "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "version": "0.8.18", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.18.tgz", + "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==", "dependencies": { "core-js": "^1.0.0", "isomorphic-fetch": "^2.1.1", @@ -32386,7 +32433,7 @@ "object-assign": "^4.1.0", "promise": "^7.1.1", "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" + "ua-parser-js": "^0.7.30" } }, "node_modules/fbjs/node_modules/core-js": { @@ -35352,29 +35399,21 @@ } }, "node_modules/htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "dependencies": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "node_modules/htmlparser2/node_modules/readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" } }, "node_modules/http-cache-semantics": { @@ -36932,7 +36971,7 @@ "node_modules/isomorphic-fetch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==", "dependencies": { "node-fetch": "^1.0.1", "whatwg-fetch": ">=0.10.0" @@ -38598,14 +38637,15 @@ } }, "node_modules/jest-environment-jsdom/node_modules/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", "dev": true, "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", - "universalify": "^0.1.2" + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, "engines": { "node": ">=6" @@ -38624,9 +38664,9 @@ } }, "node_modules/jest-environment-jsdom/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, "engines": { "node": ">= 4.0.0" @@ -40009,18 +40049,6 @@ } } }, - "node_modules/jsdom/node_modules/entities": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", - "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/jsdom/node_modules/escodegen": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", @@ -40124,18 +40152,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/jsdom/node_modules/parse5": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", - "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", - "dev": true, - "dependencies": { - "entities": "^4.3.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/jsdom/node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -47756,11 +47772,14 @@ } }, "node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dependencies": { - "boolbase": "~1.0.0" + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, "node_modules/num2fraction": { @@ -49481,11 +49500,26 @@ } }, "node_modules/parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "dependencies": { - "@types/node": "*" + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/parseurl": { @@ -49830,9 +49864,9 @@ } }, "node_modules/postcss": { - "version": "8.4.25", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.25.tgz", - "integrity": "sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==", + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", "funding": [ { "type": "opencollective", @@ -49848,7 +49882,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -50042,9 +50076,9 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -53894,17 +53928,6 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/renderkid/node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, "node_modules/renderkid/node_modules/domhandler": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", @@ -53958,17 +53981,6 @@ "entities": "^2.0.0" } }, - "node_modules/renderkid/node_modules/nth-check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", - "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, "node_modules/repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", @@ -55289,11 +55301,12 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, "node_modules/space-separated-tokens": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", - "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", - "dependencies": { - "trim": "0.0.1" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, "node_modules/spawn-wrap": { @@ -55415,13 +55428,20 @@ } }, "node_modules/spdy-transport/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "devOptional": true, "dependencies": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/spdy-transport/node_modules/ms": { @@ -55445,13 +55465,20 @@ } }, "node_modules/spdy/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "devOptional": true, "dependencies": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/spdy/node_modules/ms": { @@ -56406,22 +56433,6 @@ "node": ">= 10" } }, - "node_modules/svgo/node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/svgo/node_modules/css-tree": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", @@ -56436,18 +56447,6 @@ "npm": ">=7.0.0" } }, - "node_modules/svgo/node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/svgo/node_modules/csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", @@ -56461,91 +56460,12 @@ "npm": ">=7.0.0" } }, - "node_modules/svgo/node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/svgo/node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/svgo/node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/svgo/node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/svgo/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/svgo/node_modules/mdn-data": { "version": "2.0.28", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", "dev": true }, - "node_modules/svgo/node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, "node_modules/svgo/node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -57591,7 +57511,8 @@ "node_modules/trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", + "deprecated": "Use String.prototype.trim() instead" }, "node_modules/trim-lines": { "version": "3.0.1", @@ -59156,7 +59077,7 @@ "node_modules/watchpack-chokidar2/node_modules/glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "optional": true, "dependencies": { "is-glob": "^3.1.0", @@ -59218,9 +59139,9 @@ "dev": true }, "node_modules/webpack": { - "version": "5.88.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz", - "integrity": "sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==", + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -64963,11 +64884,40 @@ } }, "@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "requires": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@babel/compat-data": { @@ -65037,11 +64987,11 @@ } }, "@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "requires": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -65137,17 +65087,17 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==" + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" }, "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { @@ -65251,14 +65201,14 @@ } }, "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" }, "@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==" + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" }, "@babel/helper-validator-option": { "version": "7.22.5", @@ -65287,12 +65237,12 @@ } }, "@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "requires": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "dependencies": { @@ -65347,9 +65297,9 @@ } }, "@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==" + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.22.5", @@ -66449,38 +66399,38 @@ } }, "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" } }, "@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", "globals": "^11.1.0" }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -66491,12 +66441,12 @@ } }, "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, @@ -78810,14 +78760,6 @@ "requires": { "@babel/types": "^7.21.3", "entities": "^4.4.0" - }, - "dependencies": { - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - } } }, "@svgr/plugin-jsx": { @@ -80938,7 +80880,7 @@ "@vx/axis": { "version": "0.0.140", "resolved": "https://registry.npmjs.org/@vx/axis/-/axis-0.0.140.tgz", - "integrity": "sha1-qtVXwoHGzCHBUWl3MBVSxwUuUiQ=", + "integrity": "sha512-lxMgWySkSh7ew8XS25Kpn95HH4d8dpL2vLv1UvASJY2VxdczQayTUUvQLecesJI4bbJV2R7Fasm64EBlJAezTw==", "requires": { "@vx/group": "0.0.140", "@vx/point": "0.0.136", @@ -80950,7 +80892,7 @@ "prop-types": { "version": "15.5.10", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", - "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "integrity": "sha512-vCFzoUFaZkVNeFkhK1KbSq4cn97GDrpfBt9K2qLkGnPAEFhEv3M61Lk5t+B7c0QfMLWo0fPkowk/4SuXerh26Q==", "requires": { "fbjs": "^0.8.9", "loose-envify": "^1.3.1" @@ -84052,27 +83994,30 @@ "dev": true }, "cheerio": { - "version": "1.0.0-rc.3", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", - "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.1", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash": "^4.15.0", - "parse5": "^3.0.1" - }, - "dependencies": { - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - } + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + } + }, + "cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "requires": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" } }, "chokidar": { @@ -84654,12 +84599,9 @@ } }, "comma-separated-tokens": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", - "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", - "requires": { - "trim": "0.0.1" - } + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==" }, "commander": { "version": "2.20.3", @@ -85359,7 +85301,7 @@ "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "requires": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -85759,12 +85701,6 @@ "entities": "^2.0.0" } }, - "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true - }, "domhandler": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", @@ -85814,15 +85750,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "nth-check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", - "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, "postcss-calc": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.0.0.tgz", @@ -86149,14 +86076,15 @@ } }, "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" } }, "css-tree": { @@ -86178,9 +86106,9 @@ } }, "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" }, "css.escape": { "version": "1.5.1", @@ -87439,19 +87367,13 @@ } }, "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" - } + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" } }, "dom-to-image": { @@ -87483,9 +87405,9 @@ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" }, "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" }, "domexception": { "version": "4.0.0", @@ -87505,11 +87427,11 @@ } }, "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "requires": { - "domelementtype": "1" + "domelementtype": "^2.3.0" } }, "dompurify": { @@ -87518,12 +87440,13 @@ "integrity": "sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg==" }, "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" } }, "dot-case": { @@ -87921,9 +87844,9 @@ } }, "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" }, "env-ci": { "version": "5.5.0", @@ -89599,9 +89522,9 @@ } }, "fbjs": { - "version": "0.8.17", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", - "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "version": "0.8.18", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.18.tgz", + "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==", "requires": { "core-js": "^1.0.0", "isomorphic-fetch": "^2.1.1", @@ -89609,7 +89532,7 @@ "object-assign": "^4.1.0", "promise": "^7.1.1", "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" + "ua-parser-js": "^0.7.30" }, "dependencies": { "core-js": { @@ -91839,28 +91762,14 @@ } }, "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" } }, "http-cache-semantics": { @@ -93008,7 +92917,7 @@ "isomorphic-fetch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==", "requires": { "node-fetch": "^1.0.1", "whatwg-fetch": ">=0.10.0" @@ -94378,14 +94287,15 @@ } }, "tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", "dev": true, "requires": { "psl": "^1.1.33", "punycode": "^2.1.1", - "universalify": "^0.1.2" + "universalify": "^0.2.0", + "url-parse": "^1.5.3" } }, "tr46": { @@ -94398,9 +94308,9 @@ } }, "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true }, "w3c-xmlserializer": { @@ -95398,12 +95308,6 @@ "ms": "2.1.2" } }, - "entities": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", - "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==", - "dev": true - }, "escodegen": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", @@ -95476,15 +95380,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "parse5": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", - "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", - "dev": true, - "requires": { - "entities": "^4.3.0" - } - }, "saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -101341,11 +101236,11 @@ } }, "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "requires": { - "boolbase": "~1.0.0" + "boolbase": "^1.0.0" } }, "num2fraction": { @@ -102660,11 +102555,20 @@ } }, "parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "requires": { - "@types/node": "*" + "entities": "^4.4.0" + } + }, + "parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "requires": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" } }, "parseurl": { @@ -102925,19 +102829,19 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { - "version": "8.4.25", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.25.tgz", - "integrity": "sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==", + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", "requires": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, "dependencies": { "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" }, "picocolors": { "version": "1.0.0", @@ -105980,11 +105884,6 @@ "entities": "^2.0.0" } }, - "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" - }, "domhandler": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", @@ -106018,14 +105917,6 @@ "domutils": "^2.5.2", "entities": "^2.0.0" } - }, - "nth-check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", - "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==", - "requires": { - "boolbase": "^1.0.0" - } } } }, @@ -107098,12 +106989,9 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, "space-separated-tokens": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", - "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", - "requires": { - "trim": "0.0.1" - } + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==" }, "spawn-wrap": { "version": "2.0.0", @@ -107191,12 +107079,12 @@ }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "devOptional": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -107222,12 +107110,12 @@ }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "devOptional": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -107965,19 +107853,6 @@ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true }, - "css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - } - }, "css-tree": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", @@ -107988,12 +107863,6 @@ "source-map-js": "^1.0.1" } }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true - }, "csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", @@ -108003,64 +107872,12 @@ "css-tree": "~2.2.0" } }, - "dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "requires": { - "domelementtype": "^2.3.0" - } - }, - "domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "requires": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - } - }, - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - }, "mdn-data": { "version": "2.0.28", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", "dev": true }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -108859,7 +108676,7 @@ "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==" }, "trim-lines": { "version": "3.0.1", @@ -109989,7 +109806,7 @@ "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "optional": true, "requires": { "is-glob": "^3.1.0", @@ -110045,9 +109862,9 @@ "dev": true }, "webpack": { - "version": "5.88.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz", - "integrity": "sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==", + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", From c989a1cbcebc15229d8c549ae110eaab289938a3 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 10:57:57 -0700 Subject: [PATCH 16/39] chore(dependencies): removes unused bootstrap-slider (#26684) --- superset-frontend/package-lock.json | 1 - superset-frontend/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index d94297ae7f3..8758d24ebd9 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -61,7 +61,6 @@ "antd": "4.10.3", "babel-plugin-typescript-to-proptypes": "^2.0.0", "bootstrap": "^3.4.1", - "bootstrap-slider": "^10.0.0", "brace": "^0.11.1", "broadcast-channel": "^4.10.0", "chrono-node": "^2.2.6", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 8abd9dd9554..393df1fd9c2 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -127,7 +127,6 @@ "antd": "4.10.3", "babel-plugin-typescript-to-proptypes": "^2.0.0", "bootstrap": "^3.4.1", - "bootstrap-slider": "^10.0.0", "brace": "^0.11.1", "broadcast-channel": "^4.10.0", "chrono-node": "^2.2.6", From 775474366eb84fddef63db02b1c34824f5891ce6 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 10:58:31 -0700 Subject: [PATCH 17/39] chore(dependencies): remove unused @babel/runtime-corejs3 (#26685) --- superset-frontend/package-lock.json | 1 - superset-frontend/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 8758d24ebd9..a6e64c4bfbc 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -15,7 +15,6 @@ ], "dependencies": { "@ant-design/icons": "^5.0.1", - "@babel/runtime-corejs3": "^7.22.6", "@emotion/babel-preset-css-prop": "^11.2.0", "@emotion/cache": "^11.4.0", "@emotion/react": "^11.4.1", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 393df1fd9c2..c8211a35e11 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -81,7 +81,6 @@ ], "dependencies": { "@ant-design/icons": "^5.0.1", - "@babel/runtime-corejs3": "^7.22.6", "@emotion/babel-preset-css-prop": "^11.2.0", "@emotion/cache": "^11.4.0", "@emotion/react": "^11.4.1", From 9f7db406f1f8001561becb8e054b986eaa9783f5 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 10:58:37 -0700 Subject: [PATCH 18/39] chore(dependencies): removes unused @visx/tooltip (#26686) --- superset-frontend/package-lock.json | 1 - superset-frontend/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index a6e64c4bfbc..e4569ea7f4c 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -52,7 +52,6 @@ "@visx/grid": "^3.0.1", "@visx/responsive": "^3.0.0", "@visx/scale": "^3.0.0", - "@visx/tooltip": "^3.0.0", "@visx/xychart": "^3.0.0", "abortcontroller-polyfill": "^1.1.9", "ace-builds": "^1.4.14", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index c8211a35e11..056edcb6821 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -118,7 +118,6 @@ "@visx/grid": "^3.0.1", "@visx/responsive": "^3.0.0", "@visx/scale": "^3.0.0", - "@visx/tooltip": "^3.0.0", "@visx/xychart": "^3.0.0", "abortcontroller-polyfill": "^1.1.9", "ace-builds": "^1.4.14", From 9c3f40d87c4a4d8357ea5f554d79b96aeeeb7617 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 10:58:43 -0700 Subject: [PATCH 19/39] chore(dependencies): remove unused ansi-regex (#26687) --- superset-frontend/package-lock.json | 1 - superset-frontend/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index e4569ea7f4c..3b394326c2e 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -55,7 +55,6 @@ "@visx/xychart": "^3.0.0", "abortcontroller-polyfill": "^1.1.9", "ace-builds": "^1.4.14", - "ansi-regex": "^4.1.1", "antd": "4.10.3", "babel-plugin-typescript-to-proptypes": "^2.0.0", "bootstrap": "^3.4.1", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 056edcb6821..06fec0b706a 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -121,7 +121,6 @@ "@visx/xychart": "^3.0.0", "abortcontroller-polyfill": "^1.1.9", "ace-builds": "^1.4.14", - "ansi-regex": "^4.1.1", "antd": "4.10.3", "babel-plugin-typescript-to-proptypes": "^2.0.0", "bootstrap": "^3.4.1", From 214142f54afe748aa1b7825b816f58431ebd8c7e Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 10:58:48 -0700 Subject: [PATCH 20/39] chore(dependencies): remove unused react-datetime (#26688) --- superset-frontend/package-lock.json | 21 --------------------- superset-frontend/package.json | 1 - 2 files changed, 22 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 3b394326c2e..26f5f54f2f1 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -101,7 +101,6 @@ "react-ace": "^10.1.0", "react-checkbox-tree": "^1.8.0", "react-color": "^2.13.8", - "react-datetime": "^3.2.0", "react-diff-viewer-continued": "^3.2.5", "react-dnd": "^11.1.3", "react-dnd-html5-backend": "^11.1.3", @@ -51557,18 +51556,6 @@ "react-dom": ">=16.8.0" } }, - "node_modules/react-datetime": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/react-datetime/-/react-datetime-3.2.0.tgz", - "integrity": "sha512-w5XdeNIGzBht9CadaZIJhKUhEcDTgH0XokKxGPCxeeJRYL7B3HIKA8CM6Q0xej2JFJt0n5d+zi3maMwaY3262A==", - "dependencies": { - "prop-types": "^15.5.7" - }, - "peerDependencies": { - "moment": "^2.16.0", - "react": "^16.5.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-diff-viewer-continued": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/react-diff-viewer-continued/-/react-diff-viewer-continued-3.2.5.tgz", @@ -104084,14 +104071,6 @@ "integrity": "sha512-BuzrlrM0ylg7coPkXOrRqlf2BgHLw5L44sybbr9Lg4xy7w9e5N7fGYbojOO0s8J0nvrM3PERN2rVFkvSa24lnQ==", "requires": {} }, - "react-datetime": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/react-datetime/-/react-datetime-3.2.0.tgz", - "integrity": "sha512-w5XdeNIGzBht9CadaZIJhKUhEcDTgH0XokKxGPCxeeJRYL7B3HIKA8CM6Q0xej2JFJt0n5d+zi3maMwaY3262A==", - "requires": { - "prop-types": "^15.5.7" - } - }, "react-diff-viewer-continued": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/react-diff-viewer-continued/-/react-diff-viewer-continued-3.2.5.tgz", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 06fec0b706a..5657ee1353d 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -167,7 +167,6 @@ "react-ace": "^10.1.0", "react-checkbox-tree": "^1.8.0", "react-color": "^2.13.8", - "react-datetime": "^3.2.0", "react-diff-viewer-continued": "^3.2.5", "react-dnd": "^11.1.3", "react-dnd-html5-backend": "^11.1.3", From eba3929ed143a84cf8967b4875c277f01313701e Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 10:58:55 -0700 Subject: [PATCH 21/39] chore(dependencies): remove unused lodash-es (#26689) --- superset-frontend/package-lock.json | 7 ++++--- superset-frontend/package.json | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 26f5f54f2f1..55f1adac22e 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -84,7 +84,6 @@ "json-bigint": "^1.0.0", "json-stringify-pretty-compact": "^2.0.0", "lodash": "^4.17.21", - "lodash-es": "^4.17.21", "mapbox-gl": "^2.10.0", "match-sorter": "^6.1.0", "memoize-one": "^5.1.1", @@ -44038,7 +44037,8 @@ "node_modules/lodash-es": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true }, "node_modules/lodash._baseisequal": { "version": "3.0.7", @@ -98369,7 +98369,8 @@ "lodash-es": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true }, "lodash._baseisequal": { "version": "3.0.7", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 5657ee1353d..9011291f783 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -150,7 +150,6 @@ "json-bigint": "^1.0.0", "json-stringify-pretty-compact": "^2.0.0", "lodash": "^4.17.21", - "lodash-es": "^4.17.21", "mapbox-gl": "^2.10.0", "match-sorter": "^6.1.0", "memoize-one": "^5.1.1", From ae3bb47708d615095e78779515e39e95076ff092 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 10:59:01 -0700 Subject: [PATCH 22/39] chore(dependencies): remove unused global-box (#26690) --- superset-frontend/package-lock.json | 9 ++++----- superset-frontend/package.json | 1 - superset-frontend/packages/superset-ui-demo/package.json | 1 - 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 55f1adac22e..656837e21eb 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -74,7 +74,6 @@ "fs-extra": "^10.0.0", "fuse.js": "^6.4.6", "geolib": "^2.0.24", - "global-box": "^1.2.0", "html-webpack-plugin": "^5.3.2", "immer": "^9.0.6", "interweave": "^13.0.0", @@ -34435,7 +34434,8 @@ "node_modules/global-box": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/global-box/-/global-box-1.2.0.tgz", - "integrity": "sha512-IgpqqAYWNG3eluK1tsCkI8Uxff16+OYWLEhDS/QrfkfmbRQ/tVlBXZfURn5tSoPPT6wtmeJp7VKhXrcc5jl/1A==" + "integrity": "sha512-IgpqqAYWNG3eluK1tsCkI8Uxff16+OYWLEhDS/QrfkfmbRQ/tVlBXZfURn5tSoPPT6wtmeJp7VKhXrcc5jl/1A==", + "peer": true }, "node_modules/global-cache": { "version": "1.2.1", @@ -62155,7 +62155,6 @@ "bootstrap": "^3.4.1", "core-js": "3.8.3", "gh-pages": "^3.0.0", - "global-box": "^1.2.0", "jquery": "^3.4.1", "memoize-one": "^5.1.1", "react": "^16.13.1", @@ -77407,7 +77406,6 @@ "core-js": "3.8.3", "fork-ts-checker-webpack-plugin": "^5.0.7", "gh-pages": "^3.0.0", - "global-box": "^1.2.0", "jquery": "^3.4.1", "memoize-one": "^5.1.1", "react": "^16.13.1", @@ -91059,7 +91057,8 @@ "global-box": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/global-box/-/global-box-1.2.0.tgz", - "integrity": "sha512-IgpqqAYWNG3eluK1tsCkI8Uxff16+OYWLEhDS/QrfkfmbRQ/tVlBXZfURn5tSoPPT6wtmeJp7VKhXrcc5jl/1A==" + "integrity": "sha512-IgpqqAYWNG3eluK1tsCkI8Uxff16+OYWLEhDS/QrfkfmbRQ/tVlBXZfURn5tSoPPT6wtmeJp7VKhXrcc5jl/1A==", + "peer": true }, "global-cache": { "version": "1.2.1", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 9011291f783..105835f5ef8 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -140,7 +140,6 @@ "fs-extra": "^10.0.0", "fuse.js": "^6.4.6", "geolib": "^2.0.24", - "global-box": "^1.2.0", "html-webpack-plugin": "^5.3.2", "immer": "^9.0.6", "interweave": "^13.0.0", diff --git a/superset-frontend/packages/superset-ui-demo/package.json b/superset-frontend/packages/superset-ui-demo/package.json index 7c04c590a38..45f6473a87b 100644 --- a/superset-frontend/packages/superset-ui-demo/package.json +++ b/superset-frontend/packages/superset-ui-demo/package.json @@ -46,7 +46,6 @@ "bootstrap": "^3.4.1", "core-js": "3.8.3", "gh-pages": "^3.0.0", - "global-box": "^1.2.0", "jquery": "^3.4.1", "memoize-one": "^5.1.1", "react": "^16.13.1", From 969f8edc5a2b7b076292ef579416207f53f26681 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 10:59:08 -0700 Subject: [PATCH 23/39] chore(dependencies): removes unused minimist (#26692) --- superset-frontend/package-lock.json | 1 - superset-frontend/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 656837e21eb..035c4508efc 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -86,7 +86,6 @@ "mapbox-gl": "^2.10.0", "match-sorter": "^6.1.0", "memoize-one": "^5.1.1", - "minimist": "^1.2.6", "moment": "^2.26.0", "moment-timezone": "^0.5.44", "mousetrap": "^1.6.1", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 105835f5ef8..a22ceb16baa 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -152,7 +152,6 @@ "mapbox-gl": "^2.10.0", "match-sorter": "^6.1.0", "memoize-one": "^5.1.1", - "minimist": "^1.2.6", "moment": "^2.26.0", "moment-timezone": "^0.5.44", "mousetrap": "^1.6.1", From 60004f5bf3a4f919c6fa71d586b2645816083972 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 10:59:14 -0700 Subject: [PATCH 24/39] chore(dependencies): removes unsued d3-color and d3-array (#26694) --- superset-frontend/package-lock.json | 2 -- superset-frontend/package.json | 2 -- 2 files changed, 4 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 035c4508efc..f5d80e0b1f0 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -63,8 +63,6 @@ "chrono-node": "^2.2.6", "classnames": "^2.2.5", "core-js": "^3.6.5", - "d3-array": "^1.2.4", - "d3-color": "^3.1.0", "d3-scale": "^2.1.2", "dom-to-image-more": "^2.10.1", "dom-to-pdf": "^0.3.2", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index a22ceb16baa..ad843b0fe2b 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -129,8 +129,6 @@ "chrono-node": "^2.2.6", "classnames": "^2.2.5", "core-js": "^3.6.5", - "d3-array": "^1.2.4", - "d3-color": "^3.1.0", "d3-scale": "^2.1.2", "dom-to-image-more": "^2.10.1", "dom-to-pdf": "^0.3.2", From a49526d9840c34786460d95eda5f88598664cc62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 11:42:29 -0700 Subject: [PATCH 25/39] build(deps): bump @babel/traverse from 7.22.8 to 7.23.2 in /superset-frontend (#25665) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From ef4878b845ea2d3de3c0ad83a4ebfc220d8f14f4 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 12:36:43 -0700 Subject: [PATCH 26/39] fix: do not use lodash/memoize (#26709) --- superset-frontend/src/utils/getControlsForVizType.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/superset-frontend/src/utils/getControlsForVizType.js b/superset-frontend/src/utils/getControlsForVizType.js index ae48b8b0d8c..8771d91dc7b 100644 --- a/superset-frontend/src/utils/getControlsForVizType.js +++ b/superset-frontend/src/utils/getControlsForVizType.js @@ -17,12 +17,12 @@ * under the License. */ -import memoize from 'lodash/memoize'; +import memoizeOne from 'memoize-one'; import { isControlPanelSectionConfig } from '@superset-ui/chart-controls'; import { getChartControlPanelRegistry } from '@superset-ui/core'; import { controls } from '../explore/controls'; -const memoizedControls = memoize((vizType, controlPanel) => { +const memoizedControls = memoizeOne((vizType, controlPanel) => { const controlsMap = {}; (controlPanel?.controlPanelSections || []) .filter(isControlPanelSectionConfig) From 3ed70d8f53c229682027df3efa7815ca12bd1328 Mon Sep 17 00:00:00 2001 From: Vitor Avila <96086495+Vitor-Avila@users.noreply.github.com> Date: Mon, 22 Jan 2024 16:37:03 -0300 Subject: [PATCH 27/39] fix(legacy-charts): Show Time Grain control for legacy charts (#26705) --- .../src/shared-controls/sharedControls.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx index a981c4422e9..9c1837ad87d 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx @@ -205,7 +205,7 @@ const time_grain_sqla: SharedControlConfig<'SelectControl'> = { choices: (datasource as Dataset)?.time_grain_sqla || [], }), visibility: ({ controls }) => { - if (!hasGenericChartAxes) { + if (!hasGenericChartAxes || !controls?.x_axis) { return true; } From ffc357c6a1dd6b739c4e09133a2c0ef22bb9a397 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Mon, 22 Jan 2024 13:50:16 -0700 Subject: [PATCH 28/39] chore(dependencies): loosen constraints on dependency checker (#26708) --- .github/workflows/dependency-review.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index ba00b5d3db2..d0804c7a74d 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -4,7 +4,7 @@ # # Source repository: https://github.com/actions/dependency-review-action # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement -name: 'Dependency Review' +name: "Dependency Review" on: [pull_request] permissions: @@ -14,12 +14,12 @@ jobs: dependency-review: runs-on: ubuntu-latest steps: - - name: 'Checkout Repository' + - name: "Checkout Repository" uses: actions/checkout@v3 - - name: 'Dependency Review' + - name: "Dependency Review" uses: actions/dependency-review-action@v2 with: - fail-on-severity: high + fail-on-severity: critical # compatible/incompatible licenses addressed here: https://www.apache.org/legal/resolved.html # find SPDX identifiers here: https://spdx.org/licenses/ deny-licenses: MS-LPL, BUSL-1.1, QPL-1.0, Sleepycat, SSPL-1.0, CPOL-1.02, AGPL-3.0, GPL-1.0+, BSD-4-Clause-UC, NPL-1.0, NPL-1.1, JSON From 5eb4e82d278b29f074d0530a473c54215446fbab Mon Sep 17 00:00:00 2001 From: Vitor Avila <96086495+Vitor-Avila@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:05:58 -0300 Subject: [PATCH 29/39] fix(db2): Improving support for ibm db2 connections (#26744) --- setup.py | 2 +- superset/db_engine_specs/db2.py | 55 ++++++++++++++ tests/unit_tests/db_engine_specs/test_db2.py | 75 ++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 tests/unit_tests/db_engine_specs/test_db2.py diff --git a/setup.py b/setup.py index cb02a7f4909..5f194f9978e 100644 --- a/setup.py +++ b/setup.py @@ -152,7 +152,7 @@ def get_git_sha() -> str: "databricks-sql-connector>=2.0.2, <3", "sqlalchemy-databricks>=0.2.0", ], - "db2": ["ibm-db-sa>=0.3.5, <0.4"], + "db2": ["ibm-db-sa>0.3.8, <=0.4.0"], "dremio": ["sqlalchemy-dremio>=1.1.5, <1.3"], "drill": ["sqlalchemy-drill==0.1.dev"], "druid": ["pydruid>=0.6.5,<0.7"], diff --git a/superset/db_engine_specs/db2.py b/superset/db_engine_specs/db2.py index 5f54613a4b5..db2e500b53d 100644 --- a/superset/db_engine_specs/db2.py +++ b/superset/db_engine_specs/db2.py @@ -14,9 +14,16 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +import logging +from typing import Optional, Union + +from sqlalchemy.engine.reflection import Inspector + from superset.constants import TimeGrain from superset.db_engine_specs.base import BaseEngineSpec, LimitMethod +logger = logging.getLogger(__name__) + class Db2EngineSpec(BaseEngineSpec): engine = "db2" @@ -26,6 +33,8 @@ class Db2EngineSpec(BaseEngineSpec): force_column_alias_quotes = True max_column_name_length = 30 + supports_dynamic_schema = True + _time_grain_expressions = { None: "{col}", TimeGrain.SECOND: "CAST({col} as TIMESTAMP) - MICROSECOND({col}) MICROSECONDS", @@ -52,3 +61,49 @@ class Db2EngineSpec(BaseEngineSpec): @classmethod def epoch_to_dttm(cls) -> str: return "(TIMESTAMP('1970-01-01', '00:00:00') + {col} SECONDS)" + + @classmethod + def get_table_comment( + cls, inspector: Inspector, table_name: str, schema: Union[str, None] + ) -> Optional[str]: + """ + Get comment of table from a given schema + + Ibm Db2 return comments as tuples, so we need to get the first element + + :param inspector: SqlAlchemy Inspector instance + :param table_name: Table name + :param schema: Schema name. If omitted, uses default schema for database + :return: comment of table + """ + comment = None + try: + table_comment = inspector.get_table_comment(table_name, schema) + comment = table_comment.get("text") + return comment[0] + except IndexError: + return comment + except Exception as ex: # pylint: disable=broad-except + logger.error("Unexpected error while fetching table comment", exc_info=True) + logger.exception(ex) + return comment + + @classmethod + def get_prequeries( + cls, + catalog: Union[str, None] = None, + schema: Union[str, None] = None, + ) -> list[str]: + """ + Set the search path to the specified schema. + + This is important for two reasons: in SQL Lab it will allow queries to run in + the schema selected in the dropdown, resolving unqualified table names to the + expected schema. + + But more importantly, in SQL Lab this is used to check if the user has access to + any tables with unqualified names. If the schema is not set by SQL Lab it could + be anything, and we would have to block users from running any queries + referencing tables without an explicit schema. + """ + return [f'set current_schema "{schema}"'] if schema else [] diff --git a/tests/unit_tests/db_engine_specs/test_db2.py b/tests/unit_tests/db_engine_specs/test_db2.py new file mode 100644 index 00000000000..d7dd19ad592 --- /dev/null +++ b/tests/unit_tests/db_engine_specs/test_db2.py @@ -0,0 +1,75 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import pytest +from pytest_mock import MockerFixture + + +def test_epoch_to_dttm() -> None: + """ + Test the `epoch_to_dttm` method. + """ + from superset.db_engine_specs.db2 import Db2EngineSpec + + assert ( + Db2EngineSpec.epoch_to_dttm().format(col="epoch_dttm") + == "(TIMESTAMP('1970-01-01', '00:00:00') + epoch_dttm SECONDS)" + ) + + +def test_get_table_comment(mocker: MockerFixture): + """ + Test the `get_table_comment` method. + """ + from superset.db_engine_specs.db2 import Db2EngineSpec + + mock_inspector = mocker.MagicMock() + mock_inspector.get_table_comment.return_value = { + "text": ("This is a table comment",) + } + + assert ( + Db2EngineSpec.get_table_comment(mock_inspector, "my_table", "my_schema") + == "This is a table comment" + ) + + +def test_get_table_comment_empty(mocker: MockerFixture): + """ + Test the `get_table_comment` method + when no comment is returned. + """ + from superset.db_engine_specs.db2 import Db2EngineSpec + + mock_inspector = mocker.MagicMock() + mock_inspector.get_table_comment.return_value = {} + + assert ( + Db2EngineSpec.get_table_comment(mock_inspector, "my_table", "my_schema") == None + ) + + +def test_get_prequeries() -> None: + """ + Test the ``get_prequeries`` method. + """ + from superset.db_engine_specs.db2 import Db2EngineSpec + + assert Db2EngineSpec.get_prequeries() == [] + assert Db2EngineSpec.get_prequeries(schema="my_schema") == [ + 'set current_schema "my_schema"' + ] From be748f35cdfc628f32f4c4e767a1beb8bcd015c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:53:06 -0700 Subject: [PATCH 30/39] build(deps): bump @docsearch/react from 3.3.3 to 3.5.2 in /docs (#26720) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package.json | 2 +- docs/yarn.lock | 362 ++++++++++++++-------------------------------- 2 files changed, 106 insertions(+), 258 deletions(-) diff --git a/docs/package.json b/docs/package.json index 9bcde81fa72..6cef203b48b 100644 --- a/docs/package.json +++ b/docs/package.json @@ -18,7 +18,7 @@ "dependencies": { "@algolia/client-search": "^4.22.1", "@ant-design/icons": "^4.7.0", - "@docsearch/react": "^3.3.3", + "@docsearch/react": "^3.5.2", "@docusaurus/core": "^2.4.1", "@docusaurus/plugin-client-redirects": "^2.4.3", "@docusaurus/plugin-google-gtag": "^2.4.1", diff --git a/docs/yarn.lock b/docs/yarn.lock index 3a666ab6619..57dd13d81d2 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -2,121 +2,70 @@ # yarn lockfile v1 -"@algolia/autocomplete-core@1.7.4": - version "1.7.4" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.4.tgz#85ff36b2673654a393c8c505345eaedd6eaa4f70" - integrity sha512-daoLpQ3ps/VTMRZDEBfU8ixXd+amZcNJ4QSP3IERGyzqnL5Ch8uSRFt/4G8pUvW9c3o6GA4vtVv4I4lmnkdXyg== - dependencies: - "@algolia/autocomplete-shared" "1.7.4" - -"@algolia/autocomplete-preset-algolia@1.7.4": - version "1.7.4" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.4.tgz#610ee1d887962f230b987cba2fd6556478000bc3" - integrity sha512-s37hrvLEIfcmKY8VU9LsAXgm2yfmkdHT3DnA3SgHaY93yjZ2qL57wzb5QweVkYuEBZkT2PIREvRoLXC2sxTbpQ== +"@algolia/autocomplete-core@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz#1d56482a768c33aae0868c8533049e02e8961be7" + integrity sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw== dependencies: - "@algolia/autocomplete-shared" "1.7.4" + "@algolia/autocomplete-plugin-algolia-insights" "1.9.3" + "@algolia/autocomplete-shared" "1.9.3" -"@algolia/autocomplete-shared@1.7.4": - version "1.7.4" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.4.tgz#78aea1140a50c4d193e1f06a13b7f12c5e2cbeea" - integrity sha512-2VGCk7I9tA9Ge73Km99+Qg87w0wzW4tgUruvWAn/gfey1ZXgmxZtyIRBebk35R1O8TbK77wujVtCnpsGpRy1kg== - -"@algolia/cache-browser-local-storage@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.11.0.tgz" - integrity sha512-4sr9vHIG1fVA9dONagdzhsI/6M5mjs/qOe2xUP0yBmwsTsuwiZq3+Xu6D3dsxsuFetcJgC6ydQoCW8b7fDJHYQ== +"@algolia/autocomplete-plugin-algolia-insights@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz#9b7f8641052c8ead6d66c1623d444cbe19dde587" + integrity sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg== dependencies: - "@algolia/cache-common" "4.11.0" + "@algolia/autocomplete-shared" "1.9.3" -"@algolia/cache-browser-local-storage@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.15.0.tgz#84f12aec6b6aa69542a3bfd3a4ba458ed2cc8230" - integrity sha512-uxxFhTWh4JJDb2+FFSmNMfEQ8p9o2vjSpU7iW007QX3OvqljPPN68lk3bpZVaG8pwr5MU1DqpkZ71FcQdVTjgQ== +"@algolia/autocomplete-preset-algolia@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz#64cca4a4304cfcad2cf730e83067e0c1b2f485da" + integrity sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA== dependencies: - "@algolia/cache-common" "4.15.0" + "@algolia/autocomplete-shared" "1.9.3" -"@algolia/cache-common@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.11.0.tgz" - integrity sha512-lODcJRuPXqf+6mp0h6bOxPMlbNoyn3VfjBVcQh70EDP0/xExZbkpecgHyyZK4kWg+evu+mmgvTK3GVHnet/xKw== +"@algolia/autocomplete-shared@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz#2e22e830d36f0a9cf2c0ccd3c7f6d59435b77dfa" + integrity sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ== -"@algolia/cache-common@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.15.0.tgz#a198098c4b8fa6ef661879ec22d2a2d1ad77d2bb" - integrity sha512-Me3PbI4QurAM+3D+htIE0l1xt6+bl/18SG6Wc7bPQEZAtN7DTGz22HqhKNyLF2lR/cOfpaH7umXZlZEhIHf7gQ== +"@algolia/cache-browser-local-storage@4.22.1": + version "4.22.1" + resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.1.tgz#14b6dc9abc9e3a304a5fffb063d15f30af1032d1" + integrity sha512-Sw6IAmOCvvP6QNgY9j+Hv09mvkvEIDKjYW8ow0UDDAxSXy664RBNQk3i/0nt7gvceOJ6jGmOTimaZoY1THmU7g== + dependencies: + "@algolia/cache-common" "4.22.1" "@algolia/cache-common@4.22.1": version "4.22.1" resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.22.1.tgz#c625dff4bc2a74e79f9aed67b4e053b0ef1b3ec1" integrity sha512-TJMBKqZNKYB9TptRRjSUtevJeQVXRmg6rk9qgFKWvOy8jhCPdyNZV1nB3SKGufzvTVbomAukFR8guu/8NRKBTA== -"@algolia/cache-in-memory@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.11.0.tgz" - integrity sha512-aBz+stMSTBOBaBEQ43zJXz2DnwS7fL6dR0e2myehAgtfAWlWwLDHruc/98VOy1ZAcBk1blE2LCU02bT5HekGxQ== - dependencies: - "@algolia/cache-common" "4.11.0" - -"@algolia/cache-in-memory@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.15.0.tgz#77cac4db36a0aa0837f7a7ceb760188191e35268" - integrity sha512-B9mg1wd7CKMfpkbiTQ8KlcKkH6ut/goVaI6XmDCUczOOqeuZlV34tuEi7o3Xo1j66KWr/d9pMjjGYcoVPCVeOA== - dependencies: - "@algolia/cache-common" "4.15.0" - -"@algolia/client-account@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.11.0.tgz" - integrity sha512-jwmFBoUSzoMwMqgD3PmzFJV/d19p1RJXB6C1ADz4ju4mU7rkaQLtqyZroQpheLoU5s5Tilmn/T8/0U2XLoJCRQ== - dependencies: - "@algolia/client-common" "4.11.0" - "@algolia/client-search" "4.11.0" - "@algolia/transporter" "4.11.0" - -"@algolia/client-account@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.15.0.tgz#8e0723052169665b4449dc2f8bcf3075feb6a424" - integrity sha512-8wqI33HRZy5ydfFt6F5vMhtkOiAUhVfSCYXx4U3Go5RALqWLgVUp6wzOo0mr1z08POCkHDpbQMQvyayb1CZ/kw== - dependencies: - "@algolia/client-common" "4.15.0" - "@algolia/client-search" "4.15.0" - "@algolia/transporter" "4.15.0" - -"@algolia/client-analytics@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.11.0.tgz" - integrity sha512-v5U9585aeEdYml7JqggHAj3E5CQ+jPwGVztPVhakBk8H/cmLyPS2g8wvmIbaEZCHmWn4TqFj3EBHVYxAl36fSA== - dependencies: - "@algolia/client-common" "4.11.0" - "@algolia/client-search" "4.11.0" - "@algolia/requester-common" "4.11.0" - "@algolia/transporter" "4.11.0" - -"@algolia/client-analytics@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.15.0.tgz#6b8fe450e1bba114b0d0598cbf9acac482798a36" - integrity sha512-jrPjEeNEIIQKeA1XCZXx3f3aybtwF7wjYlnfHbLARuZ9AuHzimOKjX0ZwqvMmvTsHivpcZ2rqY+j1E8HoH1ELA== +"@algolia/cache-in-memory@4.22.1": + version "4.22.1" + resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.22.1.tgz#858a3d887f521362e87d04f3943e2810226a0d71" + integrity sha512-ve+6Ac2LhwpufuWavM/aHjLoNz/Z/sYSgNIXsinGofWOysPilQZPUetqLj8vbvi+DHZZaYSEP9H5SRVXnpsNNw== dependencies: - "@algolia/client-common" "4.15.0" - "@algolia/client-search" "4.15.0" - "@algolia/requester-common" "4.15.0" - "@algolia/transporter" "4.15.0" + "@algolia/cache-common" "4.22.1" -"@algolia/client-common@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.11.0.tgz" - integrity sha512-Qy+F+TZq12kc7tgfC+FM3RvYH/Ati7sUiUv/LkvlxFwNwNPwWGoZO81AzVSareXT/ksDDrabD4mHbdTbBPTRmQ== +"@algolia/client-account@4.22.1": + version "4.22.1" + resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.22.1.tgz#a7fb8b66b9a4f0a428e1426b2561144267d76d43" + integrity sha512-k8m+oegM2zlns/TwZyi4YgCtyToackkOpE+xCaKCYfBfDtdGOaVZCM5YvGPtK+HGaJMIN/DoTL8asbM3NzHonw== dependencies: - "@algolia/requester-common" "4.11.0" - "@algolia/transporter" "4.11.0" + "@algolia/client-common" "4.22.1" + "@algolia/client-search" "4.22.1" + "@algolia/transporter" "4.22.1" -"@algolia/client-common@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.15.0.tgz#27dd9441aedf481736696d519e55ea8e2f5a4432" - integrity sha512-PlsJMObZuYw4JlG5EhYv1PHDOv7n5mD5PzqFyoNfSOYaEPRZepa3W579ya29yOu3FZ0VGMNJmB7Q5v/+/fwvIw== +"@algolia/client-analytics@4.22.1": + version "4.22.1" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.22.1.tgz#506558740b4d49b1b1e3393861f729a8ce921851" + integrity sha512-1ssi9pyxyQNN4a7Ji9R50nSdISIumMFDwKNuwZipB6TkauJ8J7ha/uO60sPJFqQyqvvI+px7RSNRQT3Zrvzieg== dependencies: - "@algolia/requester-common" "4.15.0" - "@algolia/transporter" "4.15.0" + "@algolia/client-common" "4.22.1" + "@algolia/client-search" "4.22.1" + "@algolia/requester-common" "4.22.1" + "@algolia/transporter" "4.22.1" "@algolia/client-common@4.22.1": version "4.22.1" @@ -126,43 +75,16 @@ "@algolia/requester-common" "4.22.1" "@algolia/transporter" "4.22.1" -"@algolia/client-personalization@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.11.0.tgz" - integrity sha512-mI+X5IKiijHAzf9fy8VSl/GTT67dzFDnJ0QAM8D9cMPevnfX4U72HRln3Mjd0xEaYUOGve8TK/fMg7d3Z5yG6g== - dependencies: - "@algolia/client-common" "4.11.0" - "@algolia/requester-common" "4.11.0" - "@algolia/transporter" "4.11.0" - -"@algolia/client-personalization@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.15.0.tgz#6f10eda827d2607ab6c2341464cd35107bf8cf99" - integrity sha512-Bf0bhRAiNL9LWurzyHRH8UBi4fDt3VbCNkInxVngKQT1uCZWXecwoPWGhcSSpdanBqFJA/1WBt+BWx7a50Bhlg== - dependencies: - "@algolia/client-common" "4.15.0" - "@algolia/requester-common" "4.15.0" - "@algolia/transporter" "4.15.0" - -"@algolia/client-search@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.11.0.tgz" - integrity sha512-iovPLc5YgiXBdw2qMhU65sINgo9umWbHFzInxoNErWnYoTQWfXsW6P54/NlKx5uscoLVjSf+5RUWwFu5BX+lpw== - dependencies: - "@algolia/client-common" "4.11.0" - "@algolia/requester-common" "4.11.0" - "@algolia/transporter" "4.11.0" - -"@algolia/client-search@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.15.0.tgz#2d849faae7943fcc983ac923eac767666a9e6a9a" - integrity sha512-dTwZD4u53WdmexnMcoO2Qd/+YCP3ESXKOtD2MryQ1a9dHwB2Y3Qob0kyS1PG82idwM3enbznvscI9Sf4o9PUWQ== +"@algolia/client-personalization@4.22.1": + version "4.22.1" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.22.1.tgz#ff088d797648224fb582e9fe5828f8087835fa3d" + integrity sha512-sl+/klQJ93+4yaqZ7ezOttMQ/nczly/3GmgZXJ1xmoewP5jmdP/X/nV5U7EHHH3hCUEHeN7X1nsIhGPVt9E1cQ== dependencies: - "@algolia/client-common" "4.15.0" - "@algolia/requester-common" "4.15.0" - "@algolia/transporter" "4.15.0" + "@algolia/client-common" "4.22.1" + "@algolia/requester-common" "4.22.1" + "@algolia/transporter" "4.22.1" -"@algolia/client-search@^4.22.1": +"@algolia/client-search@4.22.1", "@algolia/client-search@^4.22.1": version "4.22.1" resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.22.1.tgz#508cc6ab3d1f4e9c02735a630d4dff6fbb8514a2" integrity sha512-yb05NA4tNaOgx3+rOxAmFztgMTtGBi97X7PC3jyNeGiwkAjOZc2QrdZBYyIdcDLoI09N0gjtpClcackoTN0gPA== @@ -176,95 +98,36 @@ resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== -"@algolia/logger-common@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.11.0.tgz" - integrity sha512-pRMJFeOY8hoWKIxWuGHIrqnEKN/kqKh7UilDffG/+PeEGxBuku+Wq5CfdTFG0C9ewUvn8mAJn5BhYA5k8y0Jqg== - -"@algolia/logger-common@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.15.0.tgz#a2cf3d3abbdd00594006164302600ba46d75059f" - integrity sha512-D8OFwn/HpvQz66goIcjxOKsYBMuxiruxJ3cA/bnc0EiDvSA2P2z6bNQWgS5gbstuTZIJmbhr+53NyOxFkmMNAA== - "@algolia/logger-common@4.22.1": version "4.22.1" resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.22.1.tgz#79cf4cd295de0377a94582c6aaac59b1ded731d9" integrity sha512-OnTFymd2odHSO39r4DSWRFETkBufnY2iGUZNrMXpIhF5cmFE8pGoINNPzwg02QLBlGSaLqdKy0bM8S0GyqPLBg== -"@algolia/logger-console@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.11.0.tgz" - integrity sha512-wXztMk0a3VbNmYP8Kpc+F7ekuvaqZmozM2eTLok0XIshpAeZ/NJDHDffXK2Pw+NF0wmHqurptLYwKoikjBYvhQ== - dependencies: - "@algolia/logger-common" "4.11.0" - -"@algolia/logger-console@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.15.0.tgz#8a0948b0c16ad546af9dd14b9021f21f42737c97" - integrity sha512-pQOvVaRSEJQJRXKTnxEA6nN1hipSQadJJ4einw0nIlfMOGZh/kps1ybh8vRUlUGyfEuN/3dyFs0W3Ac7hIItlg== - dependencies: - "@algolia/logger-common" "4.15.0" - -"@algolia/requester-browser-xhr@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.11.0.tgz" - integrity sha512-Fp3SfDihAAFR8bllg8P5ouWi3+qpEVN5e7hrtVIYldKBOuI/qFv80Zv/3/AMKNJQRYglS4zWyPuqrXm58nz6KA== +"@algolia/logger-console@4.22.1": + version "4.22.1" + resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.22.1.tgz#0355345f6940f67aaa78ae9b81c06e44e49f2336" + integrity sha512-O99rcqpVPKN1RlpgD6H3khUWylU24OXlzkavUAMy6QZd1776QAcauE3oP8CmD43nbaTjBexZj2nGsBH9Tc0FVA== dependencies: - "@algolia/requester-common" "4.11.0" + "@algolia/logger-common" "4.22.1" -"@algolia/requester-browser-xhr@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.15.0.tgz#38b5956d01408ad4291d89915df921ff8534cca6" - integrity sha512-va186EfALF+6msYZXaoBSxcnFCg3SoWJ+uv1yMyhQRJRe7cZSHWSVT3s40vmar90gxlBu80KMVwVlsvJhJv6ew== +"@algolia/requester-browser-xhr@4.22.1": + version "4.22.1" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.1.tgz#f04df6fe9690a071b267c77d26b83a3be9280361" + integrity sha512-dtQGYIg6MteqT1Uay3J/0NDqD+UciHy3QgRbk7bNddOJu+p3hzjTRYESqEnoX/DpEkaNYdRHUKNylsqMpgwaEw== dependencies: - "@algolia/requester-common" "4.15.0" - -"@algolia/requester-common@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.11.0.tgz" - integrity sha512-+cZGe/9fuYgGuxjaBC+xTGBkK7OIYdfapxhfvEf03dviLMPmhmVYFJtJlzAjQ2YmGDJpHrGgAYj3i/fbs8yhiA== - -"@algolia/requester-common@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.15.0.tgz#c68ad3dccc1de71b5be9b08a07e2baf58ec49d82" - integrity sha512-w0UUzxElbo4hrKg4QP/jiXDNbIJuAthxdlkos9nS8KAPK2XI3R9BlUjLz/ZVs4F9TDGI0mhjrNHhZ12KXcoyhg== + "@algolia/requester-common" "4.22.1" "@algolia/requester-common@4.22.1": version "4.22.1" resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.22.1.tgz#27be35f3718aafcb6b388ff9c3aa2defabd559ff" integrity sha512-dgvhSAtg2MJnR+BxrIFqlLtkLlVVhas9HgYKMk2Uxiy5m6/8HZBL40JVAMb2LovoPFs9I/EWIoFVjOrFwzn5Qg== -"@algolia/requester-node-http@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.11.0.tgz" - integrity sha512-qJIk9SHRFkKDi6dMT9hba8X1J1z92T5AZIgl+tsApjTGIRQXJLTIm+0q4yOefokfu4CoxYwRZ9QAq+ouGwfeOg== - dependencies: - "@algolia/requester-common" "4.11.0" - -"@algolia/requester-node-http@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.15.0.tgz#02f841586e620c7b4e4e555f315cd52dd815f330" - integrity sha512-eeEOhFtgwKcgAlKAZpgBRZJ0ILSEBCXxZ9uwfVWPD24W1b6z08gVoTJ6J7lCeCnJmudg+tMElDnGzHkjup9CJA== - dependencies: - "@algolia/requester-common" "4.15.0" - -"@algolia/transporter@4.11.0": - version "4.11.0" - resolved "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.11.0.tgz" - integrity sha512-k4dyxiaEfYpw4UqybK9q7lrFzehygo6KV3OCYJMMdX0IMWV0m4DXdU27c1zYRYtthaFYaBzGF4Kjcl8p8vxCKw== - dependencies: - "@algolia/cache-common" "4.11.0" - "@algolia/logger-common" "4.11.0" - "@algolia/requester-common" "4.11.0" - -"@algolia/transporter@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.15.0.tgz#c65c512206c66aadc2897337220ae5454001967e" - integrity sha512-JoWR+ixG3EmA0UPntQFN/FV5TasYcYu93d5+oKzHFeZ6Z7rtW5Im9iy/Oh/ggk1AAN5fTdqKewtbBpdaYDbKsQ== +"@algolia/requester-node-http@4.22.1": + version "4.22.1" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.22.1.tgz#589a6fa828ad0f325e727a6fcaf4e1a2343cc62b" + integrity sha512-JfmZ3MVFQkAU+zug8H3s8rZ6h0ahHZL/SpMaSasTCGYR5EEJsCc8SI5UZ6raPN2tjxa5bxS13BRpGSBUens7EA== dependencies: - "@algolia/cache-common" "4.15.0" - "@algolia/logger-common" "4.15.0" - "@algolia/requester-common" "4.15.0" + "@algolia/requester-common" "4.22.1" "@algolia/transporter@4.22.1": version "4.22.1" @@ -2593,20 +2456,20 @@ resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz#c3c5ae543c897caa9c2a68630bed355be5f9990f" integrity sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ== -"@docsearch/css@3.3.3": - version "3.3.3" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.3.3.tgz#f9346c9e24602218341f51b8ba91eb9109add434" - integrity sha512-6SCwI7P8ao+se1TUsdZ7B4XzL+gqeQZnBc+2EONZlcVa0dVrk0NjETxozFKgMv0eEGH8QzP1fkN+A1rH61l4eg== +"@docsearch/css@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.5.2.tgz#610f47b48814ca94041df969d9fcc47b91fc5aac" + integrity sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA== -"@docsearch/react@^3.1.1", "@docsearch/react@^3.3.3": - version "3.3.3" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.3.3.tgz#907b6936a565f880b4c0892624b4f7a9f132d298" - integrity sha512-pLa0cxnl+G0FuIDuYlW+EBK6Rw2jwLw9B1RHIeS4N4s2VhsfJ/wzeCi3CWcs5yVfxLd5ZK50t//TMA5e79YT7Q== +"@docsearch/react@^3.1.1", "@docsearch/react@^3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.5.2.tgz#2e6bbee00eb67333b64906352734da6aef1232b9" + integrity sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng== dependencies: - "@algolia/autocomplete-core" "1.7.4" - "@algolia/autocomplete-preset-algolia" "1.7.4" - "@docsearch/css" "3.3.3" - algoliasearch "^4.0.0" + "@algolia/autocomplete-core" "1.9.3" + "@algolia/autocomplete-preset-algolia" "1.9.3" + "@docsearch/css" "3.5.2" + algoliasearch "^4.19.1" "@docusaurus/core@2.4.3", "@docusaurus/core@^2.4.1": version "2.4.3" @@ -4126,45 +3989,25 @@ algoliasearch-helper@^3.10.0: dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^4.0.0: - version "4.11.0" - resolved "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.11.0.tgz" - integrity sha512-IXRj8kAP2WrMmj+eoPqPc6P7Ncq1yZkFiyDrjTBObV1ADNL8Z/KdZ+dWC5MmYcBLAbcB/mMCpak5N/D1UIZvsA== - dependencies: - "@algolia/cache-browser-local-storage" "4.11.0" - "@algolia/cache-common" "4.11.0" - "@algolia/cache-in-memory" "4.11.0" - "@algolia/client-account" "4.11.0" - "@algolia/client-analytics" "4.11.0" - "@algolia/client-common" "4.11.0" - "@algolia/client-personalization" "4.11.0" - "@algolia/client-search" "4.11.0" - "@algolia/logger-common" "4.11.0" - "@algolia/logger-console" "4.11.0" - "@algolia/requester-browser-xhr" "4.11.0" - "@algolia/requester-common" "4.11.0" - "@algolia/requester-node-http" "4.11.0" - "@algolia/transporter" "4.11.0" - -algoliasearch@^4.13.1: - version "4.15.0" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.15.0.tgz#8279576f06667a1d0705e8c22a17daa8e707b469" - integrity sha512-+vgKQF5944dYsz9zhKk07JbOYeNdKisoD5GeG0woBL3nLzbn2a+nGwki60DXg7CXvaFXBcTXyJG4C+VaBVd44g== - dependencies: - "@algolia/cache-browser-local-storage" "4.15.0" - "@algolia/cache-common" "4.15.0" - "@algolia/cache-in-memory" "4.15.0" - "@algolia/client-account" "4.15.0" - "@algolia/client-analytics" "4.15.0" - "@algolia/client-common" "4.15.0" - "@algolia/client-personalization" "4.15.0" - "@algolia/client-search" "4.15.0" - "@algolia/logger-common" "4.15.0" - "@algolia/logger-console" "4.15.0" - "@algolia/requester-browser-xhr" "4.15.0" - "@algolia/requester-common" "4.15.0" - "@algolia/requester-node-http" "4.15.0" - "@algolia/transporter" "4.15.0" +algoliasearch@^4.13.1, algoliasearch@^4.19.1: + version "4.22.1" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.22.1.tgz#f10fbecdc7654639ec20d62f109c1b3a46bc6afc" + integrity sha512-jwydKFQJKIx9kIZ8Jm44SdpigFwRGPESaxZBaHSV0XWN2yBJAOT4mT7ppvlrpA4UGzz92pqFnVKr/kaZXrcreg== + dependencies: + "@algolia/cache-browser-local-storage" "4.22.1" + "@algolia/cache-common" "4.22.1" + "@algolia/cache-in-memory" "4.22.1" + "@algolia/client-account" "4.22.1" + "@algolia/client-analytics" "4.22.1" + "@algolia/client-common" "4.22.1" + "@algolia/client-personalization" "4.22.1" + "@algolia/client-search" "4.22.1" + "@algolia/logger-common" "4.22.1" + "@algolia/logger-console" "4.22.1" + "@algolia/requester-browser-xhr" "4.22.1" + "@algolia/requester-common" "4.22.1" + "@algolia/requester-node-http" "4.22.1" + "@algolia/transporter" "4.22.1" ansi-align@^3.0.0, ansi-align@^3.0.1: version "3.0.1" @@ -8527,6 +8370,11 @@ prismjs@^1.28.0: resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== +prismjs@~1.28.0: + version "1.28.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.28.0.tgz#0d8f561fa0f7cf6ebca901747828b149147044b6" + integrity sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" From 6a1ce6a70499dc1090570a40c7de9ba89bf8429a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:54:31 -0700 Subject: [PATCH 31/39] build(deps): bump @saucelabs/theme-github-codeblock from 0.1.1 to 0.2.3 in /docs (#26724) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package.json | 2 +- docs/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/package.json b/docs/package.json index 6cef203b48b..2884c0d204f 100644 --- a/docs/package.json +++ b/docs/package.json @@ -26,7 +26,7 @@ "@emotion/core": "^10.1.1", "@emotion/styled": "^10.0.27", "@mdx-js/react": "^1.6.22", - "@saucelabs/theme-github-codeblock": "^0.1.1", + "@saucelabs/theme-github-codeblock": "^0.2.3", "@superset-ui/style": "^0.14.23", "@svgr/webpack": "^5.5.0", "antd": "^4.19.3", diff --git a/docs/yarn.lock b/docs/yarn.lock index 57dd13d81d2..46648f60f97 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -3180,10 +3180,10 @@ resolved "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz" integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== -"@saucelabs/theme-github-codeblock@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@saucelabs/theme-github-codeblock/-/theme-github-codeblock-0.1.1.tgz#d2caa3fbf56c38ae2fe974871f1188226bb57d92" - integrity sha512-iHzODYjcUAYI4eJzLrNCw/Iq9SWxCKB/cMgEKHjRmNMb2NKch1dsI2ZSCg8lNedIPmOaRfqHT29hLyMoc/5Wpg== +"@saucelabs/theme-github-codeblock@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@saucelabs/theme-github-codeblock/-/theme-github-codeblock-0.2.3.tgz#706a43292f600532271979941b0155db667c2c21" + integrity sha512-GSl3Lr/jOWm4OP3BPX2vXxc8FMSOXj1mJnls6cUqMwlGOfKQ1Ia9pq1O9/ES+5TrZHIzAws/n5FFSn1OkGJw/Q== "@sideway/address@^4.1.3": version "4.1.4" From 75a98af64bb1f1f2ac8e98a337d0b26ad60bcca5 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Mon, 22 Jan 2024 16:24:07 -0800 Subject: [PATCH 32/39] feat: auto-label PRs that contain db migrations (#26745) --- .github/workflows/label-migration-pr.yml | 25 ++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/label-migration-pr.yml diff --git a/.github/workflows/label-migration-pr.yml b/.github/workflows/label-migration-pr.yml new file mode 100644 index 00000000000..e0b46e163cf --- /dev/null +++ b/.github/workflows/label-migration-pr.yml @@ -0,0 +1,25 @@ +name: Label Migration PR + +on: + pull_request: + paths: + - 'superset/migrations/**' + +jobs: + label: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Add label + uses: actions/github-script@v3 + with: + github-token: ${{github.token}} + script: | + github.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['risk:db-migration'] + }) From 60d1e4e95abd9a6bb3009e1c88f5ad2dd82965c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:22:21 -0700 Subject: [PATCH 33/39] build(deps): bump @emotion/babel-preset-css-prop from 11.2.0 to 11.11.0 in /superset-frontend (#26576) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- superset-frontend/package-lock.json | 211 ++++++++++++++++------------ superset-frontend/package.json | 2 +- 2 files changed, 126 insertions(+), 87 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index f5d80e0b1f0..149981c3fd9 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -15,7 +15,7 @@ ], "dependencies": { "@ant-design/icons": "^5.0.1", - "@emotion/babel-preset-css-prop": "^11.2.0", + "@emotion/babel-preset-css-prop": "^11.11.0", "@emotion/cache": "^11.4.0", "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", @@ -5187,64 +5187,84 @@ } }, "node_modules/@emotion/babel-plugin": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.3.0.tgz", - "integrity": "sha512-UZKwBV2rADuhRp+ZOGgNWg2eYgbzKzQXfQPtJbu/PLy8onurxlNCLvxMQEvlr1/GudguPI5IU9qIY1+2z1M5bA==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", "dependencies": { - "@babel/helper-module-imports": "^7.12.13", - "@babel/plugin-syntax-jsx": "^7.12.13", - "@babel/runtime": "^7.13.10", - "@emotion/hash": "^0.8.0", - "@emotion/memoize": "^0.7.5", - "@emotion/serialize": "^1.0.2", - "babel-plugin-macros": "^2.6.1", + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", - "stylis": "^4.0.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "stylis": "4.2.0" } }, "node_modules/@emotion/babel-plugin-jsx-pragmatic": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin-jsx-pragmatic/-/babel-plugin-jsx-pragmatic-0.1.5.tgz", - "integrity": "sha512-y+3AJ0SItMDaAgGPVkQBC/S/BaqaPACkQ6MyCI2CUlrjTxKttTVfD3TMtcs7vLEcLxqzZ1xiG0vzwCXjhopawQ==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin-jsx-pragmatic/-/babel-plugin-jsx-pragmatic-0.2.1.tgz", + "integrity": "sha512-xy1SlgEJygAAIvIuC2idkGKJYa6v5iwoyILkvNKgk347bV+IImXrUat5Z86EmLGyWhEoTplVT9EHqTnHZG4HFw==", "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "@babel/plugin-syntax-jsx": "^7.17.12" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz", - "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/babel-plugin/node_modules/@emotion/serialize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz", - "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", + "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", "dependencies": { - "@emotion/hash": "^0.8.0", - "@emotion/memoize": "^0.7.4", - "@emotion/unitless": "^0.7.5", - "@emotion/utils": "^1.0.0", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", "csstype": "^3.0.2" } }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, "node_modules/@emotion/babel-plugin/node_modules/@emotion/utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.0.0.tgz", - "integrity": "sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/babel-plugin/node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } }, "node_modules/@emotion/babel-plugin/node_modules/csstype": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", - "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { "version": "4.0.0", @@ -5266,14 +5286,14 @@ } }, "node_modules/@emotion/babel-preset-css-prop": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-preset-css-prop/-/babel-preset-css-prop-11.2.0.tgz", - "integrity": "sha512-9XLQm2eLPYTho+Cx1LQTDA1rATjoAaB4O+ds55XDvoAa+Z16Hhg8y5Vihj3C8E6+ilDM8SV5A9Z6z+yj0YIRBg==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-preset-css-prop/-/babel-preset-css-prop-11.11.0.tgz", + "integrity": "sha512-+1Cba68IyBeltWzvbBSXcBWqP2eKQuQcSUpIu3ma4pOUeRol4EvwWrYS2Rv51aIVqg066fLB+Z9O/8NKR7uUlQ==", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.12.1", - "@babel/runtime": "^7.7.2", - "@emotion/babel-plugin": "^11.2.0", - "@emotion/babel-plugin-jsx-pragmatic": "^0.1.5" + "@babel/plugin-transform-react-jsx": "^7.17.12", + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/babel-plugin-jsx-pragmatic": "^0.2.1" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -56298,9 +56318,9 @@ } }, "node_modules/stylis": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.9.tgz", - "integrity": "sha512-ci7pEFNVW3YJiWEzqPOMsAjY6kgraZ3ZgBfQ5HYbNtLJEsQ0G46ejWZpfSSCp/FaSiCSGGhzL9O2lN+2cB6ong==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "node_modules/supercluster": { "version": "4.1.1", @@ -67444,50 +67464,69 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==" }, "@emotion/babel-plugin": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.3.0.tgz", - "integrity": "sha512-UZKwBV2rADuhRp+ZOGgNWg2eYgbzKzQXfQPtJbu/PLy8onurxlNCLvxMQEvlr1/GudguPI5IU9qIY1+2z1M5bA==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", "requires": { - "@babel/helper-module-imports": "^7.12.13", - "@babel/plugin-syntax-jsx": "^7.12.13", - "@babel/runtime": "^7.13.10", - "@emotion/hash": "^0.8.0", - "@emotion/memoize": "^0.7.5", - "@emotion/serialize": "^1.0.2", - "babel-plugin-macros": "^2.6.1", + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", - "stylis": "^4.0.3" + "stylis": "4.2.0" }, "dependencies": { + "@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, "@emotion/memoize": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz", - "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "@emotion/serialize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz", - "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", + "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", "requires": { - "@emotion/hash": "^0.8.0", - "@emotion/memoize": "^0.7.4", - "@emotion/unitless": "^0.7.5", - "@emotion/utils": "^1.0.0", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", "csstype": "^3.0.2" } }, + "@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, "@emotion/utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.0.0.tgz", - "integrity": "sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "requires": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + } }, "csstype": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", - "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "escape-string-regexp": { "version": "4.0.0", @@ -67502,22 +67541,22 @@ } }, "@emotion/babel-plugin-jsx-pragmatic": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin-jsx-pragmatic/-/babel-plugin-jsx-pragmatic-0.1.5.tgz", - "integrity": "sha512-y+3AJ0SItMDaAgGPVkQBC/S/BaqaPACkQ6MyCI2CUlrjTxKttTVfD3TMtcs7vLEcLxqzZ1xiG0vzwCXjhopawQ==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin-jsx-pragmatic/-/babel-plugin-jsx-pragmatic-0.2.1.tgz", + "integrity": "sha512-xy1SlgEJygAAIvIuC2idkGKJYa6v5iwoyILkvNKgk347bV+IImXrUat5Z86EmLGyWhEoTplVT9EHqTnHZG4HFw==", "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "@babel/plugin-syntax-jsx": "^7.17.12" } }, "@emotion/babel-preset-css-prop": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-preset-css-prop/-/babel-preset-css-prop-11.2.0.tgz", - "integrity": "sha512-9XLQm2eLPYTho+Cx1LQTDA1rATjoAaB4O+ds55XDvoAa+Z16Hhg8y5Vihj3C8E6+ilDM8SV5A9Z6z+yj0YIRBg==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-preset-css-prop/-/babel-preset-css-prop-11.11.0.tgz", + "integrity": "sha512-+1Cba68IyBeltWzvbBSXcBWqP2eKQuQcSUpIu3ma4pOUeRol4EvwWrYS2Rv51aIVqg066fLB+Z9O/8NKR7uUlQ==", "requires": { - "@babel/plugin-transform-react-jsx": "^7.12.1", - "@babel/runtime": "^7.7.2", - "@emotion/babel-plugin": "^11.2.0", - "@emotion/babel-plugin-jsx-pragmatic": "^0.1.5" + "@babel/plugin-transform-react-jsx": "^7.17.12", + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/babel-plugin-jsx-pragmatic": "^0.2.1" } }, "@emotion/cache": { @@ -107735,9 +107774,9 @@ } }, "stylis": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.9.tgz", - "integrity": "sha512-ci7pEFNVW3YJiWEzqPOMsAjY6kgraZ3ZgBfQ5HYbNtLJEsQ0G46ejWZpfSSCp/FaSiCSGGhzL9O2lN+2cB6ong==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "supercluster": { "version": "4.1.1", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index ad843b0fe2b..3e60c295e9d 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -81,7 +81,7 @@ ], "dependencies": { "@ant-design/icons": "^5.0.1", - "@emotion/babel-preset-css-prop": "^11.2.0", + "@emotion/babel-preset-css-prop": "^11.11.0", "@emotion/cache": "^11.4.0", "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", From 43cf0c69ecb6369a9ff02bb1a671a905aebf0de5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:22:38 -0700 Subject: [PATCH 34/39] build(deps-dev): bump eslint-plugin-react-hooks from 4.2.0 to 4.6.0 in /superset-frontend (#26572) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- superset-frontend/package-lock.json | 16 ++++++++-------- superset-frontend/package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 149981c3fd9..ea70d680b19 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -227,7 +227,7 @@ "eslint-plugin-no-only-tests": "^2.4.0", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.22.0", - "eslint-plugin-react-hooks": "^4.2.0", + "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-testing-library": "^3.10.2", "eslint-plugin-theme-colors": "file:tools/eslint-plugin-theme-colors", "eslint-plugin-translation-vars": "file:tools/eslint-plugin-translation-vars", @@ -31156,15 +31156,15 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", - "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", "dev": true, "engines": { "node": ">=10" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, "node_modules/eslint-plugin-react/node_modules/doctrine": { @@ -88783,9 +88783,9 @@ } }, "eslint-plugin-react-hooks": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", - "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", "dev": true, "requires": {} }, diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 3e60c295e9d..ba6f262797e 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -293,7 +293,7 @@ "eslint-plugin-no-only-tests": "^2.4.0", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.22.0", - "eslint-plugin-react-hooks": "^4.2.0", + "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-testing-library": "^3.10.2", "eslint-plugin-theme-colors": "file:tools/eslint-plugin-theme-colors", "eslint-plugin-translation-vars": "file:tools/eslint-plugin-translation-vars", From 6557fb8132b24a4f110ac49056031cae21f589d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:22:52 -0700 Subject: [PATCH 35/39] build(deps): bump react-github-btn from 1.2.1 to 1.4.0 in /docs (#26613) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package.json | 2 +- docs/yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/package.json b/docs/package.json index 2884c0d204f..d38b639ff7e 100644 --- a/docs/package.json +++ b/docs/package.json @@ -39,7 +39,7 @@ "prism-react-renderer": "^1.2.1", "react": "^17.0.1", "react-dom": "^17.0.1", - "react-github-btn": "^1.2.0", + "react-github-btn": "^1.4.0", "stream": "^0.0.2", "swagger-ui-react": "^4.1.3", "url-loader": "^4.1.1" diff --git a/docs/yarn.lock b/docs/yarn.lock index 46648f60f97..95d11566639 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -6123,10 +6123,10 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -github-buttons@^2.8.0: - version "2.21.1" - resolved "https://registry.yarnpkg.com/github-buttons/-/github-buttons-2.21.1.tgz#9e55eb83b70c9149a21c235db2e971c53d4d98a2" - integrity sha512-n9bCQ8sj+5oX1YH5NeyWGbAclRDtHEhMBzqw2ctsWpdEHOwVgfruRu0VIVy01Ah10dd/iFajMHYU71L7IBWBOw== +github-buttons@^2.22.0: + version "2.27.0" + resolved "https://registry.yarnpkg.com/github-buttons/-/github-buttons-2.27.0.tgz#bbebea3d1c4f8c302b7d8432fd25a679242597e2" + integrity sha512-PmfRMI2Rttg/2jDfKBeSl621sEznrsKF019SuoLdoNlO7qRUZaOyEI5Li4uW+79pVqnDtKfIEVuHTIJ5lgy64w== github-slugger@^1.4.0: version "1.4.0" @@ -8993,12 +8993,12 @@ react-fast-compare@^3.2.0: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== -react-github-btn@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/react-github-btn/-/react-github-btn-1.2.1.tgz#ece93f609a4bad5e7eb9f47ae49bfaba69466dce" - integrity sha512-/gXD01mHAOhW0xYuNJFDn08OGjaMXOjcg6GCKVPdHvQcWzswH4aT85DLDAAJ6Zhw/71veSIH4Kx1BTBfy69SsA== +react-github-btn@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/react-github-btn/-/react-github-btn-1.4.0.tgz#92654107e92658e60dd977c7a92b212f806da78d" + integrity sha512-lV4FYClAfjWnBfv0iNlJUGhamDgIq6TayD0kPZED6VzHWdpcHmPfsYOZ/CFwLfPv4Zp+F4m8QKTj0oy2HjiGXg== dependencies: - github-buttons "^2.8.0" + github-buttons "^2.22.0" react-helmet-async@*: version "1.2.3" From 2961d69a82f2472808cb2de8697aef2b76ea4ab5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:30:50 -0700 Subject: [PATCH 36/39] build(deps): update react-table requirement from ^7.6.3 to ^7.8.0 in /superset-frontend/plugins/plugin-chart-table (#26522) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- superset-frontend/plugins/plugin-chart-table/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset-frontend/plugins/plugin-chart-table/package.json b/superset-frontend/plugins/plugin-chart-table/package.json index 74c1872d0f4..98a097a3c4e 100644 --- a/superset-frontend/plugins/plugin-chart-table/package.json +++ b/superset-frontend/plugins/plugin-chart-table/package.json @@ -33,7 +33,7 @@ "lodash": "^4.17.21", "match-sorter": "^6.3.0", "memoize-one": "^5.1.1", - "react-table": "^7.6.3", + "react-table": "^7.8.0", "regenerator-runtime": "^0.13.7", "xss": "^1.0.14" }, From 36608b503e0144bdfd63c84d72aab2a6af353560 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:31:17 -0700 Subject: [PATCH 37/39] build(deps-dev): bump @babel/register from 7.22.5 to 7.23.7 in /superset-frontend (#26556) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- superset-frontend/package-lock.json | 30 ++++++++++++++--------------- superset-frontend/package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index ea70d680b19..d896908d5c0 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -150,7 +150,7 @@ "@babel/plugin-transform-runtime": "^7.22.7", "@babel/preset-env": "^7.22.7", "@babel/preset-react": "^7.22.5", - "@babel/register": "^7.22.5", + "@babel/register": "^7.23.7", "@cypress/react": "^5.10.0", "@emotion/jest": "^11.3.0", "@hot-loader/react-dom": "^16.13.0", @@ -3795,14 +3795,14 @@ } }, "node_modules/@babel/register": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.22.5.tgz", - "integrity": "sha512-vV6pm/4CijSQ8Y47RH5SopXzursN35RQINfGJkmOlcpAtGuf94miFvIPhCKGQN7WGIcsgG1BHEX2KVdTYwTwUQ==", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", + "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", "dependencies": { "clone-deep": "^4.0.1", "find-cache-dir": "^2.0.0", "make-dir": "^2.1.0", - "pirates": "^4.0.5", + "pirates": "^4.0.6", "source-map-support": "^0.5.16" }, "engines": { @@ -49738,9 +49738,9 @@ } }, "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "engines": { "node": ">= 6" } @@ -66348,14 +66348,14 @@ } }, "@babel/register": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.22.5.tgz", - "integrity": "sha512-vV6pm/4CijSQ8Y47RH5SopXzursN35RQINfGJkmOlcpAtGuf94miFvIPhCKGQN7WGIcsgG1BHEX2KVdTYwTwUQ==", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", + "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", "requires": { "clone-deep": "^4.0.1", "find-cache-dir": "^2.0.0", "make-dir": "^2.1.0", - "pirates": "^4.0.5", + "pirates": "^4.0.6", "source-map-support": "^0.5.16" } }, @@ -102747,9 +102747,9 @@ } }, "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==" + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==" }, "pkg-dir": { "version": "3.0.0", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index ba6f262797e..f828b1736b9 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -216,7 +216,7 @@ "@babel/plugin-transform-runtime": "^7.22.7", "@babel/preset-env": "^7.22.7", "@babel/preset-react": "^7.22.5", - "@babel/register": "^7.22.5", + "@babel/register": "^7.23.7", "@cypress/react": "^5.10.0", "@emotion/jest": "^11.3.0", "@hot-loader/react-dom": "^16.13.0", From 2842b63cbe3005d92af6427bca1c52475f4f85ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:31:33 -0700 Subject: [PATCH 38/39] build(deps-dev): bump prettier-plugin-packagejson from 2.2.15 to 2.4.9 in /superset-frontend (#26570) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- superset-frontend/package-lock.json | 276 +++++++++++++++++++--------- superset-frontend/package.json | 2 +- 2 files changed, 192 insertions(+), 86 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index d896908d5c0..4b24957ec88 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -249,7 +249,7 @@ "mock-socket": "^9.0.3", "node-fetch": "^2.6.7", "prettier": "^2.4.1", - "prettier-plugin-packagejson": "^2.2.15", + "prettier-plugin-packagejson": "^2.4.9", "process": "^0.11.10", "react-resizable": "^3.0.5", "react-test-renderer": "^16.9.0", @@ -12240,6 +12240,18 @@ "node": ">=14" } }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.20", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.20.tgz", @@ -29446,12 +29458,12 @@ } }, "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12.20" } }, "node_modules/detect-newline": { @@ -32276,9 +32288,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.10", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.10.tgz", - "integrity": "sha512-s9nFhFnvR63wls6/kM88kQqDhMu0AfdjqouE2l5GVQPbqLgyFjjU5ry/r2yKsJxpb9Py1EYNqieFrmMaX4v++A==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -34240,9 +34252,9 @@ } }, "node_modules/git-hooks-list": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", - "integrity": "sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.1.0.tgz", + "integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==", "dev": true, "funding": { "url": "https://github.com/fisker/git-hooks-list?sponsor=1" @@ -50238,15 +50250,21 @@ } }, "node_modules/prettier-plugin-packagejson": { - "version": "2.2.15", - "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.2.15.tgz", - "integrity": "sha512-r3WKxw0ALyD3gr3RlIFK3o7mUejCVkqwVKtUuPQaB3+aNiZYKxmad+GpZ6WFWTm6Zq2jX0wvSdlkGccQ2pEnCg==", + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.4.9.tgz", + "integrity": "sha512-b3Q7agXVqxK3UpYEJr0xLD51SxriYXESWUCjmxOBUGqnPFZOg9jZGZ+Ptzq252I6OqzXN2rj1tJIFq6KOGLLJw==", "dev": true, "dependencies": { - "sort-package-json": "1.53.1" + "sort-package-json": "2.6.0", + "synckit": "0.9.0" }, "peerDependencies": { "prettier": ">= 1.16.0" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } } }, "node_modules/pretty-bytes": { @@ -55183,66 +55201,97 @@ "dev": true }, "node_modules/sort-package-json": { - "version": "1.53.1", - "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.53.1.tgz", - "integrity": "sha512-ltLORrQuuPMpy23YkWCA8fO7zBOxM4P1j9LcGxci4K2Fk8jmSyCA/ATU6CFyy8qR2HQRx4RBYWzoi78FU/Anuw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.6.0.tgz", + "integrity": "sha512-XSQ+lY9bAYA8ZsoChcEoPlgcSMaheziEp1beox1JVxy1SV4F2jSq9+h2rJ+3mC/Dhu9Ius1DLnInD5AWcsDXZw==", "dev": true, "dependencies": { - "detect-indent": "^6.0.0", - "detect-newline": "3.1.0", - "git-hooks-list": "1.0.3", - "globby": "10.0.0", - "is-plain-obj": "2.1.0", + "detect-indent": "^7.0.1", + "detect-newline": "^4.0.0", + "get-stdin": "^9.0.0", + "git-hooks-list": "^3.0.0", + "globby": "^13.1.2", + "is-plain-obj": "^4.1.0", "sort-object-keys": "^1.1.3" }, "bin": { "sort-package-json": "cli.js" } }, + "node_modules/sort-package-json/node_modules/detect-newline": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-package-json/node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/sort-package-json/node_modules/globby": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", - "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", "dev": true, "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/sort-package-json/node_modules/ignore": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", - "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" } }, "node_modules/sort-package-json/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/sort-package-json/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/source-list-map": { @@ -56508,6 +56557,28 @@ "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.15.tgz", "integrity": "sha512-k8uzYIkIVwmT+TcglpdN50pS2y1BDcUnBPK9iJeGu0Pl1lOI8pD6wtzgw91Pjpe+RxtTncw32tLxs/R0yNL2Mg==" }, + "node_modules/synckit": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.0.tgz", + "integrity": "sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/synckit/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/table": { "version": "6.7.3", "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", @@ -73032,6 +73103,12 @@ "dev": true, "optional": true }, + "@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true + }, "@polka/url": { "version": "1.0.0-next.20", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.20.tgz", @@ -87221,9 +87298,9 @@ } }, "detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", "dev": true }, "detect-newline": { @@ -89414,9 +89491,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.10", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.10.tgz", - "integrity": "sha512-s9nFhFnvR63wls6/kM88kQqDhMu0AfdjqouE2l5GVQPbqLgyFjjU5ry/r2yKsJxpb9Py1EYNqieFrmMaX4v++A==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -90924,9 +91001,9 @@ } }, "git-hooks-list": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", - "integrity": "sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.1.0.tgz", + "integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==", "dev": true }, "git-raw-commits": { @@ -103082,12 +103159,13 @@ } }, "prettier-plugin-packagejson": { - "version": "2.2.15", - "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.2.15.tgz", - "integrity": "sha512-r3WKxw0ALyD3gr3RlIFK3o7mUejCVkqwVKtUuPQaB3+aNiZYKxmad+GpZ6WFWTm6Zq2jX0wvSdlkGccQ2pEnCg==", + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.4.9.tgz", + "integrity": "sha512-b3Q7agXVqxK3UpYEJr0xLD51SxriYXESWUCjmxOBUGqnPFZOg9jZGZ+Ptzq252I6OqzXN2rj1tJIFq6KOGLLJw==", "dev": true, "requires": { - "sort-package-json": "1.53.1" + "sort-package-json": "2.6.0", + "synckit": "0.9.0" } }, "pretty-bytes": { @@ -106902,51 +106980,61 @@ "dev": true }, "sort-package-json": { - "version": "1.53.1", - "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.53.1.tgz", - "integrity": "sha512-ltLORrQuuPMpy23YkWCA8fO7zBOxM4P1j9LcGxci4K2Fk8jmSyCA/ATU6CFyy8qR2HQRx4RBYWzoi78FU/Anuw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.6.0.tgz", + "integrity": "sha512-XSQ+lY9bAYA8ZsoChcEoPlgcSMaheziEp1beox1JVxy1SV4F2jSq9+h2rJ+3mC/Dhu9Ius1DLnInD5AWcsDXZw==", "dev": true, "requires": { - "detect-indent": "^6.0.0", - "detect-newline": "3.1.0", - "git-hooks-list": "1.0.3", - "globby": "10.0.0", - "is-plain-obj": "2.1.0", + "detect-indent": "^7.0.1", + "detect-newline": "^4.0.0", + "get-stdin": "^9.0.0", + "git-hooks-list": "^3.0.0", + "globby": "^13.1.2", + "is-plain-obj": "^4.1.0", "sort-object-keys": "^1.1.3" }, "dependencies": { + "detect-newline": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "dev": true + }, + "get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true + }, "globby": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", - "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", "dev": true, "requires": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" } }, "ignore": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", - "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true }, "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true }, "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "dev": true } } @@ -107924,6 +108012,24 @@ "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.15.tgz", "integrity": "sha512-k8uzYIkIVwmT+TcglpdN50pS2y1BDcUnBPK9iJeGu0Pl1lOI8pD6wtzgw91Pjpe+RxtTncw32tLxs/R0yNL2Mg==" }, + "synckit": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.0.tgz", + "integrity": "sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==", + "dev": true, + "requires": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, "table": { "version": "6.7.3", "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index f828b1736b9..b12bd92986e 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -315,7 +315,7 @@ "mock-socket": "^9.0.3", "node-fetch": "^2.6.7", "prettier": "^2.4.1", - "prettier-plugin-packagejson": "^2.2.15", + "prettier-plugin-packagejson": "^2.4.9", "process": "^0.11.10", "react-resizable": "^3.0.5", "react-test-renderer": "^16.9.0", From 04445a34872267a55ec0ef526cdc061ee0ad3dd4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:45:34 -0700 Subject: [PATCH 39/39] build(deps-dev): bump webpack from 5.76.0 to 5.89.0 in /docs (#26717) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package.json | 2 +- docs/yarn.lock | 358 +++++++++++++++++++++++----------------------- 2 files changed, 178 insertions(+), 182 deletions(-) diff --git a/docs/package.json b/docs/package.json index d38b639ff7e..525ddea8669 100644 --- a/docs/package.json +++ b/docs/package.json @@ -49,7 +49,7 @@ "@tsconfig/docusaurus": "^2.0.2", "@types/react": "^17.0.42", "typescript": "^5.3.3", - "webpack": "^5.76.0" + "webpack": "^5.89.0" }, "browserslist": { "production": [ diff --git a/docs/yarn.lock b/docs/yarn.lock index 95d11566639..a627d40f3c3 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -3080,6 +3080,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" @@ -3093,11 +3098,24 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/source-map@^0.3.3": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" + integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + "@jridgewell/trace-mapping@^0.3.17": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" @@ -3106,6 +3124,14 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@jridgewell/trace-mapping@^0.3.20": + version "0.3.22" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c" + integrity sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@jridgewell/trace-mapping@^0.3.9": version "0.3.14" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" @@ -3500,10 +3526,10 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@*", "@types/estree@^1.0.0": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": version "4.17.28" @@ -3776,125 +3802,125 @@ dependencies: "@types/yargs-parser" "*" -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== +"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" + integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" + integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== +"@webassemblyjs/helper-wasm-section@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" + integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" + integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-opt" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" + "@webassemblyjs/wast-printer" "1.11.6" + +"@webassemblyjs/wasm-gen@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" + integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" + integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" + +"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" + integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" + integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== + dependencies: + "@webassemblyjs/ast" "1.11.6" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": @@ -3915,20 +3941,20 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== acorn-walk@^8.0.0: version "8.2.0" resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^8.0.4, acorn@^8.5.0, acorn@^8.7.1: - version "8.8.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" - integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== +acorn@^8.0.4, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.2: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== address@^1.0.1, address@^1.1.2: version "1.1.2" @@ -5506,10 +5532,10 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.10.0: - version "5.12.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" - integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== +enhanced-resolve@^5.15.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" + integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -5569,10 +5595,10 @@ es-abstract@^1.17.2, es-abstract@^1.19.1: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-module-lexer@^1.2.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5" + integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w== es-to-primitive@^1.2.1: version "1.2.1" @@ -9556,10 +9582,10 @@ schema-utils@^2.6.5: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== +schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== dependencies: "@types/json-schema" "^7.0.8" ajv "^6.12.5" @@ -10161,16 +10187,16 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.3: - version "5.3.7" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz#ef760632d24991760f339fe9290deb936ad1ffc7" - integrity sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw== +terser-webpack-plugin@^5.3.3, terser-webpack-plugin@^5.3.7: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== dependencies: - "@jridgewell/trace-mapping" "^0.3.17" + "@jridgewell/trace-mapping" "^0.3.20" jest-worker "^27.4.5" schema-utils "^3.1.1" serialize-javascript "^6.0.1" - terser "^5.16.5" + terser "^5.26.0" terser@^5.10.0, terser@^5.7.2: version "5.14.2" @@ -10182,13 +10208,13 @@ terser@^5.10.0, terser@^5.7.2: commander "^2.20.0" source-map-support "~0.5.20" -terser@^5.16.5: - version "5.16.6" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.6.tgz#f6c7a14a378ee0630fbe3ac8d1f41b4681109533" - integrity sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg== +terser@^5.26.0: + version "5.27.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.27.0.tgz#70108689d9ab25fef61c4e93e808e9fd092bf20c" + integrity sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A== dependencies: - "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" commander "^2.20.0" source-map-support "~0.5.20" @@ -10761,52 +10787,22 @@ webpack-sources@^3.2.2, webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.73.0: - version "5.76.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.1.tgz#7773de017e988bccb0f13c7d75ec245f377d295c" - integrity sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.4.0" - webpack-sources "^3.2.3" - -webpack@^5.76.0: - version "5.76.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c" - integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA== +webpack@^5.73.0, webpack@^5.89.0: + version "5.89.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.89.0.tgz#56b8bf9a34356e93a6625770006490bf3a7f32dc" + integrity sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@types/estree" "^1.0.0" + "@webassemblyjs/ast" "^1.11.5" + "@webassemblyjs/wasm-edit" "^1.11.5" + "@webassemblyjs/wasm-parser" "^1.11.5" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" + acorn-import-assertions "^1.9.0" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" + enhanced-resolve "^5.15.0" + es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" @@ -10815,9 +10811,9 @@ webpack@^5.76.0: loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.1.0" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" + terser-webpack-plugin "^5.3.7" watchpack "^2.4.0" webpack-sources "^3.2.3"