Skip to content

Commit 6046927

Browse files
os-zhuangclaude
andauthored
fix(app-shell): Studio UX hardening — object nav = runtime grid, discoverable add-field (#2070)
Deep-test pass on the Studio surface surfaced two issues, both fixed: 1. Interfaces object nav leaf rendered the object field-form preview (getMetadataPreview('object')) instead of the records grid — inconsistent with the Data pillar and the running app, and it spread object metadata (pluralLabel/isSystem/active/abstract) onto DOM nodes (React warnings). Now object leaves render the object-view records grid (preview = runtime), are excluded from `isEditable` (no stray draft/save), and show a hint that schema editing lives in the Data pillar. Removes the console warnings. 2. The grid's trailing "+" add-field affordance is off-screen-right for wide objects (hard to discover). Added a visible "+ 添加字段" button to the Data pillar header (next to the field count) as a second entry point to the same form. Verified live: Interfaces Projects/Tasks now show the records grid (no prop warnings after clearing the console); the Data header button opens the add-field form. eslint 0 / tsc 0. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 96b1293 commit 6046927

1 file changed

Lines changed: 23 additions & 5 deletions

File tree

packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
Save,
3636
Pencil,
3737
Check,
38+
Plus,
3839
type LucideIcon,
3940
} from 'lucide-react';
4041
import { getMetadataPreview, type MetadataSelection } from '../metadata-admin/preview-registry';
@@ -300,7 +301,9 @@ function InterfacesPillar({ packageId }: { packageId: string }): React.ReactElem
300301

301302
const Preview = getMetadataPreview(current?.type ?? '');
302303
const Inspector = getMetadataInspector(current?.type ?? '');
303-
const isEditable = !!Preview; // page / dashboard have a design preview + draft
304+
// Object leaves render as a runtime records grid (preview = runtime); schema
305+
// editing is the Data pillar's job, so they are not draft-editable in this canvas.
306+
const isEditable = !!Preview && current?.type !== 'object';
304307

305308
// Load the selected surface's draft (only for editable preview types).
306309
React.useEffect(() => {
@@ -523,6 +526,11 @@ function InterfacesPillar({ packageId }: { packageId: string }): React.ReactElem
523526
<div className="flex items-center justify-center gap-2 py-16 text-sm text-muted-foreground">
524527
<Loader2 className="h-4 w-4 animate-spin" /> 加载中…
525528
</div>
529+
) : current.type === 'object' ? (
530+
// Object nav leaf = the records list as the running app shows it
531+
// (preview = runtime). Schema editing lives in the Data pillar, so
532+
// here we render the object-view grid, not the field-form preview.
533+
<SchemaRenderer schema={{ type: 'object-view', objectName: current.name } as never} />
526534
) : Preview ? (
527535
<Preview
528536
type={current.type}
@@ -534,19 +542,21 @@ function InterfacesPillar({ packageId }: { packageId: string }): React.ReactElem
534542
onPatch={onPatch}
535543
locale={locale}
536544
/>
537-
) : current.type === 'object' ? (
538-
<SchemaRenderer schema={{ type: 'object-view', objectName: current.name } as never} />
539545
) : (
540546
<div className="py-12 text-center text-xs text-muted-foreground">
541547
{current.type} 暂用只读预览,设计能力建设中。
542548
</div>
543549
)}
544550
</div>
545-
{isEditable && (
551+
{isEditable ? (
546552
<p className="mt-2 flex items-center gap-1 text-[11px] text-muted-foreground">
547553
<MousePointer2 className="h-3 w-3" /> 点选积木 → 右侧直接改 · 改完「保存草稿」→「发布」
548554
</p>
549-
)}
555+
) : current?.type === 'object' ? (
556+
<p className="mt-2 flex items-center gap-1 text-[11px] text-muted-foreground">
557+
<Database className="h-3 w-3" /> 运行态列表预览 · 改字段 / 结构请到 <span className="font-medium">Data</span> 支柱
558+
</p>
559+
) : null}
550560
</main>
551561

552562
{/* inspector */}
@@ -747,6 +757,14 @@ function DataPillar({ packageId }: { packageId: string }): React.ReactElement {
747757
object · {current.name}
748758
</span>
749759
<span className="text-[11px] text-muted-foreground">{fields.length} 字段</span>
760+
<button
761+
type="button"
762+
onClick={() => setAddOpen(true)}
763+
title="给该对象添加一个字段"
764+
className="ml-auto inline-flex items-center gap-1 rounded-md border px-2 py-1 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground"
765+
>
766+
<Plus className="h-3.5 w-3.5" /> 添加字段
767+
</button>
750768
</div>
751769
{/* Data mode = the records themselves, as a directly-viewable grid
752770
* (Airtable parity). Fields are the columns; the trailing "+" column

0 commit comments

Comments
 (0)