Skip to content

Commit 92c1950

Browse files
committed
添加调试元数据检查器到多个视图组件
1 parent a19639b commit 92c1950

File tree

4 files changed

+197
-48
lines changed

4 files changed

+197
-48
lines changed

apps/console/src/App.tsx

Lines changed: 64 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import { BrowserRouter, Routes, Route, Navigate, useNavigate, useLocation, useSe
22
import { useState, useEffect } from 'react';
33
import { ObjectStackClient } from '@objectstack/client';
44
import { ObjectForm } from '@object-ui/plugin-form';
5-
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Empty, EmptyTitle } from '@object-ui/components';
5+
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Empty, EmptyTitle, Button } from '@object-ui/components';
66
import { SchemaRendererProvider } from '@object-ui/react';
77
import { ObjectStackDataSource } from './dataSource';
88
import appConfig from '../objectstack.shared';
9+
import { Code2 } from 'lucide-react';
910

1011
// Components
1112
import { ConsoleLayout } from './components/ConsoleLayout';
@@ -22,6 +23,7 @@ import { useParams } from 'react-router-dom';
2223
// Detail View Component
2324
function RecordDetailView({ dataSource, objects, onEdit }: any) {
2425
const { objectName, recordId } = useParams();
26+
const [showDebug, setShowDebug] = useState(false);
2527
const objectDef = objects.find((o: any) => o.name === objectName);
2628

2729
if (!objectDef) {
@@ -35,32 +37,68 @@ function RecordDetailView({ dataSource, objects, onEdit }: any) {
3537
);
3638
}
3739

40+
const detailSchema = {
41+
type: 'detail-view',
42+
objectName: objectDef.name,
43+
resourceId: recordId,
44+
showBack: true,
45+
onBack: 'history',
46+
showEdit: true,
47+
title: objectDef.label,
48+
sections: [
49+
{
50+
title: 'Details',
51+
fields: Object.keys(objectDef.fields || {}).map(key => ({
52+
name: key,
53+
label: objectDef.fields[key].label || key,
54+
type: objectDef.fields[key].type || 'text'
55+
})),
56+
columns: 2
57+
}
58+
]
59+
};
60+
3861
return (
39-
<div className="h-full bg-background overflow-auto p-4 lg:p-6">
40-
<DetailView
41-
schema={{
42-
type: 'detail-view',
43-
objectName: objectDef.name,
44-
resourceId: recordId,
45-
showBack: true,
46-
onBack: 'history',
47-
showEdit: true,
48-
title: objectDef.label,
49-
sections: [
50-
{
51-
title: 'Details',
52-
fields: Object.keys(objectDef.fields || {}).map(key => ({
53-
name: key,
54-
label: objectDef.fields[key].label || key,
55-
type: objectDef.fields[key].type || 'text'
56-
})),
57-
columns: 2
58-
}
59-
]
60-
}}
61-
dataSource={dataSource}
62-
onEdit={() => onEdit({ _id: recordId, id: recordId })}
63-
/>
62+
<div className="h-full bg-background overflow-hidden flex flex-col relative">
63+
<div className="absolute top-4 right-4 z-50">
64+
<Button
65+
variant="outline"
66+
size="icon"
67+
onClick={() => setShowDebug(!showDebug)}
68+
title="Toggle Metadata Inspector"
69+
className="bg-background/80 backdrop-blur shadow-sm"
70+
>
71+
<Code2 className="h-4 w-4" />
72+
</Button>
73+
</div>
74+
75+
<div className="flex-1 overflow-hidden flex flex-row">
76+
<div className="flex-1 overflow-auto p-4 lg:p-6">
77+
<DetailView
78+
schema={detailSchema}
79+
dataSource={dataSource}
80+
onEdit={() => onEdit({ _id: recordId, id: recordId })}
81+
/>
82+
</div>
83+
{showDebug && (
84+
<div className="w-[400px] border-l bg-muted/30 p-0 overflow-hidden flex flex-col shrink-0 shadow-xl z-20 transition-all">
85+
<div className="p-3 border-b bg-muted/50 font-semibold text-sm flex items-center justify-between">
86+
<span>Metadata Inspector</span>
87+
<span className="text-xs text-muted-foreground">JSON Protocol</span>
88+
</div>
89+
<div className="flex-1 overflow-auto p-4 space-y-6">
90+
<div>
91+
<h4 className="text-xs font-bold uppercase text-muted-foreground mb-2">View Schema</h4>
92+
<div className="relative rounded-md border bg-slate-950 text-slate-50 overflow-hidden">
93+
<pre className="text-xs p-3 overflow-auto max-h-[800px]">
94+
{JSON.stringify(detailSchema, null, 2)}
95+
</pre>
96+
</div>
97+
</div>
98+
</div>
99+
</div>
100+
)}
101+
</div>
64102
</div>
65103
);
66104
}

apps/console/src/components/DashboardView.tsx

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
* Renders a dashboard based on the dashboardName parameter
44
*/
55

6+
import { useState } from 'react';
67
import { useParams } from 'react-router-dom';
78
import { DashboardRenderer } from '@object-ui/plugin-dashboard';
8-
import { Empty, EmptyTitle, EmptyDescription } from '@object-ui/components';
9+
import { Empty, EmptyTitle, EmptyDescription, Button } from '@object-ui/components';
10+
import { Code2 } from 'lucide-react';
911
import appConfig from '../../objectstack.shared';
1012

1113
export function DashboardView() {
1214
const { dashboardName } = useParams<{ dashboardName: string }>();
15+
const [showDebug, setShowDebug] = useState(false);
1316

1417
// Find dashboard definition in config
1518
// In a real implementation, this would fetch from the server
@@ -27,14 +30,49 @@ export function DashboardView() {
2730
}
2831

2932
return (
30-
<div className="p-6">
31-
<div className="mb-6">
32-
<h1 className="text-3xl font-bold">{dashboard.label || dashboard.name}</h1>
33-
{dashboard.description && (
34-
<p className="text-muted-foreground mt-2">{dashboard.description}</p>
35-
)}
33+
<div className="flex flex-col h-full overflow-hidden bg-background">
34+
<div className="flex justify-between items-center p-6 border-b shrink-0">
35+
<div>
36+
<h1 className="text-2xl font-bold tracking-tight">{dashboard.label || dashboard.name}</h1>
37+
{dashboard.description && (
38+
<p className="text-muted-foreground mt-1">{dashboard.description}</p>
39+
)}
40+
</div>
41+
<Button
42+
variant={showDebug ? "secondary" : "outline"}
43+
size="sm"
44+
onClick={() => setShowDebug(!showDebug)}
45+
className="gap-2"
46+
>
47+
<Code2 className="h-4 w-4" />
48+
Metadata
49+
</Button>
50+
</div>
51+
52+
<div className="flex-1 overflow-hidden flex flex-row relative">
53+
<div className="flex-1 overflow-auto p-6">
54+
<DashboardRenderer schema={dashboard} />
55+
</div>
56+
57+
{showDebug && (
58+
<div className="w-[400px] border-l bg-muted/30 p-0 overflow-hidden flex flex-col shrink-0 shadow-xl z-20 transition-all">
59+
<div className="p-3 border-b bg-muted/50 font-semibold text-sm flex items-center justify-between">
60+
<span>Metadata Inspector</span>
61+
<span className="text-xs text-muted-foreground">JSON Protocol</span>
62+
</div>
63+
<div className="flex-1 overflow-auto p-4 space-y-6">
64+
<div>
65+
<h4 className="text-xs font-bold uppercase text-muted-foreground mb-2">Dashboard Configuration</h4>
66+
<div className="relative rounded-md border bg-slate-950 text-slate-50 overflow-hidden">
67+
<pre className="text-xs p-3 overflow-auto max-h-[800px]">
68+
{JSON.stringify(dashboard, null, 2)}
69+
</pre>
70+
</div>
71+
</div>
72+
</div>
73+
</div>
74+
)}
3675
</div>
37-
<DashboardRenderer schema={dashboard} />
3876
</div>
3977
);
4078
}

apps/console/src/components/ObjectView.tsx

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useMemo } from 'react';
1+
import { useMemo, useState } from 'react';
22
import { useParams, useSearchParams, useNavigate } from 'react-router-dom';
33
import { ObjectChart } from '@object-ui/plugin-charts';
44
import { ListView } from '@object-ui/plugin-list';
@@ -8,13 +8,14 @@ import '@object-ui/plugin-grid';
88
import '@object-ui/plugin-kanban';
99
import '@object-ui/plugin-calendar';
1010
import { Button, Empty, EmptyTitle, EmptyDescription, Sheet, SheetContent } from '@object-ui/components';
11-
import { Plus, Calendar as CalendarIcon, Kanban as KanbanIcon, Table as TableIcon, AlignLeft } from 'lucide-react';
11+
import { Plus, Calendar as CalendarIcon, Kanban as KanbanIcon, Table as TableIcon, AlignLeft, Code2 } from 'lucide-react';
1212
import type { ListViewSchema } from '@object-ui/types';
1313

1414
export function ObjectView({ dataSource, objects, onEdit, onRowClick }: any) {
1515
const navigate = useNavigate();
1616
const { objectName, viewId } = useParams();
1717
const [searchParams, setSearchParams] = useSearchParams();
18+
const [showDebug, setShowDebug] = useState(false);
1819

1920
// Get Object Definition
2021
const objectDef = objects.find((o: any) => o.name === objectName);
@@ -189,6 +190,16 @@ export function ObjectView({ dataSource, objects, onEdit, onRowClick }: any) {
189190
</div>
190191

191192
<div className="flex items-center gap-2">
193+
<Button
194+
size="sm"
195+
variant={showDebug ? "secondary" : "outline"}
196+
onClick={() => setShowDebug(!showDebug)}
197+
className="shadow-none gap-2 hidden sm:flex"
198+
title="Toggle Metadata Inspector"
199+
>
200+
<Code2 className="h-4 w-4" />
201+
<span className="hidden lg:inline">Metadata</span>
202+
</Button>
192203
<Button size="sm" onClick={() => onEdit(null)} className="shadow-none gap-2">
193204
<Plus className="h-4 w-4" />
194205
<span className="hidden sm:inline">New</span>
@@ -231,10 +242,39 @@ export function ObjectView({ dataSource, objects, onEdit, onRowClick }: any) {
231242
</div>
232243

233244
{/* 3. Content Area (Edge-to-Edge) */}
234-
<div className="flex-1 overflow-hidden relative">
235-
<div className="absolute inset-0">
236-
{renderCurrentView()}
245+
<div className="flex-1 overflow-hidden relative flex flex-row">
246+
<div className="flex-1 relative h-full">
247+
<div className="absolute inset-0">
248+
{renderCurrentView()}
249+
</div>
237250
</div>
251+
{showDebug && (
252+
<div className="w-[400px] border-l bg-muted/30 p-0 overflow-hidden flex flex-col shrink-0 shadow-xl z-20 transition-all">
253+
<div className="p-3 border-b bg-muted/50 font-semibold text-sm flex items-center justify-between">
254+
<span>Metadata Inspector</span>
255+
<span className="text-xs text-muted-foreground">JSON Protocol</span>
256+
</div>
257+
<div className="flex-1 overflow-auto p-4 space-y-6">
258+
<div>
259+
<h4 className="text-xs font-bold uppercase text-muted-foreground mb-2">View Configuration</h4>
260+
<div className="relative rounded-md border bg-slate-950 text-slate-50 overflow-hidden">
261+
<pre className="text-xs p-3 overflow-auto max-h-[400px]">
262+
{JSON.stringify(activeView, null, 2)}
263+
</pre>
264+
</div>
265+
</div>
266+
267+
<div>
268+
<h4 className="text-xs font-bold uppercase text-muted-foreground mb-2">Object Definition</h4>
269+
<div className="relative rounded-md border bg-slate-950 text-slate-50 overflow-hidden">
270+
<pre className="text-xs p-3 overflow-auto max-h-[400px]">
271+
{JSON.stringify(objectDef, null, 2)}
272+
</pre>
273+
</div>
274+
</div>
275+
</div>
276+
</div>
277+
)}
238278
</div>
239279

240280
{/* Drawer for Record Details */}

apps/console/src/components/PageView.tsx

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
* Renders a custom page based on the pageName parameter
44
*/
55

6+
import { useState } from 'react';
67
import { useParams, useSearchParams } from 'react-router-dom';
78
import { SchemaRenderer } from '@object-ui/react';
8-
import { Empty, EmptyTitle, EmptyDescription } from '@object-ui/components';
9+
import { Empty, EmptyTitle, EmptyDescription, Button } from '@object-ui/components';
10+
import { Code2 } from 'lucide-react';
911
import appConfig from '../../objectstack.shared';
1012

1113
export function PageView() {
1214
const { pageName } = useParams<{ pageName: string }>();
1315
const [searchParams] = useSearchParams();
16+
const [showDebug, setShowDebug] = useState(false);
1417

1518
// Find page definition in config
1619
// In a real implementation, this would fetch from the server
@@ -31,13 +34,43 @@ export function PageView() {
3134
const params = Object.fromEntries(searchParams.entries());
3235

3336
return (
34-
<SchemaRenderer
35-
schema={{
36-
type: 'page',
37-
...page,
38-
// Pass URL params to page context if needed
39-
context: { ...page.context, params }
40-
}}
41-
/>
37+
<div className="flex flex-row h-full w-full overflow-hidden relative">
38+
<div className="flex-1 overflow-auto h-full relative group">
39+
<div className={`absolute top-2 right-2 z-50 transition-opacity ${showDebug ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'}`}>
40+
<Button
41+
variant="secondary"
42+
size="icon"
43+
className="shadow-md backdrop-blur-sm bg-background/50"
44+
onClick={() => setShowDebug(!showDebug)}
45+
title="Toggle Metadata Inspector"
46+
>
47+
<Code2 className="h-4 w-4" />
48+
</Button>
49+
</div>
50+
<SchemaRenderer
51+
schema={{
52+
type: 'page',
53+
...page,
54+
context: { ...page.context, params }
55+
}}
56+
/>
57+
</div>
58+
{showDebug && (
59+
<div className="w-[400px] border-l bg-muted/30 p-0 overflow-hidden flex flex-col shrink-0 shadow-xl z-20 transition-all">
60+
<div className="p-3 border-b bg-muted/50 font-semibold text-sm flex items-center justify-between">
61+
<span>Metadata Inspector</span>
62+
<span className="text-xs text-muted-foreground">JSON Protocol</span>
63+
</div>
64+
<div className="flex-1 overflow-auto p-4">
65+
<h4 className="text-xs font-bold uppercase text-muted-foreground mb-2">Page Configuration</h4>
66+
<div className="relative rounded-md border bg-slate-950 text-slate-50 overflow-hidden">
67+
<pre className="text-xs p-3 overflow-auto max-h-[calc(100vh-100px)]">
68+
{JSON.stringify(page, null, 2)}
69+
</pre>
70+
</div>
71+
</div>
72+
</div>
73+
)}
74+
</div>
4275
);
4376
}

0 commit comments

Comments
 (0)