This is an automated email from the ASF dual-hosted git repository. diegopucci pushed a commit to branch geido/feat/disable-creatable-filter-value in repository https://gitbox.apache.org/repos/asf/superset.git
commit f321f7af5166f7f2617e6673a86911afabe7ea98 Author: Diego Pucci <[email protected]> AuthorDate: Tue Apr 8 16:39:04 2025 +0300 feat(Native Filters): Configure creatable filter behavior --- .../cypress/e2e/dashboard/shared_dashboard_functions.ts | 1 + superset-frontend/cypress-base/cypress/support/e2e.ts | 2 +- superset-frontend/spec/fixtures/mockNativeFilters.ts | 3 +++ .../FiltersConfigForm/FiltersConfigForm.tsx | 1 + .../components/Select/SelectFilterPlugin.stories.tsx | 4 ++++ .../filters/components/Select/SelectFilterPlugin.test.tsx | 13 +++++++++++++ .../src/filters/components/Select/SelectFilterPlugin.tsx | 3 ++- .../src/filters/components/Select/buildQuery.test.ts | 1 + .../src/filters/components/Select/controlPanel.ts | 14 ++++++++++++++ superset-frontend/src/filters/components/Select/types.ts | 2 ++ 10 files changed, 42 insertions(+), 2 deletions(-) diff --git a/superset-frontend/cypress-base/cypress/e2e/dashboard/shared_dashboard_functions.ts b/superset-frontend/cypress-base/cypress/e2e/dashboard/shared_dashboard_functions.ts index b0f7853e94..595bf45da0 100644 --- a/superset-frontend/cypress-base/cypress/e2e/dashboard/shared_dashboard_functions.ts +++ b/superset-frontend/cypress-base/cypress/e2e/dashboard/shared_dashboard_functions.ts @@ -55,6 +55,7 @@ export function prepareDashboardFilters( controlValues: { enableEmptyFilter: false, defaultToFirstItem: false, + creatable: true, multiSelect: true, searchAllOptions: false, inverseSelection: false, diff --git a/superset-frontend/cypress-base/cypress/support/e2e.ts b/superset-frontend/cypress-base/cypress/support/e2e.ts index 18572b6ab2..17ac14c7e6 100644 --- a/superset-frontend/cypress-base/cypress/support/e2e.ts +++ b/superset-frontend/cypress-base/cypress/support/e2e.ts @@ -166,7 +166,7 @@ Cypress.Commands.add('login', () => { cy.request({ method: 'POST', url: '/login/', - body: { username: 'admin', password: 'general' }, + body: { username: 'admin', password: 'admin' }, }).then(response => { if (response.status === 302) { // If there's a redirect, follow it manually diff --git a/superset-frontend/spec/fixtures/mockNativeFilters.ts b/superset-frontend/spec/fixtures/mockNativeFilters.ts index b83cdcc8dc..414935c8b3 100644 --- a/superset-frontend/spec/fixtures/mockNativeFilters.ts +++ b/superset-frontend/spec/fixtures/mockNativeFilters.ts @@ -48,6 +48,7 @@ export const nativeFilters: NativeFiltersState = { excluded: [], }, controlValues: { + creatable: false, multiSelect: false, enableEmptyFilter: false, inverseSelection: false, @@ -79,6 +80,7 @@ export const nativeFilters: NativeFiltersState = { excluded: [], }, controlValues: { + creatable: false, multiSelect: false, enableEmptyFilter: false, inverseSelection: false, @@ -463,6 +465,7 @@ export const buildNativeFilter = ( ) => ({ id, controlValues: { + creatable: true, multiSelect: true, enableEmptyFilter: false, defaultToFirstItem: false, 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 7ef4e6bacb..01effc9aa1 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx @@ -136,6 +136,7 @@ type ControlKey = keyof PluginFilterSelectCustomizeProps; const controlsOrder: ControlKey[] = [ 'enableEmptyFilter', 'defaultToFirstItem', + 'creatable', 'multiSelect', 'searchAllOptions', 'inverseSelection', diff --git a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.stories.tsx b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.stories.tsx index 55808ad6ad..46e056b5ff 100644 --- a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.stories.tsx +++ b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.stories.tsx @@ -29,17 +29,20 @@ getChartTransformPropsRegistry().registerValue('filter_select', transformProps); export default { title: 'Filter Plugins', argTypes: { + creatable: { control: 'boolean', defaultValue: true }, multiSelect: { control: 'boolean', defaultValue: true }, inverseSelection: { control: 'boolean', defaultValue: false }, }, }; export const Select = ({ + creatable, multiSeelct, inverseSelection, width, height, }: { + creatable: boolean; multiSeelct: boolean; inverseSelection: boolean; width: number; @@ -53,6 +56,7 @@ export const Select = ({ formData={{ adhoc_filters: [], extra_filters: [], + creatable, multiSelect: { multiSeelct }, inverseSelection: { inverseSelection }, row_limit: 1000, diff --git a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.test.tsx b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.test.tsx index 8b88ebba69..ec6b33d95b 100644 --- a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.test.tsx +++ b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.test.tsx @@ -27,6 +27,7 @@ jest.useFakeTimers(); const selectMultipleProps = { formData: { sortAscending: true, + creatable: false, multiSelect: true, enableEmptyFilter: true, defaultToFirstItem: false, @@ -259,4 +260,16 @@ describe('SelectFilterPlugin', () => { await userEvent.type(screen.getByRole('combobox'), '1'); expect(screen.queryByLabelText(String(bigValue))).toBeInTheDocument(); }); + + test('Should not allow for new values when creatable is false', () => { + getWrapper({ creatable: false }); + userEvent.type(screen.getByRole('combobox'), 'new value'); + expect(screen.queryByTitle('new value')).not.toBeInTheDocument(); + }); + + test('Should allow for new values when creatable is false', async () => { + getWrapper({ creatable: true }); + userEvent.type(screen.getByRole('combobox'), 'new value'); + expect(await screen.findByTitle('new value')).toBeInTheDocument(); + }); }); diff --git a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx index 23447fb295..ca8fbda8df 100644 --- a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx +++ b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx @@ -100,6 +100,7 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) { } = props; const { enableEmptyFilter, + creatable, multiSelect, showSearch, inverseSelection, @@ -296,7 +297,7 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) { <Select name={formData.nativeFilterId} allowClear - allowNewOptions={!searchAllOptions} + allowNewOptions={!searchAllOptions && creatable !== false} allowSelectAll={!searchAllOptions} // @ts-ignore value={filterState.value || []} diff --git a/superset-frontend/src/filters/components/Select/buildQuery.test.ts b/superset-frontend/src/filters/components/Select/buildQuery.test.ts index 151b4dbd8c..3f7fc0da5c 100644 --- a/superset-frontend/src/filters/components/Select/buildQuery.test.ts +++ b/superset-frontend/src/filters/components/Select/buildQuery.test.ts @@ -30,6 +30,7 @@ describe('Select buildQuery', () => { filters: undefined, enableEmptyFilter: false, inverseSelection: false, + creatable: false, multiSelect: false, defaultToFirstItem: false, searchAllOptions: false, diff --git a/superset-frontend/src/filters/components/Select/controlPanel.ts b/superset-frontend/src/filters/components/Select/controlPanel.ts index be01821760..a43e3bd2ae 100644 --- a/superset-frontend/src/filters/components/Select/controlPanel.ts +++ b/superset-frontend/src/filters/components/Select/controlPanel.ts @@ -27,6 +27,7 @@ const { enableEmptyFilter, inverseSelection, multiSelect, + creatable, defaultToFirstItem, searchAllOptions, sortAscending, @@ -66,6 +67,19 @@ const config: ControlPanelConfig = { }, }, ], + [ + { + name: 'creatable', + config: { + type: 'CheckboxControl', + label: t('Allow creation of new values'), + default: creatable, + resetConfig: true, + affectsDataMask: true, + renderTrigger: true, + }, + }, + ], [ { name: 'multiSelect', diff --git a/superset-frontend/src/filters/components/Select/types.ts b/superset-frontend/src/filters/components/Select/types.ts index e608f59640..896bcf16cc 100644 --- a/superset-frontend/src/filters/components/Select/types.ts +++ b/superset-frontend/src/filters/components/Select/types.ts @@ -36,6 +36,7 @@ export interface PluginFilterSelectCustomizeProps { defaultValue?: SelectValue; enableEmptyFilter: boolean; inverseSelection: boolean; + creatable: boolean; multiSelect: boolean; defaultToFirstItem: boolean; searchAllOptions: boolean; @@ -71,6 +72,7 @@ export const DEFAULT_FORM_DATA: PluginFilterSelectCustomizeProps = { enableEmptyFilter: false, inverseSelection: false, defaultToFirstItem: false, + creatable: true, multiSelect: true, searchAllOptions: false, sortAscending: true,
