From 72b3f5c4c1c217bb3c527de85972d04112a779bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Weberru=C3=9F?= Date: Fri, 16 Oct 2026 22:03:25 +0000 Subject: [PATCH] fix(configurator): preserve editor input and latest saved list Do not remount the editor during the initial guest-to-known-session lookup. Continue to reset the draft and scoped catalogue provider on actual identity/workspace changes. Prevent obsolete initial list responses and errors from overwriting a post-save refresh. Deterministically reproduce both orderings in the existing save/reopen/revision/delete browser journey, including stable focused-input identity. Preserve all original assertions; no retries or timeout increases. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../web/src/components/Configurations.tsx | 13 ++- .../app/apps/web/src/main.tsx | 6 +- .../app/e2e/configurator.spec.ts | 81 ++++++++++++++++--- landing-zone-configurator/docs/development.md | 10 +++ 4 files changed, 92 insertions(+), 18 deletions(-) diff --git a/landing-zone-configurator/app/apps/web/src/components/Configurations.tsx b/landing-zone-configurator/app/apps/web/src/components/Configurations.tsx index ff96535..1f74f4e 100644 --- a/landing-zone-configurator/app/apps/web/src/components/Configurations.tsx +++ b/landing-zone-configurator/app/apps/web/src/components/Configurations.tsx @@ -99,6 +99,7 @@ export function Configurations({ > | null>(null); const active = useRef(false); const controller = useRef(null); + const listRequest = useRef(0); useEffect(() => { if (!session) return; @@ -118,14 +119,16 @@ export function Configurations({ ); }) .catch(() => {}); + const request = ++listRequest.current; void fetch("/api/v1/configurations", { signal: lifetime.signal }) .then(checked) .then((response) => response.json()) .then((body) => { - if (!lifetime.signal.aborted) setConfigurations(body.configurations); + if (!lifetime.signal.aborted && request === listRequest.current) + setConfigurations(body.configurations); }) .catch(() => { - if (!lifetime.signal.aborted) + if (!lifetime.signal.aborted && request === listRequest.current) setError( "Konfigurationen konnten nicht geladen werden. Bitte aktualisieren.", ); @@ -177,13 +180,15 @@ export function Configurations({ }, [session, compact]); async function refresh() { + const request = ++listRequest.current; + const signal = controller.current?.signal ?? null; const response = await checked( await fetch("/api/v1/configurations", { - signal: controller.current?.signal ?? null, + signal, }), ); const body = await response.json(); - if (!controller.current?.signal.aborted) + if (!signal?.aborted && request === listRequest.current) setConfigurations(body.configurations); } diff --git a/landing-zone-configurator/app/apps/web/src/main.tsx b/landing-zone-configurator/app/apps/web/src/main.tsx index 984914b..42b1f82 100644 --- a/landing-zone-configurator/app/apps/web/src/main.tsx +++ b/landing-zone-configurator/app/apps/web/src/main.tsx @@ -88,6 +88,7 @@ function App() { setDeploymentSelection(null); }, [session?.user.id, session?.user.login, session?.tenant?.id]); const [draftEpoch, setDraftEpoch] = useState(0); + const [workspaceEpoch, setWorkspaceEpoch] = useState(0); const [configurationBinding, setConfigurationBinding] = useState(null); const [draft, setDraft] = useState(restoredDraft); @@ -115,6 +116,7 @@ function App() { setDraft(null); setConfigurationBinding(null); setSavedDraft(null); + setWorkspaceEpoch((value) => value + 1); } activeAccount.current = key; setSession(next); @@ -673,9 +675,7 @@ function App() { /> )} {platformAccess && ( - +