Alert intent & grace
diff --git a/frontend-modern/src/features/alerts/__tests__/AlertIntentPolicyPanel.test.tsx b/frontend-modern/src/features/alerts/__tests__/AlertIntentPolicyPanel.test.tsx
index 65a1aa2870..00f2b7b735 100644
--- a/frontend-modern/src/features/alerts/__tests__/AlertIntentPolicyPanel.test.tsx
+++ b/frontend-modern/src/features/alerts/__tests__/AlertIntentPolicyPanel.test.tsx
@@ -79,6 +79,23 @@ describe('AlertIntentPolicyPanel', () => {
expect(await screen.findByLabelText('Resource')).toHaveValue(resource.id);
});
+ it('opens directly on a row-selected resource and signal', async () => {
+ render(() => (
+
+ ));
+
+ expect(await screen.findByRole('button', { name: 'Hide policies' })).toBeInTheDocument();
+ expect(screen.getByLabelText('Resource')).toHaveValue(resource.id);
+ expect(screen.getByLabelText('Signal')).toHaveValue('metric.memory');
+ });
+
it('saves field-level resource overrides without disabling inherited policy', async () => {
render(() =>
);
diff --git a/frontend-modern/src/features/alerts/__tests__/ThresholdsTab.test.tsx b/frontend-modern/src/features/alerts/__tests__/ThresholdsTab.test.tsx
index ff02825618..aafb35681d 100644
--- a/frontend-modern/src/features/alerts/__tests__/ThresholdsTab.test.tsx
+++ b/frontend-modern/src/features/alerts/__tests__/ThresholdsTab.test.tsx
@@ -1,4 +1,4 @@
-import { render, cleanup } from '@solidjs/testing-library';
+import { render, cleanup, waitFor } from '@solidjs/testing-library';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { ThresholdsTab } from '../tabs/ThresholdsTab';
@@ -271,6 +271,7 @@ const buildProps = (): ThresholdsTabProps =>
describe('ThresholdsTab', () => {
beforeEach(() => {
captureThresholdsTableProps.mockReset();
+ captureIntentPolicyProps.mockReset();
});
afterEach(() => {
@@ -290,4 +291,28 @@ describe('ThresholdsTab', () => {
expect(typeof props.guestDefaults).toBe('object');
expect(typeof props.dockerDefaults).toBe('object');
});
+
+ it('routes a resource-row delay action into the canonical intent policy panel', async () => {
+ render(() =>
);
+
+ const tableProps = captureThresholdsTableProps.mock.calls[0][0] as {
+ onConfigureResourceIntent: (resourceId: string, signal: string) => void;
+ };
+ tableProps.onConfigureResourceIntent('vm-canonical', 'metric.memory');
+
+ await waitFor(() => {
+ const panelProps = captureIntentPolicyProps.mock.calls.at(-1)?.[0] as {
+ selectionTarget?: {
+ resourceId: string;
+ signal: string;
+ requestId: number;
+ };
+ };
+ expect(panelProps.selectionTarget).toEqual({
+ resourceId: 'vm-canonical',
+ signal: 'metric.memory',
+ requestId: 1,
+ });
+ });
+ });
});
diff --git a/frontend-modern/src/features/alerts/tabs/ThresholdsTab.tsx b/frontend-modern/src/features/alerts/tabs/ThresholdsTab.tsx
index fd56dcd330..5e40292543 100644
--- a/frontend-modern/src/features/alerts/tabs/ThresholdsTab.tsx
+++ b/frontend-modern/src/features/alerts/tabs/ThresholdsTab.tsx
@@ -1,13 +1,35 @@
+import { createSignal } from 'solid-js';
import { ThresholdsTable } from '@/components/Alerts/ThresholdsTable';
-import { AlertIntentPolicyPanel } from '../AlertIntentPolicyPanel';
+import {
+ AlertIntentPolicyPanel,
+ type AlertIntentPolicySelectionTarget,
+} from '../AlertIntentPolicyPanel';
+import type { AlertIntentSignal } from '@/api/alertIntentPolicies';
import type { ThresholdsTabProps } from '../thresholds/thresholdsTabModel';
export function ThresholdsTab(props: ThresholdsTabProps) {
+ const [intentSelectionTarget, setIntentSelectionTarget] =
+ createSignal
(null);
+ let intentSelectionRequest = 0;
+
+ const configureResourceIntent = (resourceId: string, signal: AlertIntentSignal) => {
+ intentSelectionRequest += 1;
+ setIntentSelectionTarget({
+ resourceId,
+ signal,
+ requestId: intentSelectionRequest,
+ });
+ };
+
return (
-
+
void;
overrides: () => Override[];
setOverrides: (overrides: Override[]) => void;
rawOverridesConfig: () => Record;