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); 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(); addFilter();
await clickCancel(); await clickCancel();
expect(onCancel.mock.calls).toHaveLength(0); expect(onCancel.mock.calls).toHaveLength(0);
expect(wrapper.find(Alert).text()).toContain( expect(wrapper.find(Alert).text()).toContain(
'Are you sure you want to cancel? "New filter" will not be saved.', 'There are unsaved changes.',
);
});
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.',
); );
}); });
}); });

View File

@ -44,6 +44,7 @@ import React, {
useState, useState,
} from 'react'; } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { isEqual } from 'lodash';
import { FormItem } from 'src/components/Form'; import { FormItem } from 'src/components/Form';
import { Input } from 'src/common/components'; import { Input } from 'src/common/components';
import { Select } from 'src/components'; import { Select } from 'src/components';
@ -525,9 +526,21 @@ const FiltersConfigForm = (
showDataset, showDataset,
]); ]);
const formChanged = useCallback(() => {
form.setFields([
{
name: 'changed',
value: true,
},
]);
}, [form]);
const updateFormValues = useCallback( const updateFormValues = useCallback(
(values: any) => setNativeFilterFieldValues(form, filterId, values), (values: any) => {
[filterId, form], setNativeFilterFieldValues(form, filterId, values);
formChanged();
},
[filterId, form, formChanged],
); );
const parentFilterOptions = parentFilters.map(filter => ({ const parentFilterOptions = parentFilters.map(filter => ({
@ -589,6 +602,11 @@ const FiltersConfigForm = (
formFilter?.filterType === 'filter_select' || formFilter?.filterType === 'filter_select' ||
formFilter?.filterType === 'filter_range'; formFilter?.filterType === 'filter_range';
const initialDefaultValue =
formFilter.filterType === filterToEdit?.filterType
? filterToEdit?.defaultDataMask
: null;
const preFilterValidator = () => { const preFilterValidator = () => {
if (hasTimeRange || hasAdhoc) { if (hasTimeRange || hasAdhoc) {
return Promise.resolve(); return Promise.resolve();
@ -784,16 +802,15 @@ const FiltersConfigForm = (
disabled={isRequired || defaultToFirstItem} disabled={isRequired || defaultToFirstItem}
tooltip={defaultValueTooltip} tooltip={defaultValueTooltip}
checked={hasDefaultValue} checked={hasDefaultValue}
onChange={value => setHasDefaultValue(value)} onChange={value => {
setHasDefaultValue(value);
formChanged();
}}
> >
{formFilter.filterType && ( {formFilter.filterType && (
<StyledRowSubFormItem <StyledRowSubFormItem
name={['filters', filterId, 'defaultDataMask']} name={['filters', filterId, 'defaultDataMask']}
initialValue={ initialValue={initialDefaultValue}
formFilter.filterType === filterToEdit?.filterType
? filterToEdit?.defaultDataMask
: null
}
data-test="default-input" data-test="default-input"
label={<StyledLabel>{t('Default Value')}</StyledLabel>} label={<StyledLabel>{t('Default Value')}</StyledLabel>}
required={hasDefaultValue} required={hasDefaultValue}
@ -820,6 +837,14 @@ const FiltersConfigForm = (
<DefaultValueContainer> <DefaultValueContainer>
<DefaultValue <DefaultValue
setDataMask={dataMask => { setDataMask={dataMask => {
if (
!isEqual(
initialDefaultValue?.filterState?.value,
dataMask?.filterState?.value,
)
) {
formChanged();
}
setNativeFilterFieldValues(form, filterId, { setNativeFilterFieldValues(form, filterId, {
defaultDataMask: dataMask, defaultDataMask: dataMask,
}); });
@ -862,6 +887,7 @@ const FiltersConfigForm = (
title={t('Filter is hierarchical')} title={t('Filter is hierarchical')}
initialValue={hasParentFilter} initialValue={hasParentFilter}
onChange={checked => { onChange={checked => {
formChanged();
if (checked) { if (checked) {
// execute after render // execute after render
setTimeout( setTimeout(
@ -900,6 +926,7 @@ const FiltersConfigForm = (
title={t('Pre-filter available values')} title={t('Pre-filter available values')}
initialValue={hasPreFilter} initialValue={hasPreFilter}
onChange={checked => { onChange={checked => {
formChanged();
if (checked) { if (checked) {
validatePreFilter(); validatePreFilter();
} }
@ -1000,7 +1027,10 @@ const FiltersConfigForm = (
{formFilter?.filterType !== 'filter_range' && ( {formFilter?.filterType !== 'filter_range' && (
<CollapsibleControl <CollapsibleControl
title={t('Sort filter values')} title={t('Sort filter values')}
onChange={checked => onSortChanged(checked || undefined)} onChange={checked => {
onSortChanged(checked || undefined);
formChanged();
}}
initialValue={hasSorting} initialValue={hasSorting}
> >
<StyledRowFormItem <StyledRowFormItem

View File

@ -171,7 +171,7 @@ export function FiltersConfigModal({
setCurrentFilterId(initialCurrentFilterId); setCurrentFilterId(initialCurrentFilterId);
setRemovedFilters({}); setRemovedFilters({});
setSaveAlertVisible(false); setSaveAlertVisible(false);
setFormValues({ filters: {} }); setFormValues({ filters: {}, changed: false });
}; };
const getFilterTitle = (id: string) => const getFilterTitle = (id: string) =>
@ -212,6 +212,7 @@ export function FiltersConfigModal({
onSave, onSave,
values, values,
)(); )();
resetForm();
} else { } else {
configFormRef.current.changeTab('configuration'); configFormRef.current.changeTab('configuration');
} }
@ -223,7 +224,8 @@ export function FiltersConfigModal({
}; };
const handleCancel = () => { const handleCancel = () => {
if (unsavedFiltersIds.length > 0) { const changed = form.getFieldValue('changed');
if (unsavedFiltersIds.length > 0 || form.isFieldsTouched() || changed) {
setSaveAlertVisible(true); setSaveAlertVisible(true);
} else { } else {
handleConfirmCancel(); handleConfirmCancel();
@ -245,10 +247,8 @@ export function FiltersConfigModal({
<Footer <Footer
onDismiss={() => setSaveAlertVisible(false)} onDismiss={() => setSaveAlertVisible(false)}
onCancel={handleCancel} onCancel={handleCancel}
getFilterTitle={getFilterTitle}
handleSave={handleSave} handleSave={handleSave}
saveAlertVisible={saveAlertVisible} saveAlertVisible={saveAlertVisible}
unsavedFiltersIds={unsavedFiltersIds}
onConfirmCancel={handleConfirmCancel} onConfirmCancel={handleConfirmCancel}
/> />
} }

View File

@ -27,8 +27,6 @@ type FooterProps = {
onConfirmCancel: OnClickHandler; onConfirmCancel: OnClickHandler;
onDismiss: OnClickHandler; onDismiss: OnClickHandler;
saveAlertVisible: boolean; saveAlertVisible: boolean;
getFilterTitle: (id: string) => string;
unsavedFiltersIds: string[];
}; };
const Footer: FC<FooterProps> = ({ const Footer: FC<FooterProps> = ({
@ -36,38 +34,17 @@ const Footer: FC<FooterProps> = ({
handleSave, handleSave,
onDismiss, onDismiss,
onConfirmCancel, onConfirmCancel,
getFilterTitle,
unsavedFiltersIds,
saveAlertVisible, 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) { if (saveAlertVisible) {
return ( return (
<CancelConfirmationAlert <CancelConfirmationAlert
key="cancel-confirm" key="cancel-confirm"
title={`${unsavedFiltersIds.length} ${t('unsaved filters')}`} title={t('There are unsaved changes.')}
onConfirm={onConfirmCancel} onConfirm={onConfirmCancel}
onDismiss={onDismiss} onDismiss={onDismiss}
> >
{t(`Are you sure you want to cancel?`)} {getUnsavedFilterNames()}{' '} {t(`Are you sure you want to cancel?`)}
{t(`will not be saved.`)}
</CancelConfirmationAlert> </CancelConfirmationAlert>
); );
} }

View File

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