fix(deploy): redeploy button after save, disable save when clean, success toast

- Bug 1: default serverDirtyAgainstDeploy to true (not false) while
  dirtyState query is loading — prevents the button showing 'Save'
  instead of 'Redeploy' on apps with no successful deployment yet.
- Bug 2: normalize samplingRate from server as '<n>.0' when the value
  is a whole-number float so serverState matches form after save,
  eliminating spurious dirty detection that kept Save enabled.
- Bug 3: add success toast after handleSave completes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-23 00:06:00 +02:00
parent b7b6bd2a96
commit 0a71bca7b8
2 changed files with 6 additions and 2 deletions

View File

@@ -96,7 +96,9 @@ export function useDeploymentPageState(
agentLogLevel: (agentConfig?.agentLogLevel as string) ?? defaultForm.monitoring.agentLogLevel, agentLogLevel: (agentConfig?.agentLogLevel as string) ?? defaultForm.monitoring.agentLogLevel,
metricsEnabled: agentConfig?.metricsEnabled ?? defaultForm.monitoring.metricsEnabled, metricsEnabled: agentConfig?.metricsEnabled ?? defaultForm.monitoring.metricsEnabled,
metricsInterval: defaultForm.monitoring.metricsInterval, metricsInterval: defaultForm.monitoring.metricsInterval,
samplingRate: agentConfig?.samplingRate !== undefined ? String(agentConfig.samplingRate) : defaultForm.monitoring.samplingRate, samplingRate: agentConfig?.samplingRate !== undefined
? (Number.isInteger(agentConfig.samplingRate) ? `${agentConfig.samplingRate}.0` : String(agentConfig.samplingRate))
: defaultForm.monitoring.samplingRate,
compressSuccess: agentConfig?.compressSuccess ?? defaultForm.monitoring.compressSuccess, compressSuccess: agentConfig?.compressSuccess ?? defaultForm.monitoring.compressSuccess,
replayEnabled: defaultForm.monitoring.replayEnabled, replayEnabled: defaultForm.monitoring.replayEnabled,
routeControlEnabled: defaultForm.monitoring.routeControlEnabled, routeControlEnabled: defaultForm.monitoring.routeControlEnabled,

View File

@@ -113,7 +113,7 @@ export default function AppDeploymentPage() {
const dirty = useFormDirty(form, serverState, stagedJar); const dirty = useFormDirty(form, serverState, stagedJar);
const { dialogOpen: blockerOpen, confirm: blockerConfirm, cancel: blockerCancel } = const { dialogOpen: blockerOpen, confirm: blockerConfirm, cancel: blockerCancel } =
useUnsavedChangesBlocker(dirty.anyLocalEdit); useUnsavedChangesBlocker(dirty.anyLocalEdit);
const serverDirtyAgainstDeploy = dirtyState?.dirty ?? false; const serverDirtyAgainstDeploy = dirtyState?.dirty ?? true;
const deploymentInProgress = !!activeDeployment; const deploymentInProgress = !!activeDeployment;
const primaryMode = computeMode({ const primaryMode = computeMode({
deploymentInProgress, deploymentInProgress,
@@ -220,6 +220,8 @@ export default function AppDeploymentPage() {
setStagedJar(null); setStagedJar(null);
toast({ title: 'Configuration saved', variant: 'success' });
// Invalidate dirty-state so the button reflects the new saved state // Invalidate dirty-state so the button reflects the new saved state
await queryClient.invalidateQueries({ queryKey: ['apps', envSlug, targetApp.slug, 'dirty-state'] }); await queryClient.invalidateQueries({ queryKey: ['apps', envSlug, targetApp.slug, 'dirty-state'] });