Skip to content

Commit 94ef99e

Browse files
xuyushun441-sysos-zhuangclaude
authored
fix(app-shell): merge draft overlay over effective baseline (preserve inherited fields) (#1720)
A pending draft overlay can carry only edited fields; using it wholesale dropped inherited fields like `type` that section visibleOn predicates depend on (ADR-0047 list-page section hiding). Merge draft over the effective baseline at all three draft-init sites. NOTE: robustness improvement. NOT confirmed to fix the observed live symptom (list-page editor rendering a stale pre-#25 form) — that has a separate client-side stale-form cause still under investigation. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 053c948 commit 94ef99e

1 file changed

Lines changed: 23 additions & 6 deletions

File tree

packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -549,10 +549,16 @@ function MetadataResourceEditPageImpl({
549549
// Prefer the pending draft as the editing baseline — the
550550
// operator is mid-flight on this item and should see their
551551
// own in-progress state, not the last published version.
552-
const rawInitial = (draftReal
553-
?? lay.effective
554-
?? lay.code
555-
?? {}) as Record<string, unknown>;
552+
// A pending draft overlay can carry only the edited fields, so using
553+
// it wholesale would drop inherited fields that were never touched —
554+
// notably `type`, which section-level `visibleOn` predicates depend on
555+
// (ADR-0047 hides Data Context / Layout when `data.type == 'list'`).
556+
// Merge the draft over the effective baseline so those fields survive;
557+
// the draft still wins for anything it does carry.
558+
const baseline = (lay.effective ?? lay.code ?? {}) as Record<string, unknown>;
559+
const rawInitial: Record<string, unknown> = draftReal
560+
? { ...baseline, ...(draftReal as Record<string, unknown>) }
561+
: baseline;
556562
// Normalise the wire shape into the editor's draft shape (e.g.
557563
// `view` unwraps an expanded ViewItem's `config` into a
558564
// `{ list | form }` family key). No-op for types without a hook.
@@ -903,7 +909,12 @@ function MetadataResourceEditPageImpl({
903909
setLayered(lay);
904910
const draftReal = extractDraftBody(draftResp);
905911
setHasDraft(!!draftReal);
906-
const rawFresh = (draftReal ?? lay.effective ?? itemToSave) as Record<string, unknown>;
912+
// Merge the draft over the effective baseline (see the load effect):
913+
// a partial draft overlay must not drop inherited fields like `type`.
914+
const freshBaseline = (lay.effective ?? itemToSave) as Record<string, unknown>;
915+
const rawFresh: Record<string, unknown> = draftReal
916+
? { ...freshBaseline, ...(draftReal as Record<string, unknown>) }
917+
: freshBaseline;
907918
// Re-normalise the refreshed wire shape so the editor keeps showing
908919
// the canonical draft shape after a save (e.g. the backend re-expands
909920
// a view into the ViewItem `config` wrapper).
@@ -1020,7 +1031,13 @@ function MetadataResourceEditPageImpl({
10201031
setLayered(lay);
10211032
const draftReal = extractDraftBody(draftResp);
10221033
setHasDraft(!!draftReal);
1023-
const fresh = (draftReal ?? lay.effective ?? draft) as Record<string, unknown>;
1034+
// Merge the draft over the effective baseline so a partial draft overlay
1035+
// doesn't drop inherited fields like `type` (section visibleOn depends
1036+
// on it — ADR-0047).
1037+
const freshBaseline = (lay.effective ?? draft) as Record<string, unknown>;
1038+
const fresh: Record<string, unknown> = draftReal
1039+
? { ...freshBaseline, ...(draftReal as Record<string, unknown>) }
1040+
: freshBaseline;
10241041
setDraft(fresh);
10251042
draftSnapshotRef.current = fresh;
10261043
} catch (err: any) {

0 commit comments

Comments
 (0)