diff --git a/ui/src/pages/AppsTab/AppDeploymentPage/hooks/useDeploymentPageState.ts b/ui/src/pages/AppsTab/AppDeploymentPage/hooks/useDeploymentPageState.ts index a570de1a..2a4eb6a4 100644 --- a/ui/src/pages/AppsTab/AppDeploymentPage/hooks/useDeploymentPageState.ts +++ b/ui/src/pages/AppsTab/AppDeploymentPage/hooks/useDeploymentPageState.ts @@ -97,7 +97,7 @@ export function useDeploymentPageState( metricsEnabled: agentConfig?.metricsEnabled ?? defaultForm.monitoring.metricsEnabled, metricsInterval: defaultForm.monitoring.metricsInterval, samplingRate: agentConfig?.samplingRate !== undefined - ? (Number.isInteger(agentConfig.samplingRate) ? `${agentConfig.samplingRate}.0` : String(agentConfig.samplingRate)) + ? String(agentConfig.samplingRate) : defaultForm.monitoring.samplingRate, compressSuccess: agentConfig?.compressSuccess ?? defaultForm.monitoring.compressSuccess, replayEnabled: defaultForm.monitoring.replayEnabled, diff --git a/ui/src/pages/AppsTab/AppDeploymentPage/hooks/useFormDirty.ts b/ui/src/pages/AppsTab/AppDeploymentPage/hooks/useFormDirty.ts index 0e8fbb77..ce512fa5 100644 --- a/ui/src/pages/AppsTab/AppDeploymentPage/hooks/useFormDirty.ts +++ b/ui/src/pages/AppsTab/AppDeploymentPage/hooks/useFormDirty.ts @@ -1,5 +1,5 @@ import { useMemo } from 'react'; -import type { DeploymentPageFormState } from './useDeploymentPageState'; +import type { DeploymentPageFormState, MonitoringFormState } from './useDeploymentPageState'; export interface PerTabDirty { monitoring: boolean; @@ -9,13 +9,22 @@ export interface PerTabDirty { anyLocalEdit: boolean; } +// Normalize free-text numeric fields (user types "1.0" / "1" / "1.00" — all equal). +// NaN compares as NaN through JSON, which is harmless since both sides coerce the same. +function normalizeMonitoring(m: MonitoringFormState): Omit & { samplingRate: number } { + const { samplingRate, ...rest } = m; + return { ...rest, samplingRate: parseFloat(samplingRate) }; +} + export function useFormDirty( form: DeploymentPageFormState, serverState: DeploymentPageFormState, stagedJar: File | null, ): PerTabDirty { return useMemo(() => { - const monitoring = JSON.stringify(form.monitoring) !== JSON.stringify(serverState.monitoring); + const monitoring = + JSON.stringify(normalizeMonitoring(form.monitoring)) !== + JSON.stringify(normalizeMonitoring(serverState.monitoring)); const resources = JSON.stringify(form.resources) !== JSON.stringify(serverState.resources); const variables = JSON.stringify(form.variables) !== JSON.stringify(serverState.variables); const sensitiveKeys = JSON.stringify(form.sensitiveKeys) !== JSON.stringify(serverState.sensitiveKeys);