Extract alert thresholds tab

This commit is contained in:
rcourtman
2026-03-20 15:20:27 +00:00
parent ee178e967c
commit 5f0f6119c8
6 changed files with 315 additions and 298 deletions
@@ -149,12 +149,13 @@ assume discovery metadata is always present when deriving override IDs or
toggle styling.
The alerts page shell in `frontend-modern/src/pages/Alerts.tsx` must now keep
destinations, history, and schedule rendering feature-owned under
destinations, history, schedule, and thresholds rendering feature-owned under
`frontend-modern/src/features/alerts/tabs/`. New alert tab surfaces should be
extracted as feature modules instead of remaining page-local function blocks,
so the page owns navigation/save orchestration while tab files own their
runtime presentation, tab-local interaction logic, and any history-table
presentation that does not belong in a shared primitive.
presentation or thresholds-table adapter logic that does not belong in a shared
primitive.
Alert filter metadata and grouped header consumers must also preserve the
canonical `agent` and `node` header boundary when reusing shared filter
@@ -224,11 +224,13 @@ The alerts page shell now follows that same page-shell rule for feature tabs:
orchestration, and cross-tab state, while feature-owned tab surfaces such as
`frontend-modern/src/features/alerts/tabs/DestinationsTab.tsx` and
`frontend-modern/src/features/alerts/tabs/HistoryTab.tsx` plus
`frontend-modern/src/features/alerts/tabs/ScheduleTab.tsx` own their tab-local
rendering and interaction logic. Future alert tab cleanup should continue by
extracting page-local tab blocks into feature modules rather than expanding the
top-level page file again, and history-table behavior should stay feature-owned
unless it graduates into a shared primitive used by more than one alert surface.
`frontend-modern/src/features/alerts/tabs/ScheduleTab.tsx` and
`frontend-modern/src/features/alerts/tabs/ThresholdsTab.tsx` own their
tab-local rendering and interaction logic. Future alert tab cleanup should
continue by extracting page-local tab blocks into feature modules rather than
expanding the top-level page file again, and history-table behavior or
thresholds-table adapter logic should stay feature-owned unless it graduates
into a shared primitive used by more than one alert surface.
Top-level settings surfaces must route through `Settings.tsx`,
`SettingsPageShell.tsx`, and
`frontend-modern/src/components/shared/SettingsPanel.tsx` instead of
@@ -0,0 +1,291 @@
import type { Alert, PBSInstance, PMGInstance } from '@/types/api';
import type { Resource } from '@/types/resource';
import type { RawOverrideConfig, BackupAlertConfig, SnapshotAlertConfig, PMGThresholdDefaults } from '@/types/alerts';
import { ThresholdsTable } from '@/components/Alerts/ThresholdsTable';
import type { Override } from '../types';
export interface ThresholdsTabProps {
allGuests: () => Resource[];
pbsInstances: PBSInstance[];
pmgInstances: PMGInstance[];
nodes: Resource[];
agents: Resource[];
storage: Resource[];
dockerHosts: Resource[];
allResources: Resource[];
guestDefaults: () => Record<string, number | undefined>;
nodeDefaults: () => Record<string, number | undefined>;
pbsDefaults: () => Record<string, number | undefined>;
agentDefaults: () => Record<string, number | undefined>;
dockerDefaults: () => {
cpu: number;
memory: number;
disk: number;
restartCount: number;
restartWindow: number;
memoryWarnPct: number;
memoryCriticalPct: number;
serviceWarnGapPercent: number;
serviceCriticalGapPercent: number;
};
dockerDisableConnectivity: () => boolean;
dockerPoweredOffSeverity: () => 'warning' | 'critical';
dockerIgnoredPrefixes: () => string[];
ignoredGuestPrefixes: () => string[];
guestTagWhitelist: () => string[];
guestTagBlacklist: () => string[];
storageDefault: () => number;
timeThresholds: () => {
guest: number;
node: number;
storage: number;
pbs: number;
agent: number;
};
metricTimeThresholds: () => Record<string, Record<string, number>>;
overrides: () => Override[];
rawOverridesConfig: () => Record<string, RawOverrideConfig>;
pmgThresholds: () => PMGThresholdDefaults;
setPMGThresholds: (
value: PMGThresholdDefaults | ((prev: PMGThresholdDefaults) => PMGThresholdDefaults),
) => void;
setGuestDefaults: (
value:
| Record<string, number | undefined>
| ((prev: Record<string, number | undefined>) => Record<string, number | undefined>),
) => void;
guestDisableConnectivity: () => boolean;
setGuestDisableConnectivity: (value: boolean) => void;
guestPoweredOffSeverity: () => 'warning' | 'critical';
setGuestPoweredOffSeverity: (value: 'warning' | 'critical') => void;
setNodeDefaults: (
value:
| Record<string, number | undefined>
| ((prev: Record<string, number | undefined>) => Record<string, number | undefined>),
) => void;
setAgentDefaults: (
value:
| Record<string, number | undefined>
| ((prev: Record<string, number | undefined>) => Record<string, number | undefined>),
) => void;
setPBSDefaults: (
value:
| Record<string, number | undefined>
| ((prev: Record<string, number | undefined>) => Record<string, number | undefined>),
) => void;
setDockerDefaults: (
value:
| {
cpu: number;
memory: number;
disk: number;
restartCount: number;
restartWindow: number;
memoryWarnPct: number;
memoryCriticalPct: number;
serviceWarnGapPercent: number;
serviceCriticalGapPercent: number;
}
| ((prev: {
cpu: number;
memory: number;
disk: number;
restartCount: number;
restartWindow: number;
memoryWarnPct: number;
memoryCriticalPct: number;
serviceWarnGapPercent: number;
serviceCriticalGapPercent: number;
}) => {
cpu: number;
memory: number;
disk: number;
restartCount: number;
restartWindow: number;
memoryWarnPct: number;
memoryCriticalPct: number;
serviceWarnGapPercent: number;
serviceCriticalGapPercent: number;
}),
) => void;
setDockerDisableConnectivity: (value: boolean) => void;
setDockerPoweredOffSeverity: (value: 'warning' | 'critical') => void;
setDockerIgnoredPrefixes: (value: string[] | ((prev: string[]) => string[])) => void;
setIgnoredGuestPrefixes: (value: string[] | ((prev: string[]) => string[])) => void;
setGuestTagWhitelist: (value: string[] | ((prev: string[]) => string[])) => void;
setGuestTagBlacklist: (value: string[] | ((prev: string[]) => string[])) => void;
setStorageDefault: (value: number) => void;
setMetricTimeThresholds: (
value:
| Record<string, Record<string, number>>
| ((prev: Record<string, Record<string, number>>) => Record<string, Record<string, number>>),
) => void;
snapshotDefaults: () => SnapshotAlertConfig;
setSnapshotDefaults: (
value: SnapshotAlertConfig | ((prev: SnapshotAlertConfig) => SnapshotAlertConfig),
) => void;
snapshotFactoryDefaults: SnapshotAlertConfig;
resetSnapshotDefaults: () => void;
backupDefaults: () => BackupAlertConfig;
setBackupDefaults: (
value: BackupAlertConfig | ((prev: BackupAlertConfig) => BackupAlertConfig),
) => void;
backupFactoryDefaults: BackupAlertConfig;
resetBackupDefaults: () => void;
setOverrides: (value: Override[]) => void;
setRawOverridesConfig: (value: Record<string, RawOverrideConfig>) => void;
activeAlerts: Record<string, Alert>;
setHasUnsavedChanges: (value: boolean) => void;
hasUnsavedChanges: () => boolean;
removeAlerts: (predicate: (alert: Alert) => boolean) => void;
disableAllNodes: () => boolean;
setDisableAllNodes: (value: boolean) => void;
disableAllGuests: () => boolean;
setDisableAllGuests: (value: boolean) => void;
disableAllAgents: () => boolean;
setDisableAllAgents: (value: boolean) => void;
disableAllStorage: () => boolean;
setDisableAllStorage: (value: boolean) => void;
disableAllPBS: () => boolean;
setDisableAllPBS: (value: boolean) => void;
disableAllPMG: () => boolean;
setDisableAllPMG: (value: boolean) => void;
disableAllDockerHosts: () => boolean;
setDisableAllDockerHosts: (value: boolean) => void;
disableAllDockerServices: () => boolean;
setDisableAllDockerServices: (value: boolean) => void;
disableAllDockerContainers: () => boolean;
setDisableAllDockerContainers: (value: boolean) => void;
disableAllNodesOffline: () => boolean;
setDisableAllNodesOffline: (value: boolean) => void;
disableAllGuestsOffline: () => boolean;
setDisableAllGuestsOffline: (value: boolean) => void;
disableAllAgentsOffline: () => boolean;
setDisableAllAgentsOffline: (value: boolean) => void;
disableAllPBSOffline: () => boolean;
setDisableAllPBSOffline: (value: boolean) => void;
disableAllPMGOffline: () => boolean;
setDisableAllPMGOffline: (value: boolean) => void;
disableAllDockerHostsOffline: () => boolean;
setDisableAllDockerHostsOffline: (value: boolean) => void;
resetGuestDefaults?: () => void;
resetNodeDefaults?: () => void;
resetPBSDefaults?: () => void;
resetAgentDefaults?: () => void;
resetDockerDefaults?: () => void;
resetDockerIgnoredPrefixes?: () => void;
resetStorageDefault?: () => void;
factoryGuestDefaults?: Record<string, number | undefined>;
factoryNodeDefaults?: Record<string, number | undefined>;
factoryPBSDefaults?: Record<string, number | undefined>;
factoryAgentDefaults?: Record<string, number | undefined>;
factoryDockerDefaults?: Record<string, number | undefined>;
factoryStorageDefault?: number;
}
export function ThresholdsTab(props: ThresholdsTabProps) {
return (
<ThresholdsTable
overrides={props.overrides}
setOverrides={props.setOverrides}
rawOverridesConfig={props.rawOverridesConfig}
setRawOverridesConfig={props.setRawOverridesConfig}
allGuests={props.allGuests}
nodes={props.nodes}
agents={props.agents}
storage={props.storage}
dockerHosts={props.dockerHosts}
allResources={props.allResources}
pbsInstances={props.pbsInstances}
pmgInstances={props.pmgInstances}
pmgThresholds={props.pmgThresholds}
setPMGThresholds={props.setPMGThresholds}
guestDefaults={props.guestDefaults()}
guestDisableConnectivity={props.guestDisableConnectivity}
setGuestDefaults={props.setGuestDefaults}
setGuestDisableConnectivity={props.setGuestDisableConnectivity}
guestPoweredOffSeverity={props.guestPoweredOffSeverity}
setGuestPoweredOffSeverity={props.setGuestPoweredOffSeverity}
nodeDefaults={props.nodeDefaults()}
agentDefaults={props.agentDefaults()}
pbsDefaults={props.pbsDefaults()}
setNodeDefaults={props.setNodeDefaults}
setAgentDefaults={props.setAgentDefaults}
setPBSDefaults={props.setPBSDefaults}
dockerDefaults={props.dockerDefaults()}
dockerDisableConnectivity={props.dockerDisableConnectivity}
dockerPoweredOffSeverity={props.dockerPoweredOffSeverity}
setDockerDefaults={props.setDockerDefaults}
setDockerDisableConnectivity={props.setDockerDisableConnectivity}
setDockerPoweredOffSeverity={props.setDockerPoweredOffSeverity}
dockerIgnoredPrefixes={props.dockerIgnoredPrefixes}
setDockerIgnoredPrefixes={props.setDockerIgnoredPrefixes}
ignoredGuestPrefixes={props.ignoredGuestPrefixes}
setIgnoredGuestPrefixes={props.setIgnoredGuestPrefixes}
guestTagWhitelist={props.guestTagWhitelist}
setGuestTagWhitelist={props.setGuestTagWhitelist}
guestTagBlacklist={props.guestTagBlacklist}
setGuestTagBlacklist={props.setGuestTagBlacklist}
storageDefault={props.storageDefault}
setStorageDefault={props.setStorageDefault}
timeThresholds={props.timeThresholds}
metricTimeThresholds={props.metricTimeThresholds}
setMetricTimeThresholds={props.setMetricTimeThresholds}
backupDefaults={props.backupDefaults}
setBackupDefaults={props.setBackupDefaults}
backupFactoryDefaults={props.backupFactoryDefaults}
resetBackupDefaults={props.resetBackupDefaults}
snapshotDefaults={props.snapshotDefaults}
setSnapshotDefaults={props.setSnapshotDefaults}
snapshotFactoryDefaults={props.snapshotFactoryDefaults}
resetSnapshotDefaults={props.resetSnapshotDefaults}
setHasUnsavedChanges={props.setHasUnsavedChanges}
activeAlerts={props.activeAlerts}
removeAlerts={props.removeAlerts}
disableAllNodes={props.disableAllNodes}
setDisableAllNodes={props.setDisableAllNodes}
disableAllGuests={props.disableAllGuests}
setDisableAllGuests={props.setDisableAllGuests}
disableAllAgents={props.disableAllAgents}
setDisableAllAgents={props.setDisableAllAgents}
disableAllStorage={props.disableAllStorage}
setDisableAllStorage={props.setDisableAllStorage}
disableAllPBS={props.disableAllPBS}
setDisableAllPBS={props.setDisableAllPBS}
disableAllPMG={props.disableAllPMG}
setDisableAllPMG={props.setDisableAllPMG}
disableAllDockerHosts={props.disableAllDockerHosts}
setDisableAllDockerHosts={props.setDisableAllDockerHosts}
disableAllDockerServices={props.disableAllDockerServices}
setDisableAllDockerServices={props.setDisableAllDockerServices}
disableAllDockerContainers={props.disableAllDockerContainers}
setDisableAllDockerContainers={props.setDisableAllDockerContainers}
disableAllNodesOffline={props.disableAllNodesOffline}
setDisableAllNodesOffline={props.setDisableAllNodesOffline}
disableAllGuestsOffline={props.disableAllGuestsOffline}
setDisableAllGuestsOffline={props.setDisableAllGuestsOffline}
disableAllAgentsOffline={props.disableAllAgentsOffline}
setDisableAllAgentsOffline={props.setDisableAllAgentsOffline}
disableAllPBSOffline={props.disableAllPBSOffline}
setDisableAllPBSOffline={props.setDisableAllPBSOffline}
disableAllPMGOffline={props.disableAllPMGOffline}
setDisableAllPMGOffline={props.setDisableAllPMGOffline}
disableAllDockerHostsOffline={props.disableAllDockerHostsOffline}
setDisableAllDockerHostsOffline={props.setDisableAllDockerHostsOffline}
resetGuestDefaults={props.resetGuestDefaults}
resetNodeDefaults={props.resetNodeDefaults}
resetPBSDefaults={props.resetPBSDefaults}
resetAgentDefaults={props.resetAgentDefaults}
resetDockerDefaults={props.resetDockerDefaults}
resetDockerIgnoredPrefixes={props.resetDockerIgnoredPrefixes}
resetStorageDefault={props.resetStorageDefault}
factoryGuestDefaults={props.factoryGuestDefaults}
factoryNodeDefaults={props.factoryNodeDefaults}
factoryPBSDefaults={props.factoryPBSDefaults}
factoryAgentDefaults={props.factoryAgentDefaults}
factoryDockerDefaults={props.factoryDockerDefaults}
factoryStorageDefault={props.factoryStorageDefault}
/>
);
}
+1 -290
View File
@@ -2,7 +2,6 @@ import { createSignal, Show, For, createMemo, createEffect, onMount, onCleanup }
import { useBeforeLeave } from '@solidjs/router';
import type { JSX } from 'solid-js';
import type { Alert } from '@/types/api';
import type { Resource } from '@/types/resource';
import type { RawOverrideConfig, BackupAlertConfig, SnapshotAlertConfig } from '@/types/alerts';
import { AlertsAPI } from '@/api/alerts';
@@ -22,8 +21,6 @@ import { eventBus } from '@/stores/events';
import { notificationStore } from '@/stores/notifications';
import Calendar from 'lucide-solid/icons/calendar';
import { ThresholdsTable } from '@/components/Alerts/ThresholdsTable';
import type { PMGThresholdDefaults } from '@/types/alerts';
import { useWebSocket } from '@/App';
import { useResources } from '@/hooks/useResources';
import { aiChatStore } from '@/stores/aiChat';
@@ -71,6 +68,7 @@ import { OverviewTab } from '@/features/alerts/OverviewTab';
import { DestinationsTab } from '@/features/alerts/tabs/DestinationsTab';
import { HistoryTab } from '@/features/alerts/tabs/HistoryTab';
import { ScheduleTab } from '@/features/alerts/tabs/ScheduleTab';
import { ThresholdsTab } from '@/features/alerts/tabs/ThresholdsTab';
import {
pathForTab,
tabFromPath,
@@ -2037,290 +2035,3 @@ export function Alerts() {
// Overview Tab - Shows current alert status
// Thresholds Tab - Improved design
interface ThresholdsTabProps {
allGuests: () => Resource[];
pbsInstances: PBSInstance[];
pmgInstances: PMGInstance[];
nodes: Resource[];
agents: Resource[];
storage: Resource[];
dockerHosts: Resource[];
allResources: Resource[];
guestDefaults: () => Record<string, number | undefined>;
nodeDefaults: () => Record<string, number | undefined>;
pbsDefaults: () => Record<string, number | undefined>;
agentDefaults: () => Record<string, number | undefined>;
dockerDefaults: () => {
cpu: number;
memory: number;
disk: number;
restartCount: number;
restartWindow: number;
memoryWarnPct: number;
memoryCriticalPct: number;
serviceWarnGapPercent: number;
serviceCriticalGapPercent: number;
};
dockerDisableConnectivity: () => boolean;
dockerPoweredOffSeverity: () => 'warning' | 'critical';
dockerIgnoredPrefixes: () => string[];
ignoredGuestPrefixes: () => string[];
guestTagWhitelist: () => string[];
guestTagBlacklist: () => string[];
storageDefault: () => number;
timeThresholds: () => {
guest: number;
node: number;
storage: number;
pbs: number;
agent: number;
};
metricTimeThresholds: () => Record<string, Record<string, number>>;
overrides: () => Override[];
rawOverridesConfig: () => Record<string, RawOverrideConfig>;
pmgThresholds: () => PMGThresholdDefaults;
setPMGThresholds: (
value: PMGThresholdDefaults | ((prev: PMGThresholdDefaults) => PMGThresholdDefaults),
) => void;
setGuestDefaults: (
value:
| Record<string, number | undefined>
| ((prev: Record<string, number | undefined>) => Record<string, number | undefined>),
) => void;
guestDisableConnectivity: () => boolean;
setGuestDisableConnectivity: (value: boolean) => void;
guestPoweredOffSeverity: () => 'warning' | 'critical';
setGuestPoweredOffSeverity: (value: 'warning' | 'critical') => void;
setNodeDefaults: (
value:
| Record<string, number | undefined>
| ((prev: Record<string, number | undefined>) => Record<string, number | undefined>),
) => void;
setAgentDefaults: (
value:
| Record<string, number | undefined>
| ((prev: Record<string, number | undefined>) => Record<string, number | undefined>),
) => void;
setPBSDefaults: (
value:
| Record<string, number | undefined>
| ((prev: Record<string, number | undefined>) => Record<string, number | undefined>),
) => void;
setDockerDefaults: (
value:
| {
cpu: number;
memory: number;
disk: number;
restartCount: number;
restartWindow: number;
memoryWarnPct: number;
memoryCriticalPct: number;
serviceWarnGapPercent: number;
serviceCriticalGapPercent: number;
}
| ((prev: {
cpu: number;
memory: number;
disk: number;
restartCount: number;
restartWindow: number;
memoryWarnPct: number;
memoryCriticalPct: number;
serviceWarnGapPercent: number;
serviceCriticalGapPercent: number;
}) => {
cpu: number;
memory: number;
disk: number;
restartCount: number;
restartWindow: number;
memoryWarnPct: number;
memoryCriticalPct: number;
serviceWarnGapPercent: number;
serviceCriticalGapPercent: number;
}),
) => void;
setDockerDisableConnectivity: (value: boolean) => void;
setDockerPoweredOffSeverity: (value: 'warning' | 'critical') => void;
setDockerIgnoredPrefixes: (value: string[] | ((prev: string[]) => string[])) => void;
setIgnoredGuestPrefixes: (value: string[] | ((prev: string[]) => string[])) => void;
setGuestTagWhitelist: (value: string[] | ((prev: string[]) => string[])) => void;
setGuestTagBlacklist: (value: string[] | ((prev: string[]) => string[])) => void;
setStorageDefault: (value: number) => void;
setMetricTimeThresholds: (
value:
| Record<string, Record<string, number>>
| ((prev: Record<string, Record<string, number>>) => Record<string, Record<string, number>>),
) => void;
snapshotDefaults: () => SnapshotAlertConfig;
setSnapshotDefaults: (
value: SnapshotAlertConfig | ((prev: SnapshotAlertConfig) => SnapshotAlertConfig),
) => void;
snapshotFactoryDefaults: SnapshotAlertConfig;
resetSnapshotDefaults: () => void;
backupDefaults: () => BackupAlertConfig;
setBackupDefaults: (
value: BackupAlertConfig | ((prev: BackupAlertConfig) => BackupAlertConfig),
) => void;
backupFactoryDefaults: BackupAlertConfig;
resetBackupDefaults: () => void;
setOverrides: (value: Override[]) => void;
setRawOverridesConfig: (value: Record<string, RawOverrideConfig>) => void;
activeAlerts: Record<string, Alert>;
setHasUnsavedChanges: (value: boolean) => void;
hasUnsavedChanges: () => boolean;
removeAlerts: (predicate: (alert: Alert) => boolean) => void;
// Global disable flags
disableAllNodes: () => boolean;
setDisableAllNodes: (value: boolean) => void;
disableAllGuests: () => boolean;
setDisableAllGuests: (value: boolean) => void;
disableAllAgents: () => boolean;
setDisableAllAgents: (value: boolean) => void;
disableAllStorage: () => boolean;
setDisableAllStorage: (value: boolean) => void;
disableAllPBS: () => boolean;
setDisableAllPBS: (value: boolean) => void;
disableAllPMG: () => boolean;
setDisableAllPMG: (value: boolean) => void;
disableAllDockerHosts: () => boolean;
setDisableAllDockerHosts: (value: boolean) => void;
disableAllDockerServices: () => boolean;
setDisableAllDockerServices: (value: boolean) => void;
disableAllDockerContainers: () => boolean;
setDisableAllDockerContainers: (value: boolean) => void;
// Global disable offline alerts flags
disableAllNodesOffline: () => boolean;
setDisableAllNodesOffline: (value: boolean) => void;
disableAllGuestsOffline: () => boolean;
setDisableAllGuestsOffline: (value: boolean) => void;
disableAllAgentsOffline: () => boolean;
setDisableAllAgentsOffline: (value: boolean) => void;
disableAllPBSOffline: () => boolean;
setDisableAllPBSOffline: (value: boolean) => void;
disableAllPMGOffline: () => boolean;
setDisableAllPMGOffline: (value: boolean) => void;
disableAllDockerHostsOffline: () => boolean;
setDisableAllDockerHostsOffline: (value: boolean) => void;
// Reset functions and factory defaults
resetGuestDefaults?: () => void;
resetNodeDefaults?: () => void;
resetPBSDefaults?: () => void;
resetAgentDefaults?: () => void;
resetDockerDefaults?: () => void;
resetDockerIgnoredPrefixes?: () => void;
resetStorageDefault?: () => void;
factoryGuestDefaults?: Record<string, number | undefined>;
factoryNodeDefaults?: Record<string, number | undefined>;
factoryPBSDefaults?: Record<string, number | undefined>;
factoryAgentDefaults?: Record<string, number | undefined>;
factoryDockerDefaults?: Record<string, number | undefined>;
factoryStorageDefault?: number;
}
function ThresholdsTab(props: ThresholdsTabProps) {
return (
<ThresholdsTable
overrides={props.overrides}
setOverrides={props.setOverrides}
rawOverridesConfig={props.rawOverridesConfig}
setRawOverridesConfig={props.setRawOverridesConfig}
allGuests={props.allGuests}
nodes={props.nodes}
agents={props.agents}
storage={props.storage}
dockerHosts={props.dockerHosts}
allResources={props.allResources}
pbsInstances={props.pbsInstances}
pmgInstances={props.pmgInstances}
pmgThresholds={props.pmgThresholds}
setPMGThresholds={props.setPMGThresholds}
guestDefaults={props.guestDefaults()}
guestDisableConnectivity={props.guestDisableConnectivity}
setGuestDefaults={props.setGuestDefaults}
setGuestDisableConnectivity={props.setGuestDisableConnectivity}
guestPoweredOffSeverity={props.guestPoweredOffSeverity}
setGuestPoweredOffSeverity={props.setGuestPoweredOffSeverity}
nodeDefaults={props.nodeDefaults()}
agentDefaults={props.agentDefaults()}
pbsDefaults={props.pbsDefaults()}
setNodeDefaults={props.setNodeDefaults}
setAgentDefaults={props.setAgentDefaults}
setPBSDefaults={props.setPBSDefaults}
dockerDefaults={props.dockerDefaults()}
dockerDisableConnectivity={props.dockerDisableConnectivity}
dockerPoweredOffSeverity={props.dockerPoweredOffSeverity}
setDockerDefaults={props.setDockerDefaults}
setDockerDisableConnectivity={props.setDockerDisableConnectivity}
setDockerPoweredOffSeverity={props.setDockerPoweredOffSeverity}
dockerIgnoredPrefixes={props.dockerIgnoredPrefixes}
setDockerIgnoredPrefixes={props.setDockerIgnoredPrefixes}
ignoredGuestPrefixes={props.ignoredGuestPrefixes}
setIgnoredGuestPrefixes={props.setIgnoredGuestPrefixes}
guestTagWhitelist={props.guestTagWhitelist}
setGuestTagWhitelist={props.setGuestTagWhitelist}
guestTagBlacklist={props.guestTagBlacklist}
setGuestTagBlacklist={props.setGuestTagBlacklist}
storageDefault={props.storageDefault}
setStorageDefault={props.setStorageDefault}
timeThresholds={props.timeThresholds}
metricTimeThresholds={props.metricTimeThresholds}
setMetricTimeThresholds={props.setMetricTimeThresholds}
backupDefaults={props.backupDefaults}
setBackupDefaults={props.setBackupDefaults}
backupFactoryDefaults={props.backupFactoryDefaults}
resetBackupDefaults={props.resetBackupDefaults}
snapshotDefaults={props.snapshotDefaults}
setSnapshotDefaults={props.setSnapshotDefaults}
snapshotFactoryDefaults={props.snapshotFactoryDefaults}
resetSnapshotDefaults={props.resetSnapshotDefaults}
setHasUnsavedChanges={props.setHasUnsavedChanges}
activeAlerts={props.activeAlerts}
removeAlerts={props.removeAlerts}
disableAllNodes={props.disableAllNodes}
setDisableAllNodes={props.setDisableAllNodes}
disableAllGuests={props.disableAllGuests}
setDisableAllGuests={props.setDisableAllGuests}
disableAllAgents={props.disableAllAgents}
setDisableAllAgents={props.setDisableAllAgents}
disableAllStorage={props.disableAllStorage}
setDisableAllStorage={props.setDisableAllStorage}
disableAllPBS={props.disableAllPBS}
setDisableAllPBS={props.setDisableAllPBS}
disableAllPMG={props.disableAllPMG}
setDisableAllPMG={props.setDisableAllPMG}
disableAllDockerHosts={props.disableAllDockerHosts}
setDisableAllDockerHosts={props.setDisableAllDockerHosts}
disableAllDockerServices={props.disableAllDockerServices}
setDisableAllDockerServices={props.setDisableAllDockerServices}
disableAllDockerContainers={props.disableAllDockerContainers}
setDisableAllDockerContainers={props.setDisableAllDockerContainers}
disableAllNodesOffline={props.disableAllNodesOffline}
setDisableAllNodesOffline={props.setDisableAllNodesOffline}
disableAllGuestsOffline={props.disableAllGuestsOffline}
setDisableAllGuestsOffline={props.setDisableAllGuestsOffline}
disableAllAgentsOffline={props.disableAllAgentsOffline}
setDisableAllAgentsOffline={props.setDisableAllAgentsOffline}
disableAllPBSOffline={props.disableAllPBSOffline}
setDisableAllPBSOffline={props.setDisableAllPBSOffline}
disableAllPMGOffline={props.disableAllPMGOffline}
setDisableAllPMGOffline={props.setDisableAllPMGOffline}
disableAllDockerHostsOffline={props.disableAllDockerHostsOffline}
setDisableAllDockerHostsOffline={props.setDisableAllDockerHostsOffline}
resetGuestDefaults={props.resetGuestDefaults}
resetNodeDefaults={props.resetNodeDefaults}
resetPBSDefaults={props.resetPBSDefaults}
resetAgentDefaults={props.resetAgentDefaults}
resetDockerDefaults={props.resetDockerDefaults}
resetDockerIgnoredPrefixes={props.resetDockerIgnoredPrefixes}
resetStorageDefault={props.resetStorageDefault}
factoryGuestDefaults={props.factoryGuestDefaults}
factoryNodeDefaults={props.factoryNodeDefaults}
factoryPBSDefaults={props.factoryPBSDefaults}
factoryAgentDefaults={props.factoryAgentDefaults}
factoryDockerDefaults={props.factoryDockerDefaults}
factoryStorageDefault={props.factoryStorageDefault}
/>
);
}
@@ -3,6 +3,7 @@ import alertsPageSource from '@/pages/Alerts.tsx?raw';
import alertDestinationsTabSource from '@/features/alerts/tabs/DestinationsTab.tsx?raw';
import alertHistoryTabSource from '@/features/alerts/tabs/HistoryTab.tsx?raw';
import alertScheduleTabSource from '@/features/alerts/tabs/ScheduleTab.tsx?raw';
import alertThresholdsTabSource from '@/features/alerts/tabs/ThresholdsTab.tsx?raw';
import {
ALERT_TAB_SEGMENTS,
@@ -153,7 +154,7 @@ describe('tab path helpers', () => {
expect(tabFromPath('/alerts/summary', custom)).toBe('overview');
});
it('keeps destinations, history, and schedule tabs feature-owned', () => {
it('keeps destinations, history, schedule, and thresholds tabs feature-owned', () => {
expect(alertsPageSource).toContain(
"import { DestinationsTab } from '@/features/alerts/tabs/DestinationsTab';",
);
@@ -163,13 +164,18 @@ describe('tab path helpers', () => {
expect(alertsPageSource).toContain(
"import { ScheduleTab } from '@/features/alerts/tabs/ScheduleTab';",
);
expect(alertsPageSource).toContain(
"import { ThresholdsTab } from '@/features/alerts/tabs/ThresholdsTab';",
);
expect(alertsPageSource).not.toContain('function DestinationsTab(');
expect(alertsPageSource).not.toContain('function HistoryTab(');
expect(alertsPageSource).not.toContain('function ScheduleTab(');
expect(alertsPageSource).not.toContain('function ThresholdsTab(');
expect(alertDestinationsTabSource).toContain('NotificationsAPI.getWebhooks');
expect(alertHistoryTabSource).toContain('AlertsAPI.getHistory');
expect(alertHistoryTabSource).toContain('IncidentTimelinePanel');
expect(alertScheduleTabSource).toContain('getAlertConfigQuietHourSuppressOptions');
expect(alertThresholdsTabSource).toContain('ThresholdsTable');
});
});
@@ -226,6 +226,7 @@ import alertOverviewTabSource from '@/features/alerts/OverviewTab.tsx?raw';
import alertDestinationsTabSource from '@/features/alerts/tabs/DestinationsTab.tsx?raw';
import alertHistoryTabSource from '@/features/alerts/tabs/HistoryTab.tsx?raw';
import alertScheduleTabSource from '@/features/alerts/tabs/ScheduleTab.tsx?raw';
import alertThresholdsTabSource from '@/features/alerts/tabs/ThresholdsTab.tsx?raw';
import alertIncidentPresentationSource from '@/utils/alertIncidentPresentation.ts?raw';
import alertHistoryPresentationSource from '@/utils/alertHistoryPresentation.ts?raw';
import bulkEditDialogSource from '@/components/Alerts/BulkEditDialog.tsx?raw';
@@ -2248,6 +2249,11 @@ describe('frontend resource type boundaries', () => {
expect(alertsPageSource).toContain('getAlertsMobileTabClass');
expect(alertsPageSource).toContain('getAlertsTabTitle');
expect(alertsPageSource).toContain('getAlertsTabGroups');
expect(alertsPageSource).toContain("import { ThresholdsTab } from '@/features/alerts/tabs/ThresholdsTab';");
expect(alertsPageSource).not.toContain("import { ThresholdsTable } from '@/components/Alerts/ThresholdsTable';");
expect(alertsPageSource).not.toContain('function ThresholdsTab(');
expect(alertThresholdsTabSource).toContain("import { ThresholdsTable } from '@/components/Alerts/ThresholdsTable';");
expect(alertThresholdsTabSource).toContain('pmgThresholds={props.pmgThresholds}');
expect(alertScheduleTabSource).toContain('getAlertGroupingCardClass');
expect(alertScheduleTabSource).toContain('getAlertGroupingCheckboxClass');
expect(alertScheduleTabSource).toContain('getAlertQuietDayButtonClass');