mirror of
https://github.com/apache/superset.git
synced 2024-09-06 13:57:40 -04:00
feat(native-filters): Auto apply changes in FiltersConfigModal (#14461)
* fix:fix get permission function * feat: auto apply changes after save filters config modal * fix: repopulate default values * test: fix tests * test: fix tests * fix: fix CR notes * fix: fix CR notes
This commit is contained in:
parent
680c96ec54
commit
e8e838e279
@ -74,6 +74,7 @@ export const setFilterConfiguration = (
|
|||||||
filterConfig,
|
filterConfig,
|
||||||
});
|
});
|
||||||
const { id, metadata } = getState().dashboardInfo;
|
const { id, metadata } = getState().dashboardInfo;
|
||||||
|
const oldFilters = getState().nativeFilters?.filters;
|
||||||
|
|
||||||
// TODO extract this out when makeApi supports url parameters
|
// TODO extract this out when makeApi supports url parameters
|
||||||
const updateDashboard = makeApi<
|
const updateDashboard = makeApi<
|
||||||
@ -100,7 +101,7 @@ export const setFilterConfiguration = (
|
|||||||
type: SET_FILTER_CONFIG_COMPLETE,
|
type: SET_FILTER_CONFIG_COMPLETE,
|
||||||
filterConfig,
|
filterConfig,
|
||||||
});
|
});
|
||||||
dispatch(setDataMaskForFilterConfigComplete(filterConfig));
|
dispatch(setDataMaskForFilterConfigComplete(filterConfig, oldFilters));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
dispatch({ type: SET_FILTER_CONFIG_FAIL, filterConfig });
|
dispatch({ type: SET_FILTER_CONFIG_FAIL, filterConfig });
|
||||||
dispatch({ type: SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL, filterConfig });
|
dispatch({ type: SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL, filterConfig });
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen, cleanup } from 'spec/helpers/testing-library';
|
import { render, screen } from 'spec/helpers/testing-library';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import {
|
import {
|
||||||
@ -71,7 +71,7 @@ const getDateControlTestId = testWithId<string>(
|
|||||||
const FILTER_NAME = 'Time filter 1';
|
const FILTER_NAME = 'Time filter 1';
|
||||||
const FILTER_SET_NAME = 'New filter set';
|
const FILTER_SET_NAME = 'New filter set';
|
||||||
|
|
||||||
const addFilterFlow = () => {
|
const addFilterFlow = async () => {
|
||||||
// open filter config modal
|
// open filter config modal
|
||||||
userEvent.click(screen.getByTestId(getTestId('collapsable')));
|
userEvent.click(screen.getByTestId(getTestId('collapsable')));
|
||||||
userEvent.click(screen.getByTestId(getTestId('create-filter')));
|
userEvent.click(screen.getByTestId(getTestId('create-filter')));
|
||||||
@ -80,6 +80,7 @@ const addFilterFlow = () => {
|
|||||||
userEvent.click(screen.getByText('Time filter'));
|
userEvent.click(screen.getByText('Time filter'));
|
||||||
userEvent.type(screen.getByTestId(getModalTestId('name-input')), FILTER_NAME);
|
userEvent.type(screen.getByTestId(getModalTestId('name-input')), FILTER_NAME);
|
||||||
userEvent.click(screen.getByText('Save'));
|
userEvent.click(screen.getByText('Save'));
|
||||||
|
await screen.findByText('All Filters (1)');
|
||||||
};
|
};
|
||||||
|
|
||||||
const addFilterSetFlow = async () => {
|
const addFilterSetFlow = async () => {
|
||||||
@ -175,7 +176,7 @@ describe('FilterBar', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
toggleFiltersBar.mockClear();
|
jest.clearAllMocks();
|
||||||
fetchMock.get(
|
fetchMock.get(
|
||||||
'http://localhost/api/v1/time_range/?q=%27Last%20day%27',
|
'http://localhost/api/v1/time_range/?q=%27Last%20day%27',
|
||||||
{
|
{
|
||||||
@ -203,11 +204,6 @@ describe('FilterBar', () => {
|
|||||||
mockCore.makeApi = jest.fn(() => mockApi);
|
mockCore.makeApi = jest.fn(() => mockApi);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
cleanup();
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
const renderWrapper = (props = closedBarProps, state?: object) =>
|
const renderWrapper = (props = closedBarProps, state?: object) =>
|
||||||
render(
|
render(
|
||||||
<Provider store={state ? getMockStore(state) : mockStore}>
|
<Provider store={state ? getMockStore(state) : mockStore}>
|
||||||
@ -306,14 +302,12 @@ describe('FilterBar', () => {
|
|||||||
renderWrapper(openedBarProps, stateWithoutNativeFilters);
|
renderWrapper(openedBarProps, stateWithoutNativeFilters);
|
||||||
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled();
|
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled();
|
||||||
|
|
||||||
addFilterFlow();
|
await addFilterFlow();
|
||||||
|
|
||||||
await screen.findByText('All Filters (1)');
|
|
||||||
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled();
|
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled();
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: fix flakiness and re-enable
|
it('add and apply filter set', async () => {
|
||||||
it.skip('add and apply filter set', async () => {
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
global.featureFlags = {
|
global.featureFlags = {
|
||||||
[FeatureFlag.DASHBOARD_NATIVE_FILTERS]: true,
|
[FeatureFlag.DASHBOARD_NATIVE_FILTERS]: true,
|
||||||
@ -321,22 +315,17 @@ describe('FilterBar', () => {
|
|||||||
};
|
};
|
||||||
renderWrapper(openedBarProps, stateWithoutNativeFilters);
|
renderWrapper(openedBarProps, stateWithoutNativeFilters);
|
||||||
|
|
||||||
addFilterFlow();
|
await addFilterFlow();
|
||||||
|
|
||||||
await screen.findByText('All Filters (1)');
|
|
||||||
|
|
||||||
await addFilterSetFlow();
|
await addFilterSetFlow();
|
||||||
|
|
||||||
// change filter
|
// change filter
|
||||||
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled();
|
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled();
|
||||||
|
userEvent.click(await screen.findByText('All Filters (1)'));
|
||||||
await changeFilterValue();
|
await changeFilterValue();
|
||||||
await waitFor(() => expect(screen.getAllByText('Last day').length).toBe(2));
|
await waitFor(() => expect(screen.getAllByText('Last day').length).toBe(2));
|
||||||
|
|
||||||
// apply new filter value
|
// apply new filter value
|
||||||
await waitFor(() =>
|
|
||||||
expect(screen.getByTestId(getTestId('apply-button'))).toBeEnabled(),
|
|
||||||
);
|
|
||||||
userEvent.click(screen.getByTestId(getTestId('apply-button')));
|
userEvent.click(screen.getByTestId(getTestId('apply-button')));
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled(),
|
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled(),
|
||||||
@ -352,12 +341,11 @@ describe('FilterBar', () => {
|
|||||||
).not.toHaveAttribute('data-selected', 'true');
|
).not.toHaveAttribute('data-selected', 'true');
|
||||||
userEvent.click(screen.getByTestId(getTestId('filter-set-wrapper')));
|
userEvent.click(screen.getByTestId(getTestId('filter-set-wrapper')));
|
||||||
expect(await screen.findByText('Last week')).toBeInTheDocument();
|
expect(await screen.findByText('Last week')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId(getTestId('apply-button'))).toBeEnabled();
|
|
||||||
userEvent.click(screen.getByTestId(getTestId('apply-button')));
|
userEvent.click(screen.getByTestId(getTestId('apply-button')));
|
||||||
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled();
|
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('add and edit filter set', async () => {
|
it('add and edit filter set', async () => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
global.featureFlags = {
|
global.featureFlags = {
|
||||||
[FeatureFlag.DASHBOARD_NATIVE_FILTERS_SET]: true,
|
[FeatureFlag.DASHBOARD_NATIVE_FILTERS_SET]: true,
|
||||||
@ -365,9 +353,7 @@ describe('FilterBar', () => {
|
|||||||
};
|
};
|
||||||
renderWrapper(openedBarProps, stateWithoutNativeFilters);
|
renderWrapper(openedBarProps, stateWithoutNativeFilters);
|
||||||
|
|
||||||
addFilterFlow();
|
await addFilterFlow();
|
||||||
|
|
||||||
await screen.findByText('All Filters (1)');
|
|
||||||
|
|
||||||
await addFilterSetFlow();
|
await addFilterSetFlow();
|
||||||
|
|
||||||
@ -375,12 +361,13 @@ describe('FilterBar', () => {
|
|||||||
userEvent.click(screen.getByText('Edit'));
|
userEvent.click(screen.getByText('Edit'));
|
||||||
|
|
||||||
await changeFilterValue();
|
await changeFilterValue();
|
||||||
await waitFor(() => expect(screen.getAllByText('Last day').length).toBe(1));
|
|
||||||
|
|
||||||
// apply new changes and save them
|
// apply new changes and save them
|
||||||
expect(
|
await waitFor(() =>
|
||||||
screen.getByTestId(getTestId('filter-set-edit-save')),
|
expect(
|
||||||
).toBeDisabled();
|
screen.getByTestId(getTestId('filter-set-edit-save')),
|
||||||
|
).toBeDisabled(),
|
||||||
|
);
|
||||||
expect(screen.getByTestId(getTestId('apply-button'))).toBeEnabled();
|
expect(screen.getByTestId(getTestId('apply-button'))).toBeEnabled();
|
||||||
userEvent.click(screen.getByTestId(getTestId('apply-button')));
|
userEvent.click(screen.getByTestId(getTestId('apply-button')));
|
||||||
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled();
|
expect(screen.getByTestId(getTestId('apply-button'))).toBeDisabled();
|
||||||
|
@ -23,13 +23,15 @@ import {
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { Checkbox } from 'src/common/components';
|
import { Checkbox } from 'src/common/components';
|
||||||
import { FormInstance } from 'antd/lib/form';
|
import { FormInstance } from 'antd/lib/form';
|
||||||
import { getChartControlPanelRegistry } from '@superset-ui/core';
|
import { getChartControlPanelRegistry, t } from '@superset-ui/core';
|
||||||
|
import { Tooltip } from 'src/components/Tooltip';
|
||||||
import { getControlItems, setNativeFilterFieldValues } from './utils';
|
import { getControlItems, setNativeFilterFieldValues } from './utils';
|
||||||
import { NativeFiltersForm, NativeFiltersFormItem } from '../types';
|
import { NativeFiltersForm, NativeFiltersFormItem } from '../types';
|
||||||
import { StyledCheckboxFormItem } from './FiltersConfigForm';
|
import { StyledCheckboxFormItem } from './FiltersConfigForm';
|
||||||
import { Filter } from '../../types';
|
import { Filter } from '../../types';
|
||||||
|
|
||||||
type ControlItemsProps = {
|
type ControlItemsProps = {
|
||||||
|
disabled: boolean;
|
||||||
filterId: string;
|
filterId: string;
|
||||||
forceUpdate: Function;
|
forceUpdate: Function;
|
||||||
filterToEdit?: Filter;
|
filterToEdit?: Filter;
|
||||||
@ -38,6 +40,7 @@ type ControlItemsProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ControlItems: FC<ControlItemsProps> = ({
|
const ControlItems: FC<ControlItemsProps> = ({
|
||||||
|
disabled,
|
||||||
forceUpdate,
|
forceUpdate,
|
||||||
form,
|
form,
|
||||||
filterId,
|
filterId,
|
||||||
@ -59,38 +62,48 @@ const ControlItems: FC<ControlItemsProps> = ({
|
|||||||
controlItem?.config?.renderTrigger,
|
controlItem?.config?.renderTrigger,
|
||||||
)
|
)
|
||||||
.map(controlItem => (
|
.map(controlItem => (
|
||||||
<StyledCheckboxFormItem
|
<Tooltip
|
||||||
key={controlItem.name}
|
placement="left"
|
||||||
name={['filters', filterId, 'controlValues', controlItem.name]}
|
title={
|
||||||
initialValue={
|
controlItem.config.affectsDataMask &&
|
||||||
filterToEdit?.controlValues?.[controlItem.name] ??
|
disabled &&
|
||||||
controlItem?.config?.default
|
t('Populate "Default value" to enable this control')
|
||||||
}
|
}
|
||||||
valuePropName="checked"
|
|
||||||
colon={false}
|
|
||||||
>
|
>
|
||||||
<Checkbox
|
<StyledCheckboxFormItem
|
||||||
onChange={() => {
|
key={controlItem.name}
|
||||||
if (!controlItem.config.resetConfig) {
|
name={['filters', filterId, 'controlValues', controlItem.name]}
|
||||||
forceUpdate();
|
initialValue={
|
||||||
return;
|
filterToEdit?.controlValues?.[controlItem.name] ??
|
||||||
}
|
controlItem?.config?.default
|
||||||
setNativeFilterFieldValues(form, filterId, {
|
}
|
||||||
defaultDataMask: null,
|
valuePropName="checked"
|
||||||
});
|
colon={false}
|
||||||
forceUpdate();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{controlItem.config.label}{' '}
|
<Checkbox
|
||||||
{controlItem.config.description && (
|
disabled={controlItem.config.affectsDataMask && disabled}
|
||||||
<InfoTooltipWithTrigger
|
onChange={() => {
|
||||||
placement="top"
|
if (!controlItem.config.resetConfig) {
|
||||||
label={controlItem.config.name}
|
forceUpdate();
|
||||||
tooltip={controlItem.config.description}
|
return;
|
||||||
/>
|
}
|
||||||
)}
|
setNativeFilterFieldValues(form, filterId, {
|
||||||
</Checkbox>
|
defaultDataMask: null,
|
||||||
</StyledCheckboxFormItem>
|
});
|
||||||
|
forceUpdate();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{controlItem.config.label}{' '}
|
||||||
|
{controlItem.config.description && (
|
||||||
|
<InfoTooltipWithTrigger
|
||||||
|
placement="top"
|
||||||
|
label={controlItem.config.name}
|
||||||
|
tooltip={controlItem.config.description}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Checkbox>
|
||||||
|
</StyledCheckboxFormItem>
|
||||||
|
</Tooltip>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -260,6 +260,8 @@ export const FiltersConfigForm: React.FC<FiltersConfigFormProps> = ({
|
|||||||
label: filter.title,
|
label: filter.title,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const showDefaultValue = !hasDataset || (!isDataDirty && hasFilledDataset);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Typography.Title level={5}>{t('Settings')}</Typography.Title>
|
<Typography.Title level={5}>{t('Settings')}</Typography.Title>
|
||||||
@ -434,7 +436,7 @@ export const FiltersConfigForm: React.FC<FiltersConfigFormProps> = ({
|
|||||||
data-test="default-input"
|
data-test="default-input"
|
||||||
label={<StyledLabel>{t('Default Value')}</StyledLabel>}
|
label={<StyledLabel>{t('Default Value')}</StyledLabel>}
|
||||||
>
|
>
|
||||||
{(!hasDataset || (!isDataDirty && hasFilledDataset)) && (
|
{showDefaultValue ? (
|
||||||
<DefaultValue
|
<DefaultValue
|
||||||
setDataMask={dataMask => {
|
setDataMask={dataMask => {
|
||||||
setNativeFilterFieldValues(form, filterId, {
|
setNativeFilterFieldValues(form, filterId, {
|
||||||
@ -447,6 +449,10 @@ export const FiltersConfigForm: React.FC<FiltersConfigFormProps> = ({
|
|||||||
form={form}
|
form={form}
|
||||||
formData={newFormData}
|
formData={newFormData}
|
||||||
/>
|
/>
|
||||||
|
) : hasFilledDataset ? (
|
||||||
|
t('Click "Populate" to get "Default Value" ->')
|
||||||
|
) : (
|
||||||
|
t('Fill all required fields to enable "Default Value"')
|
||||||
)}
|
)}
|
||||||
</StyledFormItem>
|
</StyledFormItem>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
@ -461,6 +467,7 @@ export const FiltersConfigForm: React.FC<FiltersConfigFormProps> = ({
|
|||||||
</Checkbox>
|
</Checkbox>
|
||||||
</StyledCheckboxFormItem>
|
</StyledCheckboxFormItem>
|
||||||
<ControlItems
|
<ControlItems
|
||||||
|
disabled={!showDefaultValue}
|
||||||
filterToEdit={filterToEdit}
|
filterToEdit={filterToEdit}
|
||||||
formFilter={formFilter}
|
formFilter={formFilter}
|
||||||
filterId={filterId}
|
filterId={filterId}
|
||||||
|
@ -42,13 +42,20 @@ export const validateForm = async (
|
|||||||
errors: [error],
|
errors: [error],
|
||||||
};
|
};
|
||||||
form.setFields([fieldError]);
|
form.setFields([fieldError]);
|
||||||
// eslint-disable-next-line no-throw-literal
|
|
||||||
throw { errorFields: [fieldError] };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const formValues = (await form.validateFields()) as NativeFiltersForm;
|
let formValues: NativeFiltersForm;
|
||||||
|
try {
|
||||||
|
formValues = (await form.validateFields()) as NativeFiltersForm;
|
||||||
|
} catch (error) {
|
||||||
|
// In Jest tests in chain of tests, Ant generate `outOfDate` error so need to catch it here
|
||||||
|
if (!error?.errorFields?.length && error?.outOfDate) {
|
||||||
|
formValues = error.values;
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
const validateInstant = (filterId: string) => {
|
const validateInstant = (filterId: string) => {
|
||||||
const isInstant = formValues.filters[filterId]
|
const isInstant = formValues.filters[filterId]
|
||||||
? formValues.filters[filterId].isInstant
|
? formValues.filters[filterId].isInstant
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
import { DataMask } from '@superset-ui/core';
|
import { DataMask } from '@superset-ui/core';
|
||||||
import { FilterConfiguration } from '../dashboard/components/nativeFilters/types';
|
import { FilterConfiguration } from '../dashboard/components/nativeFilters/types';
|
||||||
import { FeatureFlag, isFeatureEnabled } from '../featureFlags';
|
import { FeatureFlag, isFeatureEnabled } from '../featureFlags';
|
||||||
|
import { Filters } from '../dashboard/reducers/types';
|
||||||
|
|
||||||
export const UPDATE_DATA_MASK = 'UPDATE_DATA_MASK';
|
export const UPDATE_DATA_MASK = 'UPDATE_DATA_MASK';
|
||||||
export interface UpdateDataMask {
|
export interface UpdateDataMask {
|
||||||
@ -33,6 +34,7 @@ export const SET_DATA_MASK_FOR_FILTER_CONFIG_COMPLETE =
|
|||||||
export interface SetDataMaskForFilterConfigComplete {
|
export interface SetDataMaskForFilterConfigComplete {
|
||||||
type: typeof SET_DATA_MASK_FOR_FILTER_CONFIG_COMPLETE;
|
type: typeof SET_DATA_MASK_FOR_FILTER_CONFIG_COMPLETE;
|
||||||
filterConfig: FilterConfiguration;
|
filterConfig: FilterConfiguration;
|
||||||
|
filters?: Filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL =
|
export const SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL =
|
||||||
@ -44,10 +46,12 @@ export interface SetDataMaskForFilterConfigFail {
|
|||||||
}
|
}
|
||||||
export function setDataMaskForFilterConfigComplete(
|
export function setDataMaskForFilterConfigComplete(
|
||||||
filterConfig: FilterConfiguration,
|
filterConfig: FilterConfiguration,
|
||||||
|
filters?: Filters,
|
||||||
): SetDataMaskForFilterConfigComplete {
|
): SetDataMaskForFilterConfigComplete {
|
||||||
return {
|
return {
|
||||||
type: SET_DATA_MASK_FOR_FILTER_CONFIG_COMPLETE,
|
type: SET_DATA_MASK_FOR_FILTER_CONFIG_COMPLETE,
|
||||||
filterConfig,
|
filterConfig,
|
||||||
|
filters,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export function updateDataMask(
|
export function updateDataMask(
|
||||||
|
@ -34,6 +34,8 @@ import {
|
|||||||
Filter,
|
Filter,
|
||||||
FilterConfiguration,
|
FilterConfiguration,
|
||||||
} from '../dashboard/components/nativeFilters/types';
|
} from '../dashboard/components/nativeFilters/types';
|
||||||
|
import { areObjectsEqual } from '../reduxUtils';
|
||||||
|
import { Filters } from '../dashboard/reducers/types';
|
||||||
|
|
||||||
export function getInitialDataMask(id?: string): DataMask;
|
export function getInitialDataMask(id?: string): DataMask;
|
||||||
export function getInitialDataMask(id: string): DataMaskWithId {
|
export function getInitialDataMask(id: string): DataMaskWithId {
|
||||||
@ -54,21 +56,37 @@ export function getInitialDataMask(id: string): DataMaskWithId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fillNativeFilters(
|
function fillNativeFilters(
|
||||||
data: FilterConfiguration,
|
filterConfig: FilterConfiguration,
|
||||||
cleanState: DataMaskStateWithId,
|
mergedDataMask: DataMaskStateWithId,
|
||||||
draft: DataMaskStateWithId,
|
draftDataMask: DataMaskStateWithId,
|
||||||
|
currentFilters?: Filters,
|
||||||
) {
|
) {
|
||||||
data.forEach((filter: Filter) => {
|
filterConfig.forEach((filter: Filter) => {
|
||||||
cleanState[filter.id] = {
|
mergedDataMask[filter.id] = {
|
||||||
...getInitialDataMask(filter.id), // take initial data
|
...getInitialDataMask(filter.id), // take initial data
|
||||||
...filter.defaultDataMask, // if something new came from BE - take it
|
...filter.defaultDataMask, // if something new came from BE - take it
|
||||||
...draft[filter.id], // keep local filter data
|
...draftDataMask[filter.id], // keep local filter data
|
||||||
};
|
};
|
||||||
|
// if we came from filters config modal and particular filters changed take it's dataMask
|
||||||
|
if (
|
||||||
|
currentFilters &&
|
||||||
|
!areObjectsEqual(
|
||||||
|
filter.defaultDataMask,
|
||||||
|
currentFilters[filter.id]?.defaultDataMask,
|
||||||
|
{ ignoreUndefined: true },
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
mergedDataMask[filter.id] = {
|
||||||
|
...mergedDataMask[filter.id],
|
||||||
|
...filter.defaultDataMask,
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get back all other non-native filters
|
// Get back all other non-native filters
|
||||||
Object.values(draft).forEach(filter => {
|
Object.values(draftDataMask).forEach(filter => {
|
||||||
if (!String(filter?.id).startsWith(NATIVE_FILTER_PREFIX)) {
|
if (!String(filter?.id).startsWith(NATIVE_FILTER_PREFIX)) {
|
||||||
cleanState[filter?.id] = filter;
|
mergedDataMask[filter?.id] = filter;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -106,7 +124,12 @@ const dataMaskReducer = produce(
|
|||||||
);
|
);
|
||||||
return cleanState;
|
return cleanState;
|
||||||
case SET_DATA_MASK_FOR_FILTER_CONFIG_COMPLETE:
|
case SET_DATA_MASK_FOR_FILTER_CONFIG_COMPLETE:
|
||||||
fillNativeFilters(action.filterConfig ?? [], cleanState, draft);
|
fillNativeFilters(
|
||||||
|
action.filterConfig ?? [],
|
||||||
|
cleanState,
|
||||||
|
draft,
|
||||||
|
action.filters,
|
||||||
|
);
|
||||||
return cleanState;
|
return cleanState;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -37,6 +37,7 @@ const config: ControlPanelConfig = {
|
|||||||
type: 'CheckboxControl',
|
type: 'CheckboxControl',
|
||||||
label: t('Multiple select'),
|
label: t('Multiple select'),
|
||||||
default: multiSelect,
|
default: multiSelect,
|
||||||
|
affectsDataMask: true,
|
||||||
resetConfig: true,
|
resetConfig: true,
|
||||||
renderTrigger: true,
|
renderTrigger: true,
|
||||||
description: t('Allow selecting multiple values'),
|
description: t('Allow selecting multiple values'),
|
||||||
|
@ -61,6 +61,7 @@ const config: ControlPanelConfig = {
|
|||||||
label: t('Multiple select'),
|
label: t('Multiple select'),
|
||||||
default: multiSelect,
|
default: multiSelect,
|
||||||
resetConfig: true,
|
resetConfig: true,
|
||||||
|
affectsDataMask: true,
|
||||||
renderTrigger: true,
|
renderTrigger: true,
|
||||||
description: t('Allow selecting multiple values'),
|
description: t('Allow selecting multiple values'),
|
||||||
},
|
},
|
||||||
@ -89,6 +90,7 @@ const config: ControlPanelConfig = {
|
|||||||
label: t('Default to first item'),
|
label: t('Default to first item'),
|
||||||
default: defaultToFirstItem,
|
default: defaultToFirstItem,
|
||||||
resetConfig: true,
|
resetConfig: true,
|
||||||
|
affectsDataMask: true,
|
||||||
renderTrigger: true,
|
renderTrigger: true,
|
||||||
description: t('Select first item by default'),
|
description: t('Select first item by default'),
|
||||||
},
|
},
|
||||||
@ -100,6 +102,7 @@ const config: ControlPanelConfig = {
|
|||||||
config: {
|
config: {
|
||||||
type: 'CheckboxControl',
|
type: 'CheckboxControl',
|
||||||
renderTrigger: true,
|
renderTrigger: true,
|
||||||
|
affectsDataMask: true,
|
||||||
label: t('Inverse selection'),
|
label: t('Inverse selection'),
|
||||||
default: inverseSelection,
|
default: inverseSelection,
|
||||||
description: t('Exclude selected values'),
|
description: t('Exclude selected values'),
|
||||||
|
Loading…
Reference in New Issue
Block a user