@object-ui/plugin-detail 0.5.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +15 -0
- package/dist/index.js +22135 -20633
- package/dist/index.umd.cjs +26 -26
- package/dist/plugin-detail.css +1 -1
- package/dist/src/DetailView.d.ts.map +1 -1
- package/dist/src/RelatedList.d.ts +2 -0
- package/dist/src/RelatedList.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/DetailView.tsx +29 -13
- package/src/RelatedList.tsx +30 -5
- package/src/index.tsx +13 -0
package/src/DetailView.tsx
CHANGED
|
@@ -55,43 +55,58 @@ export const DetailView: React.FC<DetailViewProps> = ({
|
|
|
55
55
|
});
|
|
56
56
|
} else if (schema.api && schema.resourceId) {
|
|
57
57
|
setLoading(true);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
fetch(`${schema.api}/${schema.resourceId}`)
|
|
59
|
+
.then(res => res.json())
|
|
60
|
+
.then(result => {
|
|
61
|
+
setData(result?.data || result);
|
|
62
|
+
})
|
|
63
|
+
.catch(err => {
|
|
64
|
+
console.error('Failed to fetch detail data:', err);
|
|
65
|
+
})
|
|
66
|
+
.finally(() => setLoading(false));
|
|
63
67
|
}
|
|
64
68
|
}, [schema.api, schema.resourceId]);
|
|
65
69
|
|
|
66
70
|
const handleBack = React.useCallback(() => {
|
|
67
71
|
if (onBack) {
|
|
68
72
|
onBack();
|
|
73
|
+
} else if (schema.onNavigate) {
|
|
74
|
+
// SPA-aware navigation
|
|
75
|
+
const backUrl = schema.backUrl || (schema.objectName ? `/${schema.objectName}` : '/');
|
|
76
|
+
schema.onNavigate(backUrl, { replace: true });
|
|
69
77
|
} else if (schema.backUrl) {
|
|
70
78
|
window.location.href = schema.backUrl;
|
|
71
79
|
} else {
|
|
72
80
|
window.history.back();
|
|
73
81
|
}
|
|
74
|
-
}, [onBack, schema
|
|
82
|
+
}, [onBack, schema]);
|
|
75
83
|
|
|
76
84
|
const handleEdit = React.useCallback(() => {
|
|
77
85
|
if (onEdit) {
|
|
78
86
|
onEdit();
|
|
87
|
+
} else if (schema.onNavigate && schema.editUrl) {
|
|
88
|
+
// SPA-aware navigation
|
|
89
|
+
schema.onNavigate(schema.editUrl);
|
|
90
|
+
} else if (schema.onNavigate && schema.objectName && schema.resourceId) {
|
|
91
|
+
// Build edit URL from object + resource
|
|
92
|
+
schema.onNavigate(`/${schema.objectName}/${schema.resourceId}/edit`);
|
|
79
93
|
} else if (schema.editUrl) {
|
|
80
94
|
window.location.href = schema.editUrl;
|
|
81
95
|
}
|
|
82
|
-
|
|
83
|
-
// else {
|
|
84
|
-
// setEditMode(true);
|
|
85
|
-
// }
|
|
86
|
-
}, [onEdit, schema.editUrl]);
|
|
96
|
+
}, [onEdit, schema]);
|
|
87
97
|
|
|
88
98
|
const handleDelete = React.useCallback(() => {
|
|
89
|
-
// TODO: Replace with proper confirmation dialog component
|
|
90
99
|
const confirmMessage = schema.deleteConfirmation || 'Are you sure you want to delete this record?';
|
|
100
|
+
// Use window.confirm as fallback — the ActionProvider's onConfirm handler
|
|
101
|
+
// will intercept this if wired up via the action system.
|
|
91
102
|
if (window.confirm(confirmMessage)) {
|
|
92
103
|
onDelete?.();
|
|
104
|
+
// Navigate back after deletion if onNavigate available
|
|
105
|
+
if (schema.onNavigate && schema.objectName) {
|
|
106
|
+
schema.onNavigate(`/${schema.objectName}`, { replace: true });
|
|
107
|
+
}
|
|
93
108
|
}
|
|
94
|
-
}, [onDelete, schema
|
|
109
|
+
}, [onDelete, schema]);
|
|
95
110
|
|
|
96
111
|
if (loading || schema.loading) {
|
|
97
112
|
return (
|
|
@@ -196,6 +211,7 @@ export const DetailView: React.FC<DetailViewProps> = ({
|
|
|
196
211
|
api={related.api}
|
|
197
212
|
data={related.data}
|
|
198
213
|
columns={related.columns as any}
|
|
214
|
+
dataSource={dataSource}
|
|
199
215
|
/>
|
|
200
216
|
))}
|
|
201
217
|
</div>
|
package/src/RelatedList.tsx
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import * as React from 'react';
|
|
10
10
|
import { Card, CardHeader, CardTitle, CardContent } from '@object-ui/components';
|
|
11
11
|
import { SchemaRenderer } from '@object-ui/react';
|
|
12
|
+
import type { DataSource } from '@object-ui/types';
|
|
12
13
|
|
|
13
14
|
export interface RelatedListProps {
|
|
14
15
|
title: string;
|
|
@@ -18,6 +19,7 @@ export interface RelatedListProps {
|
|
|
18
19
|
schema?: any;
|
|
19
20
|
columns?: any[];
|
|
20
21
|
className?: string;
|
|
22
|
+
dataSource?: DataSource;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
export const RelatedList: React.FC<RelatedListProps> = ({
|
|
@@ -28,18 +30,41 @@ export const RelatedList: React.FC<RelatedListProps> = ({
|
|
|
28
30
|
schema,
|
|
29
31
|
columns,
|
|
30
32
|
className,
|
|
33
|
+
dataSource,
|
|
31
34
|
}) => {
|
|
32
|
-
const [relatedData] = React.useState(data);
|
|
35
|
+
const [relatedData, setRelatedData] = React.useState(data);
|
|
33
36
|
const [loading, setLoading] = React.useState(false);
|
|
34
37
|
|
|
35
38
|
React.useEffect(() => {
|
|
36
39
|
if (api && !data.length) {
|
|
37
40
|
setLoading(true);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
if (dataSource) {
|
|
42
|
+
dataSource.find(api).then((result) => {
|
|
43
|
+
const items = Array.isArray(result)
|
|
44
|
+
? result
|
|
45
|
+
: Array.isArray((result as any)?.data)
|
|
46
|
+
? (result as any).data
|
|
47
|
+
: [];
|
|
48
|
+
setRelatedData(items);
|
|
49
|
+
setLoading(false);
|
|
50
|
+
}).catch((err) => {
|
|
51
|
+
console.error('Failed to fetch related data:', err);
|
|
52
|
+
setLoading(false);
|
|
53
|
+
});
|
|
54
|
+
} else {
|
|
55
|
+
fetch(api)
|
|
56
|
+
.then(res => res.json())
|
|
57
|
+
.then(result => {
|
|
58
|
+
const items = Array.isArray(result) ? result : (result?.data || []);
|
|
59
|
+
setRelatedData(items);
|
|
60
|
+
})
|
|
61
|
+
.catch(err => {
|
|
62
|
+
console.error('Failed to fetch related data:', err);
|
|
63
|
+
})
|
|
64
|
+
.finally(() => setLoading(false));
|
|
65
|
+
}
|
|
41
66
|
}
|
|
42
|
-
}, [api, data]);
|
|
67
|
+
}, [api, data, dataSource]);
|
|
43
68
|
|
|
44
69
|
const viewSchema = React.useMemo(() => {
|
|
45
70
|
if (schema) return schema;
|
package/src/index.tsx
CHANGED
|
@@ -84,3 +84,16 @@ ComponentRegistry.register('related-list', RelatedList, {
|
|
|
84
84
|
{ name: 'columns', type: 'array', label: 'Columns' },
|
|
85
85
|
],
|
|
86
86
|
});
|
|
87
|
+
|
|
88
|
+
// Alias for generic view
|
|
89
|
+
ComponentRegistry.register('detail', DetailView, {
|
|
90
|
+
namespace: 'view',
|
|
91
|
+
category: 'view',
|
|
92
|
+
label: 'Detail',
|
|
93
|
+
icon: 'FileText',
|
|
94
|
+
inputs: [
|
|
95
|
+
{ name: 'objectName', type: 'string', label: 'Object Name', required: true },
|
|
96
|
+
{ name: 'recordId', type: 'string', label: 'Record ID' },
|
|
97
|
+
{ name: 'fields', type: 'array', label: 'Fields' },
|
|
98
|
+
]
|
|
99
|
+
});
|