Skip to content

Commit bbca162

Browse files
committed
Enhance data handling across components to prioritize data from ListView; update ObjectView, ObjectCalendar, ObjectGantt, ObjectGrid, ObjectKanban, ObjectGallery, ObjectMap, and ObjectTimeline for improved data flow and loading states.
1 parent 58fbb75 commit bbca162

File tree

9 files changed

+123
-16
lines changed

9 files changed

+123
-16
lines changed

apps/console/src/components/ObjectView.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,6 @@ export function ObjectView({ dataSource, objects, onEdit }: any) {
145145
aggregation: activeView.aggregation,
146146
series: activeView.series,
147147
config: activeView.config,
148-
},
149-
gallery: {
150-
imageField: activeView.imageField,
151-
titleField: activeView.titleField || 'name',
152-
subtitleField: activeView.subtitleField
153148
}
154149
}
155150
};

packages/plugin-calendar/src/ObjectCalendar.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ export const ObjectCalendar: React.FC<ObjectCalendarProps> = ({
139139
onDateClick,
140140
onNavigate,
141141
onViewChange,
142+
...rest
142143
}) => {
143144
const [data, setData] = useState<any[]>([]);
144145
const [loading, setLoading] = useState(true);
@@ -178,6 +179,16 @@ export const ObjectCalendar: React.FC<ObjectCalendarProps> = ({
178179
return;
179180
}
180181

182+
// Prioritize data passed from parent (ListView)
183+
if ((schema as any).data || (rest as any).data) {
184+
const passedData = (schema as any).data || (rest as any).data;
185+
if (Array.isArray(passedData)) {
186+
setData(passedData);
187+
setLoading(false);
188+
return;
189+
}
190+
}
191+
181192
if (!dataSource) {
182193
throw new Error('DataSource required for object/api providers');
183194
}

packages/plugin-gantt/src/ObjectGantt.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ export const ObjectGantt: React.FC<ObjectGanttProps> = ({
128128
dataSource,
129129
className,
130130
onTaskClick,
131+
...rest
131132
}) => {
132133
const [data, setData] = useState<any[]>([]);
133134
const [loading, setLoading] = useState(true);
@@ -148,6 +149,13 @@ export const ObjectGantt: React.FC<ObjectGanttProps> = ({
148149
const fetchData = async () => {
149150
try {
150151
setLoading(true);
152+
// 1. Check for data prop (Unified ListView)
153+
if ((rest as any).data && Array.isArray((rest as any).data)) {
154+
setData((rest as any).data);
155+
setLoading(false);
156+
return;
157+
}
158+
151159

152160
if (hasInlineData && dataConfig?.provider === 'value') {
153161
setData(dataConfig.items as any[]);

packages/plugin-grid/src/ObjectGrid.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,31 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
108108
onEdit,
109109
onDelete,
110110
onRowSelect,
111+
...rest
111112
}) => {
112113
const [data, setData] = useState<any[]>([]);
113114
const [loading, setLoading] = useState(true);
114115
const [error, setError] = useState<Error | null>(null);
115116
const [objectSchema, setObjectSchema] = useState<any>(null);
116117

118+
// Check if data is passed directly (from ListView)
119+
const passedData = (rest as any).data;
120+
117121
// Resolve bound data if 'bind' property exists
118122
const boundData = useDataScope(schema.bind);
119123

120124
// Get data configuration (supports both new and legacy formats)
121125
const rawDataConfig = getDataConfig(schema);
122126
// Memoize dataConfig using deep comparison to prevent infinite loops
123127
const dataConfig = React.useMemo(() => {
128+
// If we have passed data (highest priority), treat it as value provider
129+
if (passedData && Array.isArray(passedData)) {
130+
return {
131+
provider: 'value',
132+
items: passedData
133+
};
134+
}
135+
124136
// If we have bound data, it takes precedence as inline value
125137
if (boundData && Array.isArray(boundData)) {
126138
return {
@@ -129,7 +141,7 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
129141
};
130142
}
131143
return rawDataConfig;
132-
}, [JSON.stringify(rawDataConfig), boundData]);
144+
}, [JSON.stringify(rawDataConfig), boundData, passedData]);
133145

134146
const hasInlineData = dataConfig?.provider === 'value';
135147

packages/plugin-kanban/src/ObjectKanban.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export const ObjectKanban: React.FC<ObjectKanbanProps> = ({
2222
schema,
2323
dataSource,
2424
className,
25+
...props
2526
}) => {
2627
const [fetchedData, setFetchedData] = useState<any[]>([]);
2728
const [objectDef, setObjectDef] = useState<any>(null);
@@ -85,14 +86,15 @@ export const ObjectKanban: React.FC<ObjectKanbanProps> = ({
8586
};
8687

8788
// Trigger fetch if we have an objectName AND verify no inline/bound data overrides it
88-
if (schema.objectName && !boundData && !schema.data) {
89+
// And NO props.data passed from ListView
90+
if (schema.objectName && !boundData && !schema.data && !(props as any).data) {
8991
fetchData();
9092
}
9193
return () => { isMounted = false; };
92-
}, [schema.objectName, dataSource, boundData, schema.data, schema.filter]);
94+
}, [schema.objectName, dataSource, boundData, schema.data, schema.filter, (props as any).data]);
9395

94-
// Determine which data to use: bound -> inline -> fetched
95-
const rawData = boundData || schema.data || fetchedData;
96+
// Determine which data to use: props.data -> bound -> inline -> fetched
97+
const rawData = (props as any).data || boundData || schema.data || fetchedData;
9698

9799
// Enhance data with title mapping and ensure IDs
98100
const effectiveData = useMemo(() => {

packages/plugin-list/src/ListView.tsx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,68 @@ export const ListView: React.FC<ListViewProps> = ({
3939
const [sortField] = React.useState(schema.sort?.[0]?.field || '');
4040
const [sortOrder, setSortOrder] = React.useState<'asc' | 'desc'>(schema.sort?.[0]?.order || 'asc');
4141
const [showFilters, setShowFilters] = React.useState(false);
42+
43+
// Data State
44+
const dataSource = props.dataSource;
45+
const [data, setData] = React.useState<any[]>([]);
46+
const [loading, setLoading] = React.useState(false);
4247

4348
const storageKey = React.useMemo(() => {
4449
return schema.id
4550
? `listview-${schema.objectName}-${schema.id}-view`
4651
: `listview-${schema.objectName}-view`;
4752
}, [schema.objectName, schema.id]);
4853

54+
// Fetch data effect
55+
React.useEffect(() => {
56+
let isMounted = true;
57+
58+
const fetchData = async () => {
59+
if (!dataSource || !schema.objectName) return;
60+
61+
setLoading(true);
62+
try {
63+
// Construct filter
64+
let filter: any = schema.filters || [];
65+
// TODO: Merge with searchTerm and user filters
66+
// For now, we rely on the backend/driver to handle $filter
67+
68+
// Convert sort to query format
69+
// ObjectQL uses simple object: { field: 'asc' }
70+
const sort: any = sortField ? { [sortField]: sortOrder } : undefined;
71+
72+
const results = await dataSource.find(schema.objectName, {
73+
$filter: filter,
74+
$orderby: sort,
75+
$top: 100 // Default pagination limit
76+
});
77+
78+
let items: any[] = [];
79+
if (Array.isArray(results)) {
80+
items = results;
81+
} else if (results && typeof results === 'object') {
82+
if (Array.isArray((results as any).data)) {
83+
items = (results as any).data;
84+
} else if (Array.isArray((results as any).value)) {
85+
items = (results as any).value;
86+
}
87+
}
88+
89+
if (isMounted) {
90+
setData(items);
91+
}
92+
} catch (err) {
93+
console.error("ListView data fetch error:", err);
94+
} finally {
95+
if (isMounted) setLoading(false);
96+
}
97+
};
98+
99+
fetchData();
100+
101+
return () => { isMounted = false; };
102+
}, [schema.objectName, dataSource, schema.filters, sortField, sortOrder]); // Re-fetch on filter/sort change
103+
49104
// Load saved view preference
50105
React.useEffect(() => {
51106
try {
@@ -201,6 +256,11 @@ export const ListView: React.FC<ListViewProps> = ({
201256
<div className="relative flex-1 max-w-md">
202257
<Search className="absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
203258
<Input
259+
schema={viewComponentSchema}
260+
{...props}
261+
data={data} // Pass data to children to avoid double-fetch
262+
loading={loading}
263+
204264
placeholder={`Search ${schema.objectName}...`}
205265
value={searchTerm}
206266
onChange={(e) => handleSearchChange(e.target.value)}

packages/plugin-list/src/ObjectGallery.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ export const ObjectGallery = (props: any) => {
1919

2020
useEffect(() => {
2121
let isMounted = true;
22+
23+
// Use data prop if available (from ListView)
24+
if ((props.data && Array.isArray(props.data))) {
25+
setFetchedData(props.data);
26+
return;
27+
}
28+
2229
const fetchData = async () => {
2330
if (!dataSource || !schema.objectName) return;
2431
if (isMounted) setLoading(true);
@@ -49,13 +56,13 @@ export const ObjectGallery = (props: any) => {
4956
}
5057
};
5158

52-
if (schema.objectName && !boundData && !schema.data) {
59+
if (schema.objectName && !boundData && !schema.data && !props.data) {
5360
fetchData();
5461
}
5562
return () => { isMounted = false; };
56-
}, [schema.objectName, dataSource, boundData, schema.data, schema.filter]);
63+
}, [schema.objectName, dataSource, boundData, schema.data, schema.filter, props.data]);
5764

58-
const items = boundData || schema.data || fetchedData || [];
65+
const items = props.data || boundData || schema.data || fetchedData || [];
5966

6067
// Config
6168
const imageField = schema.imageField || 'image';

packages/plugin-map/src/ObjectMap.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ export const ObjectMap: React.FC<ObjectMapProps> = ({
216216
dataSource,
217217
className,
218218
onMarkerClick,
219+
...rest
219220
}) => {
220221
const [data, setData] = useState<any[]>([]);
221222
const [loading, setLoading] = useState(true);
@@ -238,6 +239,16 @@ export const ObjectMap: React.FC<ObjectMapProps> = ({
238239
try {
239240
setLoading(true);
240241

242+
// Prioritize data passed via props (from ListView)
243+
if ((schema as any).data || (rest as any).data) {
244+
const passed = (schema as any).data || (rest as any).data;
245+
if (Array.isArray(passed)) {
246+
setData(passed);
247+
setLoading(false);
248+
return;
249+
}
250+
}
251+
241252
if (hasInlineData && dataConfig?.provider === 'value') {
242253
setData(dataConfig.items as any[]);
243254
setLoading(false);

packages/plugin-timeline/src/ObjectTimeline.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export const ObjectTimeline: React.FC<ObjectTimelineProps> = ({
4949
schema,
5050
dataSource,
5151
className,
52+
...props
5253
}) => {
5354
const [fetchedData, setFetchedData] = useState<any[]>([]);
5455
const [loading, setLoading] = useState(false);
@@ -89,12 +90,12 @@ export const ObjectTimeline: React.FC<ObjectTimelineProps> = ({
8990
}
9091
};
9192

92-
if (schema.objectName && !boundData && !schema.items) {
93+
if (schema.objectName && !boundData && !schema.items && !(props as any).data) {
9394
fetchData();
9495
}
95-
}, [schema.objectName, dataSource, boundData, schema.items]);
96+
}, [schema.objectName, dataSource, boundData, schema.items, (props as any).data]);
9697

97-
const rawData = boundData || fetchedData;
98+
const rawData = (props as any).data || boundData || fetchedData;
9899

99100
// Transform data to items if we have raw data and no explicit items
100101
let effectiveItems = schema.items;

0 commit comments

Comments
 (0)