mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[RAM] Reset rule settings modal on cancel (#169720)
## Summary Fixes #169296 - Resets the rule settings modal when the user clicks Cancel, but caches the initial pull from the server so that a second request isn't necessary on reopen - Updates this cache on save so that the reset on modal close remains accurate ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
parent
8500600393
commit
3a5d6cc92b
2 changed files with 79 additions and 17 deletions
|
@ -200,6 +200,36 @@ describe('rules_settings_modal', () => {
|
|||
expect(modalProps.onSave).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('reset flapping settings to initial state on cancel without triggering another server reload', async () => {
|
||||
const result = render(<RulesSettingsModalWithProviders {...modalProps} />);
|
||||
expect(getFlappingSettingsMock).toHaveBeenCalledTimes(1);
|
||||
expect(getQueryDelaySettingsMock).toHaveBeenCalledTimes(1);
|
||||
await waitForModalLoad();
|
||||
|
||||
const lookBackWindowInput = result.getByTestId('lookBackWindowRangeInput');
|
||||
const statusChangeThresholdInput = result.getByTestId('statusChangeThresholdRangeInput');
|
||||
|
||||
fireEvent.change(lookBackWindowInput, { target: { value: 15 } });
|
||||
fireEvent.change(statusChangeThresholdInput, { target: { value: 3 } });
|
||||
|
||||
expect(lookBackWindowInput.getAttribute('value')).toBe('15');
|
||||
expect(statusChangeThresholdInput.getAttribute('value')).toBe('3');
|
||||
|
||||
// Try cancelling
|
||||
userEvent.click(result.getByTestId('rulesSettingsModalCancelButton'));
|
||||
|
||||
expect(modalProps.onClose).toHaveBeenCalledTimes(1);
|
||||
expect(updateFlappingSettingsMock).not.toHaveBeenCalled();
|
||||
expect(modalProps.onSave).not.toHaveBeenCalled();
|
||||
|
||||
expect(screen.queryByTestId('centerJustifiedSpinner')).toBe(null);
|
||||
expect(lookBackWindowInput.getAttribute('value')).toBe('10');
|
||||
expect(statusChangeThresholdInput.getAttribute('value')).toBe('10');
|
||||
|
||||
expect(getFlappingSettingsMock).toHaveBeenCalledTimes(1);
|
||||
expect(getQueryDelaySettingsMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should prevent statusChangeThreshold from being greater than lookBackWindow', async () => {
|
||||
const result = render(<RulesSettingsModalWithProviders {...modalProps} />);
|
||||
await waitForModalLoad();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { memo, useState } from 'react';
|
||||
import React, { memo, useCallback, useState, useRef } from 'react';
|
||||
import {
|
||||
RulesSettingsFlappingProperties,
|
||||
RulesSettingsProperties,
|
||||
|
@ -60,6 +60,26 @@ export const RulesSettingsErrorPrompt = memo(() => {
|
|||
);
|
||||
});
|
||||
|
||||
const useResettableState: <T>(
|
||||
initialValue?: T
|
||||
) => [T | undefined, boolean, (next: T, shouldUpdateInitialValue?: boolean) => void, () => void] = (
|
||||
initalValue
|
||||
) => {
|
||||
const initialValueRef = useRef(initalValue);
|
||||
const [value, setValue] = useState(initalValue);
|
||||
const [hasChanged, setHasChanged] = useState(false);
|
||||
const reset = () => {
|
||||
setValue(initialValueRef.current);
|
||||
setHasChanged(false);
|
||||
};
|
||||
const updateValue = (next: typeof value, shouldUpdateInitialValue = false) => {
|
||||
setValue(next);
|
||||
setHasChanged(true);
|
||||
if (shouldUpdateInitialValue) initialValueRef.current = next;
|
||||
};
|
||||
return [value, hasChanged, updateValue, reset];
|
||||
};
|
||||
|
||||
export interface RulesSettingsModalProps {
|
||||
isVisible: boolean;
|
||||
setUpdatingRulesSettings?: (isUpdating: boolean) => void;
|
||||
|
@ -84,21 +104,24 @@ export const RulesSettingsModal = memo((props: RulesSettingsModalProps) => {
|
|||
},
|
||||
} = capabilities;
|
||||
|
||||
const [flappingSettings, setFlappingSettings] = useState<RulesSettingsFlappingProperties>();
|
||||
const [hasFlappingChanged, setHasFlappingChanged] = useState<boolean>(false);
|
||||
const [flappingSettings, hasFlappingChanged, setFlappingSettings, resetFlappingSettings] =
|
||||
useResettableState<RulesSettingsFlappingProperties>();
|
||||
|
||||
const [queryDelaySettings, setQueryDelaySettings] = useState<RulesSettingsQueryDelayProperties>();
|
||||
const [hasQueryDelayChanged, setHasQueryDelayChanged] = useState<boolean>(false);
|
||||
const [queryDelaySettings, hasQueryDelayChanged, setQueryDelaySettings, resetQueryDelaySettings] =
|
||||
useResettableState<RulesSettingsQueryDelayProperties>();
|
||||
|
||||
const { isLoading: isFlappingLoading, isError: hasFlappingError } = useGetFlappingSettings({
|
||||
enabled: isVisible,
|
||||
onSuccess: (fetchedSettings) => {
|
||||
if (!flappingSettings) {
|
||||
setFlappingSettings({
|
||||
enabled: fetchedSettings.enabled,
|
||||
lookBackWindow: fetchedSettings.lookBackWindow,
|
||||
statusChangeThreshold: fetchedSettings.statusChangeThreshold,
|
||||
});
|
||||
setFlappingSettings(
|
||||
{
|
||||
enabled: fetchedSettings.enabled,
|
||||
lookBackWindow: fetchedSettings.lookBackWindow,
|
||||
statusChangeThreshold: fetchedSettings.statusChangeThreshold,
|
||||
},
|
||||
true // Update the initial value so we don't need to fetch it from the server again
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -107,13 +130,22 @@ export const RulesSettingsModal = memo((props: RulesSettingsModalProps) => {
|
|||
enabled: isVisible,
|
||||
onSuccess: (fetchedSettings) => {
|
||||
if (!queryDelaySettings) {
|
||||
setQueryDelaySettings({
|
||||
delay: fetchedSettings.delay,
|
||||
});
|
||||
setQueryDelaySettings(
|
||||
{
|
||||
delay: fetchedSettings.delay,
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const onCloseModal = useCallback(() => {
|
||||
resetFlappingSettings();
|
||||
resetQueryDelaySettings();
|
||||
onClose();
|
||||
}, [onClose, resetFlappingSettings, resetQueryDelaySettings]);
|
||||
|
||||
const { mutate } = useUpdateRuleSettings({
|
||||
onSave,
|
||||
onClose,
|
||||
|
@ -148,7 +180,6 @@ export const RulesSettingsModal = memo((props: RulesSettingsModalProps) => {
|
|||
newSettings.statusChangeThreshold
|
||||
),
|
||||
});
|
||||
setHasFlappingChanged(true);
|
||||
}
|
||||
|
||||
if (setting === 'queryDelay') {
|
||||
|
@ -160,7 +191,6 @@ export const RulesSettingsModal = memo((props: RulesSettingsModalProps) => {
|
|||
[key]: value,
|
||||
};
|
||||
setQueryDelaySettings(newSettings);
|
||||
setHasQueryDelayChanged(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -168,9 +198,11 @@ export const RulesSettingsModal = memo((props: RulesSettingsModalProps) => {
|
|||
const updatedSettings: RulesSettingsProperties = {};
|
||||
if (canWriteFlappingSettings && hasFlappingChanged) {
|
||||
updatedSettings.flapping = flappingSettings;
|
||||
setFlappingSettings(flappingSettings!, true);
|
||||
}
|
||||
if (canWriteQueryDelaySettings && hasQueryDelayChanged) {
|
||||
updatedSettings.queryDelay = queryDelaySettings;
|
||||
setQueryDelaySettings(queryDelaySettings!, true);
|
||||
}
|
||||
mutate(updatedSettings);
|
||||
};
|
||||
|
@ -214,7 +246,7 @@ export const RulesSettingsModal = memo((props: RulesSettingsModalProps) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<EuiModal data-test-subj="rulesSettingsModal" onClose={onClose} maxWidth={880}>
|
||||
<EuiModal data-test-subj="rulesSettingsModal" onClose={onCloseModal} maxWidth={880}>
|
||||
<EuiModalHeader>
|
||||
<EuiModalHeaderTitle component="h3">
|
||||
<FormattedMessage
|
||||
|
@ -236,7 +268,7 @@ export const RulesSettingsModal = memo((props: RulesSettingsModalProps) => {
|
|||
<EuiHorizontalRule margin="none" />
|
||||
</EuiModalBody>
|
||||
<EuiModalFooter>
|
||||
<EuiButtonEmpty data-test-subj="rulesSettingsModalCancelButton" onClick={onClose}>
|
||||
<EuiButtonEmpty data-test-subj="rulesSettingsModalCancelButton" onClick={onCloseModal}>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.rulesSettings.modal.cancelButton"
|
||||
defaultMessage="Cancel"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue