fix: Cancel alert is not appearing to all native filters modal fields (#15925)

This commit is contained in:
Michael S. Molina 2021-07-30 11:59:36 -03:00 committed by GitHub
parent eb78f4332f
commit cc704dd53a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 50 deletions

View File

@ -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.',
);
});
});

View File

@ -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

View File

@ -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}
/>
}

View File

@ -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>
);
}

View File

@ -48,6 +48,7 @@ export interface NativeFiltersFormItem {
export interface NativeFiltersForm {
filters: Record<string, NativeFiltersFormItem>;
changed?: boolean;
}
export type FilterRemoval =