You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Highlight fields (Status / Health / Budget / End Date / Account) can't be inline-edited. Root cause (confirmed in code): `record:highlights` (→ `HeaderHighlight`) is a separate, read-only page block that registers its field names into `HighlightFieldsContext`; `record:details` dedupes those fields out of the editable body. Inline-edit state (`isInlineEditing` / `editedValues`) lives inside `DetailView` (a child of `record:details`), so the sibling highlights block can't reach it. Net: entering inline edit only makes body fields editable; the most edit-worthy fields (highlights) stay read-only.
Goal
Lift inline edit into a record-level shared mode so the highlights strip and the details body share ONE edit session + ONE atomic, cross-field-validated Save. Fixes (2), honors (1). Long-term: inline edit becomes a reusable record-level primitive (any `record:*` block can opt in), not `DetailView`-private state.
Design
New primitives
`InlineEditContext` (@object-ui/react) — a separate context (mirrors `HighlightFieldsContext` so edit-draft churn doesn't re-render every `record:*` consumer). Pure UI state: `editing, canEdit, draft, autoFocusField, saving, error, enter(field?), setField, cancel, reset`. Export `InlineEditProvider` + `useInlineEdit()`.
`` (plugin-detail) — record-level sticky Save/Cancel bar + atomic save + OCC. On Save: one `dataSource.update(obj, id, draft, { ifMatch: data.updated_at })` → `refresh()` → reset. On 409 → reuse `ConcurrentUpdateDialog`. `draft` holds only user-edited keys → computed/read-only never sent.
Wiring
`RecordDetailView` (app-shell): wrap page content in `` inside `RecordContextProvider` (around the highlights+details SchemaRenderer) + render ``.
`record-highlights` / `HeaderHighlight`: when `editing`, render `` (value = `draft[name] ?? data[name]`, write via `setField`), pencil/double-click `enter(field)`, computed/readonly + `canEdit` gate, don't hide empty while editing.
`record-details` / `DetailView` / `DetailSection`: DetailView consumes `InlineEditContext` instead of local state; drop its Block B bar + batch save. Keep the highlight↔body dedup.
Standalone `DetailView` (drawer / direct usage, e.g. `RecordDetailDrawer`): DetailView always consumes `InlineEditContext`; standalone hosts get a local `` + `` wrapper (no dual-mode branching inside DetailView). This is the main regression surface.
Phasing
P1 — lift + atomic save (plumbing). Add `InlineEditContext`; move DetailView (page + standalone) onto it; add `` with the single atomic OCC save; delete DetailView's local batch save. Highlights stay read-only. Isolates the riskiest change (DetailView rewire + save semantics).
P2 — editable highlights. Extract ``; make `HeaderHighlight` editable against the shared draft; pencil/double-click on highlight fields. Includes compact-layout UX (a select/lookup/date editor in a narrow highlight column — design expand-on-edit / popover, Salesforce-style).
Cost: ~7–9 files incl. a foundational shared context + extracting the most complex part of `DetailSection` + a new save bar.
Risk: (1) `DetailView` is multi-use — rewiring its state ownership is the Implement visual designer for Object UI schemas #1 regression risk; (2) save semantics change (per-field loop → one atomic write) interacts with backend validation / computed recompute / OCC-conflict UX; (3) editable highlights in a compact strip = layout/UX polish risk.
Mitigation: the P1/P2 split isolates the risky plumbing from the visible feature; each phase independently verified.
Acceptance criteria
P1
`InlineEditContext` / `InlineEditProvider` / `useInlineEdit` exported from @object-ui/react.
Double-click / pencil on a body field enters edit via the shared context; one record-level Save/Cancel bar.
Save issues exactly ONE `update` with only edited fields; 409 → ConcurrentUpdateDialog.
Standalone DetailView (drawer) still edits + saves.
Existing inline-edit tests pass; new tests for atomic save + standalone.
P2
Hover/double-click a highlight field (Status/Budget/…) enters the same record edit session, editable in place.
Highlight + body edits commit together in ONE Save.
Computed/readonly highlight fields expose no editor.
Compact-layout editor is legible.
Verification
Unit: InlineFieldInput parity; editable highlights; computed/readonly gate; atomic-save assembles one update from `draft`; standalone DetailView.
Browser (:5181, showcase Project): double-click a highlight (Status/Budget) AND a body field → single Save → both persist; Cancel restores; confirm one PATCH carrying only edited fields.
Reuse (don't reinvent)
`HighlightFieldsContext` pattern (RecordContext.tsx); `ConcurrentUpdateDialog` + `isConcurrentUpdateError`; sticky-bar chrome from `DraftPreviewBar.tsx` / `RuntimeDraftBar.tsx`; the update/updateOne/patch + `ifMatch` fallback in `record-details.tsx`.
Follow-up to #2402 (Edit-as-primary CTA + double-click inline edit, merged). Delivered as one issue, two phases.
Problem
Goal
Lift inline edit into a record-level shared mode so the highlights strip and the details body share ONE edit session + ONE atomic, cross-field-validated Save. Fixes (2), honors (1). Long-term: inline edit becomes a reusable record-level primitive (any `record:*` block can opt in), not `DetailView`-private state.
Design
New primitives
Wiring
Standalone `DetailView` (drawer / direct usage, e.g. `RecordDetailDrawer`): DetailView always consumes `InlineEditContext`; standalone hosts get a local `` + `` wrapper (no dual-mode branching inside DetailView). This is the main regression surface.
Phasing
Each phase is its own PR.
Guardrails preserved
Computed (`formula`/`summary`/`rollup`/`auto_number`) + `readonly` non-editable; `affordances.edit` object-lifecycle gate (via `canEdit`); approval lock; OCC (`ifMatch` + `ConcurrentUpdateDialog`); atomic partial update never writes computed/read-only fields; FLS/permission field filtering unchanged.
Cost & risk
Acceptance criteria
P1
P2
Verification
Reuse (don't reinvent)
`HighlightFieldsContext` pattern (RecordContext.tsx); `ConcurrentUpdateDialog` + `isConcurrentUpdateError`; sticky-bar chrome from `DraftPreviewBar.tsx` / `RuntimeDraftBar.tsx`; the update/updateOne/patch + `ifMatch` fallback in `record-details.tsx`.