From ec8995d41e3e15c609c8e84442948b72d0032aa7 Mon Sep 17 00:00:00 2001 From: Dmitrii Iurco Date: Tue, 9 Jun 2026 16:17:51 -0400 Subject: [PATCH] fix: Cell Identity changes now show Configuration changes pending banner DraftConfig dirty state (set when any Cell Identity field changes) was tracked in refs but never checked by the banner, which only looked at backend pending state. Cell name changes in pic_ngo mode intentionally block auto-save (to prevent premature DDNS re-registration), so the backend never marked pending and the banner never appeared. Fix: show the banner when hasDirty() is true in addition to backend pending. Add clearAllDirty() to DraftConfigContext so Cancel immediately clears frontend dirty state without waiting for the next 5-second poll. Co-Authored-By: Claude Sonnet 4.6 --- webui/src/App.jsx | 7 ++++--- webui/src/contexts/DraftConfigContext.jsx | 6 +++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/webui/src/App.jsx b/webui/src/App.jsx index beba622..be5dffe 100644 --- a/webui/src/App.jsx +++ b/webui/src/App.jsx @@ -188,7 +188,7 @@ function AppCore() { const [applyStatus, setApplyStatus] = useState(null); // null | 'saving' | 'restarting' | 'done' | 'timeout' | 'error' const [applyError, setApplyError] = useState(''); - const { flushAll, hasDirty } = useDraftConfig(); + const { flushAll, hasDirty, clearAllDirty } = useDraftConfig(); const handleApply = useCallback(async () => { setApplyError(''); @@ -231,10 +231,11 @@ function AppCore() { }, [flushAll, hasDirty]); const handleCancel = useCallback(async () => { + clearAllDirty(); await cellAPI.cancelPending(); setPending({ needs_restart: false, changes: [] }); window.dispatchEvent(new CustomEvent('pic-config-discarded')); - }, []); + }, [clearAllDirty]); const [activeServiceChildren, setActiveServiceChildren] = useState([]); @@ -327,7 +328,7 @@ function AppCore() { )} - {isOnline && pending.needs_restart && !applyStatus && ( + {isOnline && (pending.needs_restart || hasDirty()) && !applyStatus && ( )} diff --git a/webui/src/contexts/DraftConfigContext.jsx b/webui/src/contexts/DraftConfigContext.jsx index 10955c0..e2f1e10 100644 --- a/webui/src/contexts/DraftConfigContext.jsx +++ b/webui/src/contexts/DraftConfigContext.jsx @@ -25,8 +25,12 @@ export function DraftConfigProvider({ children }) { await Promise.all(flushers.map(fn => fn())); }, []); + const clearAllDirty = useCallback(() => { + hasDirtyRef.current = {}; + }, []); + return ( - + {children} );