mirror of https://github.com/apache/superset.git
fix: Cancel alert is not appearing to all native filters modal fields (#15925)
This commit is contained in:
parent
eb78f4332f
commit
cc704dd53a
|
@ -119,22 +119,12 @@ describe('FiltersConfigModal', () => {
|
|||
expect(onCancel.mock.calls).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('shows correct alert message for an unsaved filter', async () => {
|
||||
it('shows correct alert message for unsaved filters', async () => {
|
||||
addFilter();
|
||||
await clickCancel();
|
||||
expect(onCancel.mock.calls).toHaveLength(0);
|
||||
expect(wrapper.find(Alert).text()).toContain(
|
||||
'Are you sure you want to cancel? "New filter" will not be saved.',
|
||||
);
|
||||
});
|
||||
|
||||
it('shows correct alert message for 2 unsaved filters', async () => {
|
||||
addFilter();
|
||||
addFilter();
|
||||
await clickCancel();
|
||||
expect(onCancel.mock.calls).toHaveLength(0);
|
||||
expect(wrapper.find(Alert).text()).toContain(
|
||||
'Are you sure you want to cancel? "New filter" and "New filter" will not be saved.',
|
||||
'There are unsaved changes.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -44,6 +44,7 @@ import React, {
|
|||
useState,
|
||||
} from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { isEqual } from 'lodash';
|
||||
import { FormItem } from 'src/components/Form';
|
||||
import { Input } from 'src/common/components';
|
||||
import { Select } from 'src/components';
|
||||
|
@ -525,9 +526,21 @@ const FiltersConfigForm = (
|
|||
showDataset,
|
||||
]);
|
||||
|
||||
const formChanged = useCallback(() => {
|
||||
form.setFields([
|
||||
{
|
||||
name: 'changed',
|
||||
value: true,
|
||||
},
|
||||
]);
|
||||
}, [form]);
|
||||
|
||||
const updateFormValues = useCallback(
|
||||
(values: any) => setNativeFilterFieldValues(form, filterId, values),
|
||||
[filterId, form],
|
||||
(values: any) => {
|
||||
setNativeFilterFieldValues(form, filterId, values);
|
||||
formChanged();
|
||||
},
|
||||
[filterId, form, formChanged],
|
||||
);
|
||||
|
||||
const parentFilterOptions = parentFilters.map(filter => ({
|
||||
|
@ -589,6 +602,11 @@ const FiltersConfigForm = (
|
|||
formFilter?.filterType === 'filter_select' ||
|
||||
formFilter?.filterType === 'filter_range';
|
||||
|
||||
const initialDefaultValue =
|
||||
formFilter.filterType === filterToEdit?.filterType
|
||||
? filterToEdit?.defaultDataMask
|
||||
: null;
|
||||
|
||||
const preFilterValidator = () => {
|
||||
if (hasTimeRange || hasAdhoc) {
|
||||
return Promise.resolve();
|
||||
|
@ -784,16 +802,15 @@ const FiltersConfigForm = (
|
|||
disabled={isRequired || defaultToFirstItem}
|
||||
tooltip={defaultValueTooltip}
|
||||
checked={hasDefaultValue}
|
||||
onChange={value => setHasDefaultValue(value)}
|
||||
onChange={value => {
|
||||
setHasDefaultValue(value);
|
||||
formChanged();
|
||||
}}
|
||||
>
|
||||
{formFilter.filterType && (
|
||||
<StyledRowSubFormItem
|
||||
name={['filters', filterId, 'defaultDataMask']}
|
||||
initialValue={
|
||||
formFilter.filterType === filterToEdit?.filterType
|
||||
? filterToEdit?.defaultDataMask
|
||||
: null
|
||||
}
|
||||
initialValue={initialDefaultValue}
|
||||
data-test="default-input"
|
||||
label={<StyledLabel>{t('Default Value')}</StyledLabel>}
|
||||
required={hasDefaultValue}
|
||||
|
@ -820,6 +837,14 @@ const FiltersConfigForm = (
|
|||
<DefaultValueContainer>
|
||||
<DefaultValue
|
||||
setDataMask={dataMask => {
|
||||
if (
|
||||
!isEqual(
|
||||
initialDefaultValue?.filterState?.value,
|
||||
dataMask?.filterState?.value,
|
||||
)
|
||||
) {
|
||||
formChanged();
|
||||
}
|
||||
setNativeFilterFieldValues(form, filterId, {
|
||||
defaultDataMask: dataMask,
|
||||
});
|
||||
|
@ -862,6 +887,7 @@ const FiltersConfigForm = (
|
|||
title={t('Filter is hierarchical')}
|
||||
initialValue={hasParentFilter}
|
||||
onChange={checked => {
|
||||
formChanged();
|
||||
if (checked) {
|
||||
// execute after render
|
||||
setTimeout(
|
||||
|
@ -900,6 +926,7 @@ const FiltersConfigForm = (
|
|||
title={t('Pre-filter available values')}
|
||||
initialValue={hasPreFilter}
|
||||
onChange={checked => {
|
||||
formChanged();
|
||||
if (checked) {
|
||||
validatePreFilter();
|
||||
}
|
||||
|
@ -1000,7 +1027,10 @@ const FiltersConfigForm = (
|
|||
{formFilter?.filterType !== 'filter_range' && (
|
||||
<CollapsibleControl
|
||||
title={t('Sort filter values')}
|
||||
onChange={checked => onSortChanged(checked || undefined)}
|
||||
onChange={checked => {
|
||||
onSortChanged(checked || undefined);
|
||||
formChanged();
|
||||
}}
|
||||
initialValue={hasSorting}
|
||||
>
|
||||
<StyledRowFormItem
|
||||
|
|
|
@ -171,7 +171,7 @@ export function FiltersConfigModal({
|
|||
setCurrentFilterId(initialCurrentFilterId);
|
||||
setRemovedFilters({});
|
||||
setSaveAlertVisible(false);
|
||||
setFormValues({ filters: {} });
|
||||
setFormValues({ filters: {}, changed: false });
|
||||
};
|
||||
|
||||
const getFilterTitle = (id: string) =>
|
||||
|
@ -212,6 +212,7 @@ export function FiltersConfigModal({
|
|||
onSave,
|
||||
values,
|
||||
)();
|
||||
resetForm();
|
||||
} else {
|
||||
configFormRef.current.changeTab('configuration');
|
||||
}
|
||||
|
@ -223,7 +224,8 @@ export function FiltersConfigModal({
|
|||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
if (unsavedFiltersIds.length > 0) {
|
||||
const changed = form.getFieldValue('changed');
|
||||
if (unsavedFiltersIds.length > 0 || form.isFieldsTouched() || changed) {
|
||||
setSaveAlertVisible(true);
|
||||
} else {
|
||||
handleConfirmCancel();
|
||||
|
@ -245,10 +247,8 @@ export function FiltersConfigModal({
|
|||
<Footer
|
||||
onDismiss={() => setSaveAlertVisible(false)}
|
||||
onCancel={handleCancel}
|
||||
getFilterTitle={getFilterTitle}
|
||||
handleSave={handleSave}
|
||||
saveAlertVisible={saveAlertVisible}
|
||||
unsavedFiltersIds={unsavedFiltersIds}
|
||||
onConfirmCancel={handleConfirmCancel}
|
||||
/>
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@ type FooterProps = {
|
|||
onConfirmCancel: OnClickHandler;
|
||||
onDismiss: OnClickHandler;
|
||||
saveAlertVisible: boolean;
|
||||
getFilterTitle: (id: string) => string;
|
||||
unsavedFiltersIds: string[];
|
||||
};
|
||||
|
||||
const Footer: FC<FooterProps> = ({
|
||||
|
@ -36,38 +34,17 @@ const Footer: FC<FooterProps> = ({
|
|||
handleSave,
|
||||
onDismiss,
|
||||
onConfirmCancel,
|
||||
getFilterTitle,
|
||||
unsavedFiltersIds,
|
||||
saveAlertVisible,
|
||||
}) => {
|
||||
const getUnsavedFilterNames = (): string => {
|
||||
const unsavedFiltersNames = unsavedFiltersIds.map(
|
||||
id => `"${getFilterTitle(id)}"`,
|
||||
);
|
||||
|
||||
if (unsavedFiltersNames.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (unsavedFiltersNames.length === 1) {
|
||||
return unsavedFiltersNames[0];
|
||||
}
|
||||
|
||||
const lastFilter = unsavedFiltersNames.pop();
|
||||
|
||||
return `${unsavedFiltersNames.join(', ')} ${t('and')} ${lastFilter}`;
|
||||
};
|
||||
|
||||
if (saveAlertVisible) {
|
||||
return (
|
||||
<CancelConfirmationAlert
|
||||
key="cancel-confirm"
|
||||
title={`${unsavedFiltersIds.length} ${t('unsaved filters')}`}
|
||||
title={t('There are unsaved changes.')}
|
||||
onConfirm={onConfirmCancel}
|
||||
onDismiss={onDismiss}
|
||||
>
|
||||
{t(`Are you sure you want to cancel?`)} {getUnsavedFilterNames()}{' '}
|
||||
{t(`will not be saved.`)}
|
||||
{t(`Are you sure you want to cancel?`)}
|
||||
</CancelConfirmationAlert>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ export interface NativeFiltersFormItem {
|
|||
|
||||
export interface NativeFiltersForm {
|
||||
filters: Record<string, NativeFiltersFormItem>;
|
||||
changed?: boolean;
|
||||
}
|
||||
|
||||
export type FilterRemoval =
|
||||
|
|
Loading…
Reference in New Issue