@object-ui/plugin-view 3.1.3 → 3.1.4
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 +27 -15
- package/CHANGELOG.md +11 -0
- package/dist/index.js +4357 -4841
- package/dist/index.umd.cjs +3 -3
- package/package.json +9 -9
- package/src/ObjectView.tsx +23 -15
- package/src/index.tsx +2 -14
package/src/ObjectView.tsx
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* - ViewSwitcher for toggling between view types
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
|
25
|
+
import React, { useEffect, useState, useCallback, useMemo, useRef } from 'react';
|
|
26
26
|
import type {
|
|
27
27
|
ObjectViewSchema,
|
|
28
28
|
ObjectGridSchema,
|
|
@@ -57,20 +57,13 @@ import {
|
|
|
57
57
|
} from '@object-ui/components';
|
|
58
58
|
import { Plus } from 'lucide-react';
|
|
59
59
|
import { buildExpandFields } from '@object-ui/core';
|
|
60
|
+
import { SchemaRenderer as ImportedSchemaRenderer } from '@object-ui/react';
|
|
60
61
|
import { ViewSwitcher } from './ViewSwitcher';
|
|
61
62
|
|
|
62
63
|
/**
|
|
63
|
-
*
|
|
64
|
-
* Falls back to null if not available.
|
|
64
|
+
* SchemaRenderer from @object-ui/react, used to render sub-view schemas.
|
|
65
65
|
*/
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
69
|
-
const mod = require('@object-ui/react');
|
|
70
|
-
SchemaRendererComponent = mod.SchemaRenderer || null;
|
|
71
|
-
} catch {
|
|
72
|
-
// @object-ui/react not available
|
|
73
|
-
}
|
|
66
|
+
const SchemaRendererComponent: React.FC<any> = ImportedSchemaRenderer;
|
|
74
67
|
|
|
75
68
|
export interface ObjectViewProps {
|
|
76
69
|
/**
|
|
@@ -219,6 +212,11 @@ export const ObjectView: React.FC<ObjectViewProps> = ({
|
|
|
219
212
|
onViewAction,
|
|
220
213
|
}) => {
|
|
221
214
|
const [objectSchema, setObjectSchema] = useState<Record<string, unknown> | null>(null);
|
|
215
|
+
// Assigned in the render body (not in an effect) so the fetchData effect always
|
|
216
|
+
// reads the latest objectSchema without needing it as a dependency. This matches
|
|
217
|
+
// the same pattern used in ObjectCalendar's objectSchemaRef.
|
|
218
|
+
const objectSchemaRef = useRef<Record<string, unknown> | null>(null);
|
|
219
|
+
objectSchemaRef.current = objectSchema;
|
|
222
220
|
const [isFormOpen, setIsFormOpen] = useState(false);
|
|
223
221
|
const [formMode, setFormMode] = useState<FormMode>('create');
|
|
224
222
|
const [selectedRecord, setSelectedRecord] = useState<Record<string, unknown> | null>(null);
|
|
@@ -294,8 +292,12 @@ export const ObjectView: React.FC<ObjectViewProps> = ({
|
|
|
294
292
|
let isMounted = true;
|
|
295
293
|
|
|
296
294
|
const fetchData = async () => {
|
|
295
|
+
// When renderListView is provided, the custom list view (e.g. ListView)
|
|
296
|
+
// handles its own data fetching — skip to avoid duplicate requests and
|
|
297
|
+
// unnecessary re-renders that can cause duplicate records in child views.
|
|
298
|
+
if (renderListView) return;
|
|
297
299
|
// Only fetch for non-grid views (ObjectGrid has its own data fetching)
|
|
298
|
-
if (currentViewType === 'grid'
|
|
300
|
+
if (currentViewType === 'grid') return;
|
|
299
301
|
if (!dataSource || !schema.objectName) return;
|
|
300
302
|
|
|
301
303
|
setLoading(true);
|
|
@@ -322,8 +324,11 @@ export const ObjectView: React.FC<ObjectViewProps> = ({
|
|
|
322
324
|
? sortConfig.map(s => ({ field: s.field, order: s.direction }))
|
|
323
325
|
: (currentNamedViewConfig?.sort || activeView?.sort || schema.table?.defaultSort || undefined);
|
|
324
326
|
|
|
325
|
-
// Auto-inject $expand for lookup/master_detail fields
|
|
326
|
-
|
|
327
|
+
// Auto-inject $expand for lookup/master_detail fields.
|
|
328
|
+
// Use a ref instead of the state variable to avoid re-running this effect
|
|
329
|
+
// every time the object schema loads — that would cause a double-fetch and
|
|
330
|
+
// duplicate events in child views like the calendar.
|
|
331
|
+
const expand = buildExpandFields((objectSchemaRef.current as any)?.fields);
|
|
327
332
|
const results = await dataSource.find(schema.objectName, {
|
|
328
333
|
$filter: finalFilter.length > 0 ? finalFilter : undefined,
|
|
329
334
|
$orderby: sort,
|
|
@@ -339,6 +344,8 @@ export const ObjectView: React.FC<ObjectViewProps> = ({
|
|
|
339
344
|
items = (results as any).data;
|
|
340
345
|
} else if (Array.isArray((results as any).records)) {
|
|
341
346
|
items = (results as any).records;
|
|
347
|
+
} else if (Array.isArray((results as any).value)) {
|
|
348
|
+
items = (results as any).value;
|
|
342
349
|
}
|
|
343
350
|
}
|
|
344
351
|
|
|
@@ -352,8 +359,9 @@ export const ObjectView: React.FC<ObjectViewProps> = ({
|
|
|
352
359
|
|
|
353
360
|
fetchData();
|
|
354
361
|
return () => { isMounted = false; };
|
|
362
|
+
// objectSchema intentionally omitted from deps — read via ref to prevent double-fetch
|
|
355
363
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
356
|
-
}, [schema.objectName, dataSource, currentViewType, filterValues, sortConfig, refreshKey, currentNamedViewConfig, activeView, renderListView
|
|
364
|
+
}, [schema.objectName, dataSource, currentViewType, filterValues, sortConfig, refreshKey, currentNamedViewConfig, activeView, renderListView]);
|
|
357
365
|
|
|
358
366
|
// Determine layout mode
|
|
359
367
|
const layout = schema.layout || 'drawer';
|
package/src/index.tsx
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import React, { useContext } from 'react';
|
|
10
10
|
import { ComponentRegistry } from '@object-ui/core';
|
|
11
|
+
import { SchemaRendererContext as ImportedSchemaRendererContext } from '@object-ui/react';
|
|
11
12
|
import { ObjectView } from './ObjectView';
|
|
12
13
|
import { ViewSwitcher } from './ViewSwitcher';
|
|
13
14
|
import { FilterUI } from './FilterUI';
|
|
@@ -25,22 +26,9 @@ export type { SharedViewLinkProps } from './SharedViewLink';
|
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* SchemaRendererContext is created by @object-ui/react.
|
|
28
|
-
* We import it dynamically to avoid a circular dependency.
|
|
29
29
|
* The context value provides { dataSource }.
|
|
30
|
-
* A fallback context is created so hooks are never called conditionally.
|
|
31
30
|
*/
|
|
32
|
-
const
|
|
33
|
-
let SchemaRendererContext: React.Context<any> = FallbackContext;
|
|
34
|
-
try {
|
|
35
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
36
|
-
const mod = require('@object-ui/react');
|
|
37
|
-
// The context is re-exported from @object-ui/react
|
|
38
|
-
if (mod.SchemaRendererContext) {
|
|
39
|
-
SchemaRendererContext = mod.SchemaRendererContext;
|
|
40
|
-
}
|
|
41
|
-
} catch {
|
|
42
|
-
// @object-ui/react not available — registry-based dataSource only
|
|
43
|
-
}
|
|
31
|
+
const SchemaRendererContext: React.Context<any> = ImportedSchemaRendererContext;
|
|
44
32
|
|
|
45
33
|
// Register object-view component
|
|
46
34
|
const ObjectViewRenderer: React.FC<{ schema: any }> = ({ schema }) => {
|