diff --git a/superset-frontend/spec/fixtures/mockNativeFilters.ts b/superset-frontend/spec/fixtures/mockNativeFilters.ts index e087072bfa7..6da3a3561df 100644 --- a/superset-frontend/spec/fixtures/mockNativeFilters.ts +++ b/superset-frontend/spec/fixtures/mockNativeFilters.ts @@ -17,6 +17,7 @@ * under the License. */ import { ExtraFormData } from '@superset-ui/core'; +import { NativeFilterType } from 'src/dashboard/components/nativeFilters/types'; import { NativeFiltersState } from 'src/dashboard/reducers/types'; import { DataMaskStateWithId } from '../../src/dataMask/types'; @@ -50,6 +51,7 @@ export const nativeFilters: NativeFiltersState = { enableEmptyFilter: false, inverseSelection: false, }, + type: NativeFilterType.NATIVE_FILTER, }, 'NATIVE_FILTER-x9QPw0so1': { id: 'NATIVE_FILTER-x9QPw0so1', @@ -78,6 +80,7 @@ export const nativeFilters: NativeFiltersState = { enableEmptyFilter: false, inverseSelection: false, }, + type: NativeFilterType.NATIVE_FILTER, }, }, }; diff --git a/superset-frontend/spec/javascripts/dashboard/fixtures/mockNativeFilters.ts b/superset-frontend/spec/javascripts/dashboard/fixtures/mockNativeFilters.ts index 0bf022d55fe..1a309fdfc1a 100644 --- a/superset-frontend/spec/javascripts/dashboard/fixtures/mockNativeFilters.ts +++ b/superset-frontend/spec/javascripts/dashboard/fixtures/mockNativeFilters.ts @@ -16,8 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -import { DataMaskStateWithId } from 'src/dataMask/types'; +import { NativeFilterType } from 'src/dashboard/components/nativeFilters/types'; import { NativeFiltersState } from 'src/dashboard/reducers/types'; +import { DataMaskStateWithId } from 'src/dataMask/types'; export const mockDataMaskInfo: DataMaskStateWithId = { DefaultsID: { @@ -66,6 +67,7 @@ export const nativeFiltersInfo: NativeFiltersState = { allowsMultipleValues: true, isRequired: false, }, + type: NativeFilterType.NATIVE_FILTER, }, }, }; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx index e46d581a16a..210739b0a0e 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx @@ -80,7 +80,7 @@ import { } from './utils'; import { useBackendFormUpdate, useDefaultValue } from './state'; import { getFormData } from '../../utils'; -import { Filter } from '../../types'; +import { Filter, NativeFilterType } from '../../types'; import getControlItemsMap from './getControlItemsMap'; import FilterScope from './FilterScope/FilterScope'; import RemovedFilter from './RemovedFilter'; @@ -684,6 +684,13 @@ const FiltersConfigForm = ( forceRender > + {t('Filter name')}} diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx index f2f62983f36..53772cc17d1 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/getControlItemsMap.test.tsx @@ -16,13 +16,16 @@ * specific language governing permissions and limitations * under the License. */ +import userEvent from '@testing-library/user-event'; import React from 'react'; import { render, screen } from 'spec/helpers/testing-library'; -import userEvent from '@testing-library/user-event'; -import { Filter } from 'src/dashboard/components/nativeFilters/types'; import { FormInstance } from 'src/common/components'; -import { getControlItems, setNativeFilterFieldValues } from './utils'; +import { + Filter, + NativeFilterType, +} from 'src/dashboard/components/nativeFilters/types'; import getControlItemsMap, { ControlItemsProps } from './getControlItemsMap'; +import { getControlItems, setNativeFilterFieldValues } from './utils'; jest.mock('./utils', () => ({ getControlItems: jest.fn(), @@ -60,6 +63,7 @@ const filterMock: Filter = { filterType: '', targets: [{}], controlValues: {}, + type: NativeFilterType.NATIVE_FILTER, }; const createProps: () => ControlItemsProps = () => ({ diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts index dd211aceed7..2dba43e93fa 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts @@ -17,7 +17,7 @@ * under the License. */ import { AdhocFilter, DataMask } from '@superset-ui/core'; -import { Scope } from '../types'; +import { NativeFilterType, Scope } from '../types'; export interface NativeFiltersFormItem { scope: Scope; @@ -44,6 +44,7 @@ export interface NativeFiltersFormItem { adhoc_filters?: AdhocFilter[]; time_range?: string; granularity_sqla?: string; + type: NativeFilterType; } export interface NativeFiltersForm { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts index c2307e4b453..de990349b17 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts @@ -140,6 +140,7 @@ export const createHandleSave = ( : [], scope: formInputs.scope, sortMetric: formInputs.sortMetric, + type: formInputs.type, }; }); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/types.ts index 3792d3e82be..62833989ccd 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/types.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/types.ts @@ -59,6 +59,12 @@ export interface Filter { requiredFirst?: boolean; tabsInScope?: string[]; chartsInScope?: number[]; + type: NativeFilterType; } export type FilterConfiguration = Filter[]; + +export enum NativeFilterType { + NATIVE_FILTER = 'NATIVE_FILTER', + SECTION = 'SECTION', +} diff --git a/superset-frontend/src/dashboard/components/nativeFilters/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/utils.ts index 5dc81fd160a..60925c79bac 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/utils.ts @@ -47,6 +47,7 @@ export const getFormData = ({ adhoc_filters, time_range, granularity_sqla, + type, }: Partial & { datasetId?: number; inputRef?: RefObject; @@ -86,6 +87,7 @@ export const getFormData = ({ inView: true, viz_type: filterType, inputRef, + type, }; }; diff --git a/superset/migrations/versions/021b81fe4fbb_add_type_to_native_filter_configuration.py b/superset/migrations/versions/021b81fe4fbb_add_type_to_native_filter_configuration.py new file mode 100644 index 00000000000..8238e8f6391 --- /dev/null +++ b/superset/migrations/versions/021b81fe4fbb_add_type_to_native_filter_configuration.py @@ -0,0 +1,121 @@ +# 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. +"""Add type to native filter configuration + +Revision ID: 021b81fe4fbb +Revises: 07071313dd52 +Create Date: 2021-08-31 11:37:40.604081 + +""" + +# revision identifiers, used by Alembic. +revision = "021b81fe4fbb" +down_revision = "07071313dd52" + +import json +import logging + +import sqlalchemy as sa +from alembic import op +from sqlalchemy.ext.declarative.api import declarative_base + +from superset import db + +Base = declarative_base() + +logger = logging.getLogger("alembic") + + +class Dashboard(Base): + __tablename__ = "dashboards" + id = sa.Column(sa.Integer, primary_key=True) + json_metadata = sa.Column(sa.Text) + + +def upgrade(): + logger.info("[AddTypeToNativeFilter] Starting upgrade") + bind = op.get_bind() + session = db.Session(bind=bind) + + for dashboard in session.query(Dashboard).all(): + logger.info("[AddTypeToNativeFilter] Updating Dashboard ", dashboard.id) + + if not dashboard.json_metadata: + logger.info( + "[AddTypeToNativeFilter] Skipping Dashboard json_metadata is %s", + dashboard.id, + dashboard.json_metadata, + ) + continue + try: + json_meta = json.loads(dashboard.json_metadata) + except: + logger.exception("[AddTypeToNativeFilter] Error loading json_metadata") + continue + + if "native_filter_configuration" not in json_meta: + logger.info( + "[AddTypeToNativeFilter] Skipping Dashboard." + " native_filter_configuration not found.", + dashboard.id, + ) + continue + + for native_filter in json_meta["native_filter_configuration"]: + native_filter["type"] = "NATIVE_FILTER" + dashboard.json_metadata = json.dumps(json_meta) + + session.commit() + session.close() + logger.info("[AddTypeToNativeFilter] Done!") + + +def downgrade(): + logger.info("[RemoveTypeToNativeFilter] Starting downgrade") + bind = op.get_bind() + session = db.Session(bind=bind) + + for dashboard in session.query(Dashboard).all(): + logger.info( + "[RemoveTypeToNativeFilter] Updating Dashobard", dashboard.id, + ) + if not dashboard.json_metadata: + logger.info( + "[RemoveTypeToNativeFilter] Skipping Dashboard json_metadata is %s", + dashboard.id, + dashboard.json_metadata, + ) + continue + try: + json_meta = json.loads(dashboard.json_metadata) + except: + logger.exception("[RemoveTypeToNativeFilter] Error loading json_metadata") + continue + + if "native_filter_configuration" not in json_meta: + logger.info( + "[RemoveTypeToNativeFilter] Skipping Dashboard." + " native_filter_configuration not found.", + dashboard.id, + ) + continue + for native_filter in json_meta["native_filter_configuration"]: + native_filter.pop("type", None) + dashboard.json_metadata = json.dumps(json_meta) + session.commit() + session.close() + logger.info("[RemoveTypeToNativeFilter] Done!")