persist form values after redirect to rule page
This commit is contained in:
@@ -6,6 +6,7 @@ import { GrafanaTheme2 } from '@grafana/data';
|
|||||||
import { t } from '@grafana/i18n';
|
import { t } from '@grafana/i18n';
|
||||||
import { Button, Drawer, Stack, useStyles2 } from '@grafana/ui';
|
import { Button, Drawer, Stack, useStyles2 } from '@grafana/ui';
|
||||||
import { useAppNotification } from 'app/core/copy/appNotification';
|
import { useAppNotification } from 'app/core/copy/appNotification';
|
||||||
|
import { getMessageFromError } from 'app/core/utils/errors';
|
||||||
import { RuleDefinitionSection } from 'app/features/alerting/unified/components/RuleDefinitionSection';
|
import { RuleDefinitionSection } from 'app/features/alerting/unified/components/RuleDefinitionSection';
|
||||||
|
|
||||||
import { isGrafanaGroupUpdatedResponse } from '../api/alertRuleModel';
|
import { isGrafanaGroupUpdatedResponse } from '../api/alertRuleModel';
|
||||||
@@ -22,14 +23,20 @@ export interface AlertRuleDrawerFormProps {
|
|||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
title?: string;
|
title?: string;
|
||||||
onContinueInAlerting?: () => void;
|
onContinueInAlerting?: (values: RuleFormValues) => void;
|
||||||
prefill?: Partial<RuleFormValues>;
|
prefill?: Partial<RuleFormValues>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AlertRuleDrawerForm({ isOpen, onClose, title, onContinueInAlerting, prefill }: AlertRuleDrawerFormProps) {
|
export function AlertRuleDrawerForm({
|
||||||
|
isOpen,
|
||||||
|
onClose,
|
||||||
|
title,
|
||||||
|
onContinueInAlerting,
|
||||||
|
prefill,
|
||||||
|
}: AlertRuleDrawerFormProps) {
|
||||||
const baseDefaults = useMemo(() => getDefaultFormValues(RuleFormType.grafana), []);
|
const baseDefaults = useMemo(() => getDefaultFormValues(RuleFormType.grafana), []);
|
||||||
const methods = useForm<RuleFormValues>({
|
const methods = useForm<RuleFormValues>({
|
||||||
defaultValues: prefill ? { ...baseDefaults, ...(prefill as Partial<RuleFormValues>) } : baseDefaults,
|
defaultValues: prefill ? { ...baseDefaults, ...prefill } : baseDefaults,
|
||||||
});
|
});
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const [addRuleToRuleGroup] = useAddRuleToRuleGroup();
|
const [addRuleToRuleGroup] = useAddRuleToRuleGroup();
|
||||||
@@ -38,9 +45,9 @@ export function AlertRuleDrawerForm({ isOpen, onClose, title, onContinueInAlerti
|
|||||||
// Keep form in sync if prefill changes between openings
|
// Keep form in sync if prefill changes between openings
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (prefill) {
|
if (prefill) {
|
||||||
methods.reset({ ...baseDefaults, ...(prefill as Partial<RuleFormValues>) });
|
methods.reset({ ...baseDefaults, ...prefill });
|
||||||
}
|
}
|
||||||
}, [prefill, methods]);
|
}, [prefill, methods, baseDefaults]);
|
||||||
|
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
return null;
|
return null;
|
||||||
@@ -48,7 +55,8 @@ export function AlertRuleDrawerForm({ isOpen, onClose, title, onContinueInAlerti
|
|||||||
|
|
||||||
const submit = async (values: RuleFormValues) => {
|
const submit = async (values: RuleFormValues) => {
|
||||||
try {
|
try {
|
||||||
const groupName = values.group && values.group.trim().length > 0 ? values.group : (values.name?.trim() || 'default');
|
const groupName =
|
||||||
|
values.group && values.group.trim().length > 0 ? values.group : values.name?.trim() || 'default';
|
||||||
const effectiveValues: RuleFormValues = { ...values, group: groupName };
|
const effectiveValues: RuleFormValues = { ...values, group: groupName };
|
||||||
|
|
||||||
const dto = formValuesToRulerGrafanaRuleDTO(effectiveValues);
|
const dto = formValuesToRulerGrafanaRuleDTO(effectiveValues);
|
||||||
@@ -59,9 +67,9 @@ export function AlertRuleDrawerForm({ isOpen, onClose, title, onContinueInAlerti
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
notifyApp.error('Failed to create rule', 'The rule was not created. Please review the form and try again.');
|
notifyApp.error('Failed to create rule', 'The rule was not created. Please review the form and try again.');
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
const msg = err?.data?.message || err?.message || 'Unknown error while creating the rule.';
|
const errorMessage = getMessageFromError(err);
|
||||||
notifyApp.error('Failed to create rule', msg);
|
notifyApp.error('Failed to create rule', errorMessage);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -93,7 +101,7 @@ export function AlertRuleDrawerForm({ isOpen, onClose, title, onContinueInAlerti
|
|||||||
{t('alerting.common.cancel', 'Cancel')}
|
{t('alerting.common.cancel', 'Cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
{onContinueInAlerting && (
|
{onContinueInAlerting && (
|
||||||
<Button variant="secondary" type="button" onClick={onContinueInAlerting}>
|
<Button variant="secondary" type="button" onClick={() => onContinueInAlerting(methods.getValues())}>
|
||||||
{t('alerting.simplified.continue-in-alerting', 'Continue in Alerting')}
|
{t('alerting.simplified.continue-in-alerting', 'Continue in Alerting')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -83,7 +83,9 @@ export function RuleDefinitionSection({ type }: { type: RuleFormType }) {
|
|||||||
isOpen={showLabelsEditor}
|
isOpen={showLabelsEditor}
|
||||||
onClose={(labelsToUpdate) => {
|
onClose={(labelsToUpdate) => {
|
||||||
if (labelsToUpdate) {
|
if (labelsToUpdate) {
|
||||||
const filtered = labelsToUpdate.filter((l) => (l?.key ?? '').length > 0 || (l?.value ?? '').length > 0);
|
const filtered = labelsToUpdate.filter(
|
||||||
|
(l) => (l?.key ?? '').length > 0 || (l?.value ?? '').length > 0
|
||||||
|
);
|
||||||
setValue('labels', filtered, { shouldDirty: true, shouldValidate: true });
|
setValue('labels', filtered, { shouldDirty: true, shouldValidate: true });
|
||||||
}
|
}
|
||||||
setShowLabelsEditor(false);
|
setShowLabelsEditor(false);
|
||||||
|
|||||||
+14
-5
@@ -12,6 +12,7 @@ import { useSelector } from 'app/types/store';
|
|||||||
|
|
||||||
import { LogMessages } from '../../Analytics';
|
import { LogMessages } from '../../Analytics';
|
||||||
import { AlertRuleDrawerForm } from '../../components/AlertRuleDrawerForm';
|
import { AlertRuleDrawerForm } from '../../components/AlertRuleDrawerForm';
|
||||||
|
import type { RuleFormValues } from '../../types/rule-form';
|
||||||
import { panelToRuleFormValues } from '../../utils/rule-form';
|
import { panelToRuleFormValues } from '../../utils/rule-form';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -58,10 +59,10 @@ export const NewRuleFromPanelButton = ({ dashboard, panel, className }: Props) =
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const onContinueInAlerting = async () => {
|
const navigateToAlerting = async (currentValues?: RuleFormValues) => {
|
||||||
logInfo(LogMessages.alertRuleFromPanel);
|
logInfo(LogMessages.alertRuleFromPanel);
|
||||||
// Refresh values to ensure they're up-to-date with current panel state
|
// Prefer current drawer values if provided; otherwise refresh from panel state
|
||||||
const updateToDateFormValues = await panelToRuleFormValues(panel, dashboard);
|
const updateToDateFormValues = currentValues ?? (await panelToRuleFormValues(panel, dashboard));
|
||||||
const ruleFormUrl = urlUtil.renderUrl('alerting/new', {
|
const ruleFormUrl = urlUtil.renderUrl('alerting/new', {
|
||||||
defaults: JSON.stringify(updateToDateFormValues),
|
defaults: JSON.stringify(updateToDateFormValues),
|
||||||
returnTo: location.pathname + location.search,
|
returnTo: location.pathname + location.search,
|
||||||
@@ -69,6 +70,14 @@ export const NewRuleFromPanelButton = ({ dashboard, panel, className }: Props) =
|
|||||||
locationService.push(ruleFormUrl);
|
locationService.push(ruleFormUrl);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onContinueInAlertingFromDrawer = (values: RuleFormValues) => {
|
||||||
|
void navigateToAlerting(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onContinueInAlertingButton = () => {
|
||||||
|
void navigateToAlerting(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
const shouldUseDrawer = config.featureToggles.createAlertRuleFromPanel;
|
const shouldUseDrawer = config.featureToggles.createAlertRuleFromPanel;
|
||||||
|
|
||||||
if (shouldUseDrawer) {
|
if (shouldUseDrawer) {
|
||||||
@@ -85,7 +94,7 @@ export const NewRuleFromPanelButton = ({ dashboard, panel, className }: Props) =
|
|||||||
<AlertRuleDrawerForm
|
<AlertRuleDrawerForm
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
onClose={() => setIsOpen(false)}
|
onClose={() => setIsOpen(false)}
|
||||||
onContinueInAlerting={onContinueInAlerting}
|
onContinueInAlerting={onContinueInAlertingFromDrawer}
|
||||||
prefill={formValues ?? undefined}
|
prefill={formValues ?? undefined}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
@@ -95,7 +104,7 @@ export const NewRuleFromPanelButton = ({ dashboard, panel, className }: Props) =
|
|||||||
return (
|
return (
|
||||||
<LinkButton
|
<LinkButton
|
||||||
icon="bell"
|
icon="bell"
|
||||||
onClick={onContinueInAlerting}
|
onClick={onContinueInAlertingButton}
|
||||||
href={urlUtil.renderUrl('alerting/new', {
|
href={urlUtil.renderUrl('alerting/new', {
|
||||||
defaults: JSON.stringify(formValues),
|
defaults: JSON.stringify(formValues),
|
||||||
returnTo: location.pathname + location.search,
|
returnTo: location.pathname + location.search,
|
||||||
|
|||||||
+13
-4
@@ -9,6 +9,7 @@ import { VizPanel } from '@grafana/scenes';
|
|||||||
import { Alert, Button } from '@grafana/ui';
|
import { Alert, Button } from '@grafana/ui';
|
||||||
import { LogMessages } from 'app/features/alerting/unified/Analytics';
|
import { LogMessages } from 'app/features/alerting/unified/Analytics';
|
||||||
import { AlertRuleDrawerForm } from 'app/features/alerting/unified/components/AlertRuleDrawerForm';
|
import { AlertRuleDrawerForm } from 'app/features/alerting/unified/components/AlertRuleDrawerForm';
|
||||||
|
import type { RuleFormValues } from 'app/features/alerting/unified/types/rule-form';
|
||||||
import { scenesPanelToRuleFormValues } from 'app/features/alerting/unified/utils/rule-form';
|
import { scenesPanelToRuleFormValues } from 'app/features/alerting/unified/utils/rule-form';
|
||||||
|
|
||||||
interface ScenesNewRuleFromPanelButtonProps {
|
interface ScenesNewRuleFromPanelButtonProps {
|
||||||
@@ -45,10 +46,10 @@ export const ScenesNewRuleFromPanelButton = ({ panel, className }: ScenesNewRule
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const onClick = async () => {
|
const navigateToAlerting = async (currentValues?: RuleFormValues) => {
|
||||||
logInfo(LogMessages.alertRuleFromPanel);
|
logInfo(LogMessages.alertRuleFromPanel);
|
||||||
|
|
||||||
const updateToDateFormValues = await scenesPanelToRuleFormValues(panel);
|
const updateToDateFormValues = currentValues ?? (await scenesPanelToRuleFormValues(panel));
|
||||||
|
|
||||||
const ruleFormUrl = urlUtil.renderUrl('/alerting/new', {
|
const ruleFormUrl = urlUtil.renderUrl('/alerting/new', {
|
||||||
defaults: JSON.stringify(updateToDateFormValues),
|
defaults: JSON.stringify(updateToDateFormValues),
|
||||||
@@ -58,6 +59,14 @@ export const ScenesNewRuleFromPanelButton = ({ panel, className }: ScenesNewRule
|
|||||||
locationService.push(ruleFormUrl);
|
locationService.push(ruleFormUrl);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onContinueInAlertingFromDrawer = (values: RuleFormValues) => {
|
||||||
|
void navigateToAlerting(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onButtonClick = () => {
|
||||||
|
void navigateToAlerting(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
const shouldUseDrawer = config.featureToggles.createAlertRuleFromPanel;
|
const shouldUseDrawer = config.featureToggles.createAlertRuleFromPanel;
|
||||||
|
|
||||||
if (shouldUseDrawer) {
|
if (shouldUseDrawer) {
|
||||||
@@ -76,7 +85,7 @@ export const ScenesNewRuleFromPanelButton = ({ panel, className }: ScenesNewRule
|
|||||||
<AlertRuleDrawerForm
|
<AlertRuleDrawerForm
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
onClose={() => setIsOpen(false)}
|
onClose={() => setIsOpen(false)}
|
||||||
onContinueInAlerting={onClick}
|
onContinueInAlerting={onContinueInAlertingFromDrawer}
|
||||||
prefill={formValues ?? undefined}
|
prefill={formValues ?? undefined}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
@@ -84,7 +93,7 @@ export const ScenesNewRuleFromPanelButton = ({ panel, className }: ScenesNewRule
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button icon="bell" onClick={onClick} className={className} data-testid="create-alert-rule-button">
|
<Button icon="bell" onClick={onButtonClick} className={className} data-testid="create-alert-rule-button">
|
||||||
<Trans i18nKey="dashboard-scene.scenes-new-rule-from-panel-button.new-alert-rule">New alert rule</Trans>
|
<Trans i18nKey="dashboard-scene.scenes-new-rule-from-panel-button.new-alert-rule">New alert rule</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user