@firecms/core 3.0.1 → 3.1.0-canary.1df3b2c
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/README.md +1 -1
- package/dist/components/AIIcon.d.ts +16 -0
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +7 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +14 -0
- package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +6 -0
- package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -4
- package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +6 -0
- package/dist/components/EntityCollectionView/Board.d.ts +2 -0
- package/dist/components/EntityCollectionView/BoardColumn.d.ts +42 -0
- package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +9 -0
- package/dist/components/EntityCollectionView/BoardSortableList.d.ts +14 -0
- package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +26 -0
- package/dist/components/EntityCollectionView/EntityCard.d.ts +19 -0
- package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +20 -0
- package/dist/components/EntityCollectionView/EntityCollectionCardView.d.ts +31 -0
- package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +2 -2
- package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +7 -3
- package/dist/components/EntityCollectionView/FiltersDialog.d.ts +14 -0
- package/dist/components/EntityCollectionView/ViewModeToggle.d.ts +49 -0
- package/dist/components/EntityCollectionView/board_types.d.ts +105 -0
- package/dist/components/EntityCollectionView/useBoardDataController.d.ts +60 -0
- package/dist/components/SelectableTable/SelectableTable.d.ts +5 -1
- package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -1
- package/dist/components/VirtualTable/VirtualTableCell.d.ts +6 -0
- package/dist/components/VirtualTable/VirtualTableHeader.d.ts +2 -0
- package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +11 -0
- package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +1 -0
- package/dist/components/VirtualTable/types.d.ts +2 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/contexts/index.d.ts +10 -0
- package/dist/core/DrawerNavigationGroup.d.ts +45 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/form/validation.d.ts +3 -2
- package/dist/hooks/useBreadcrumbsController.d.ts +16 -0
- package/dist/hooks/useCollapsedGroups.d.ts +4 -1
- package/dist/index.es.js +5239 -1590
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +5233 -1585
- package/dist/index.umd.js.map +1 -1
- package/dist/preview/PropertyPreviewProps.d.ts +5 -0
- package/dist/preview/components/DatePreview.d.ts +13 -3
- package/dist/preview/components/ImagePreview.d.ts +5 -1
- package/dist/preview/components/StorageThumbnail.d.ts +2 -1
- package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
- package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
- package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
- package/dist/types/collections.d.ts +42 -2
- package/dist/types/datasource.d.ts +0 -1
- package/dist/types/plugins.d.ts +46 -1
- package/dist/types/properties.d.ts +259 -4
- package/dist/util/__tests__/conditions.test.d.ts +1 -0
- package/dist/util/__tests__/objects.test.d.ts +1 -0
- package/dist/util/conditions.d.ts +26 -0
- package/dist/util/entities.d.ts +1 -2
- package/dist/util/index.d.ts +2 -1
- package/dist/util/property_utils.d.ts +2 -1
- package/dist/util/resolutions.d.ts +1 -1
- package/package.json +10 -7
- package/src/app/Scaffold.tsx +14 -15
- package/src/components/AIIcon.tsx +39 -0
- package/src/components/ArrayContainer.tsx +1 -4
- package/src/components/ClearFilterSortButton.tsx +19 -16
- package/src/components/ConfirmationDialog.tsx +0 -2
- package/src/components/DeleteEntityDialog.tsx +2 -4
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +74 -41
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +130 -79
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +121 -104
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +132 -103
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +20 -42
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +90 -49
- package/src/components/EntityCollectionView/Board.tsx +324 -0
- package/src/components/EntityCollectionView/BoardColumn.tsx +158 -0
- package/src/components/EntityCollectionView/BoardColumnTitle.tsx +45 -0
- package/src/components/EntityCollectionView/BoardSortableList.tsx +172 -0
- package/src/components/EntityCollectionView/EntityBoardCard.tsx +212 -0
- package/src/components/EntityCollectionView/EntityCard.tsx +231 -0
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +713 -0
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +244 -0
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +485 -203
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +31 -19
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +84 -15
- package/src/components/EntityCollectionView/FiltersDialog.tsx +249 -0
- package/src/components/EntityCollectionView/ViewModeToggle.tsx +202 -0
- package/src/components/EntityCollectionView/board_types.ts +113 -0
- package/src/components/EntityCollectionView/useBoardDataController.tsx +490 -0
- package/src/components/ErrorTooltip.tsx +2 -1
- package/src/components/HomePage/DefaultHomePage.tsx +47 -10
- package/src/components/HomePage/HomePageDnD.tsx +56 -41
- package/src/components/HomePage/NavigationCard.tsx +20 -18
- package/src/components/HomePage/NavigationGroup.tsx +17 -16
- package/src/components/HomePage/RenameGroupDialog.tsx +0 -2
- package/src/components/HomePage/SmallNavigationCard.tsx +10 -9
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +3 -10
- package/src/components/ReferenceWidget.tsx +2 -4
- package/src/components/SelectableTable/SelectableTable.tsx +75 -67
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +7 -6
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +39 -40
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +38 -38
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +49 -58
- package/src/components/UnsavedChangesDialog.tsx +0 -2
- package/src/components/UserDisplay.tsx +4 -4
- package/src/components/VirtualTable/VirtualTable.tsx +170 -19
- package/src/components/VirtualTable/VirtualTableCell.tsx +18 -2
- package/src/components/VirtualTable/VirtualTableHeader.tsx +20 -11
- package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +158 -42
- package/src/components/VirtualTable/VirtualTableProps.tsx +14 -1
- package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -0
- package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +17 -4
- package/src/components/VirtualTable/types.tsx +2 -0
- package/src/components/common/useColumnsIds.tsx +95 -3
- package/src/components/index.tsx +4 -0
- package/src/contexts/BreacrumbsContext.tsx +15 -8
- package/src/contexts/index.ts +10 -0
- package/src/core/DefaultAppBar.tsx +39 -26
- package/src/core/DefaultDrawer.tsx +42 -56
- package/src/core/DrawerNavigationGroup.tsx +118 -0
- package/src/core/DrawerNavigationItem.tsx +4 -3
- package/src/core/EntityEditView.tsx +41 -43
- package/src/core/SideDialogs.tsx +4 -2
- package/src/core/index.tsx +1 -0
- package/src/form/PropertyFieldBinding.tsx +58 -43
- package/src/form/components/StorageItemPreview.tsx +2 -1
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +0 -1
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +17 -16
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +0 -1
- package/src/form/field_bindings/MapFieldBinding.tsx +69 -67
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +21 -17
- package/src/form/field_bindings/TextFieldBinding.tsx +71 -35
- package/src/form/validation.ts +245 -160
- package/src/hooks/useBreadcrumbsController.tsx +18 -0
- package/src/hooks/useBuildNavigationController.tsx +42 -19
- package/src/hooks/useCollapsedGroups.ts +12 -4
- package/src/internal/useBuildDataSource.ts +69 -34
- package/src/internal/useBuildSideDialogsController.tsx +11 -8
- package/src/internal/useBuildSideEntityController.tsx +2 -4
- package/src/internal/useRestoreScroll.tsx +26 -14
- package/src/preview/PropertyPreview.tsx +40 -32
- package/src/preview/PropertyPreviewProps.tsx +6 -0
- package/src/preview/components/DatePreview.tsx +72 -4
- package/src/preview/components/EmptyValue.tsx +1 -1
- package/src/preview/components/ImagePreview.tsx +37 -21
- package/src/preview/components/StorageThumbnail.tsx +16 -12
- package/src/preview/components/UrlComponentPreview.tsx +28 -25
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +9 -7
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +11 -9
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +26 -24
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +61 -56
- package/src/routes/CustomCMSRoute.tsx +1 -0
- package/src/routes/FireCMSRoute.tsx +26 -13
- package/src/types/collections.ts +48 -3
- package/src/types/datasource.ts +54 -56
- package/src/types/plugins.tsx +51 -1
- package/src/types/properties.ts +347 -27
- package/src/util/__tests__/conditions.test.ts +506 -0
- package/src/util/__tests__/objects.test.ts +196 -0
- package/src/util/callbacks.ts +6 -3
- package/src/util/collections.ts +51 -6
- package/src/util/conditions.ts +339 -0
- package/src/util/entities.ts +28 -29
- package/src/util/entity_cache.ts +2 -1
- package/src/util/index.ts +2 -1
- package/src/util/objects.ts +31 -13
- package/src/util/{references.ts → previews.ts} +14 -0
- package/src/util/property_utils.tsx +36 -10
- package/src/util/resolutions.ts +57 -55
- /package/dist/util/{references.d.ts → previews.d.ts} +0 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cls, ExpandMoreIcon, Typography } from "@firecms/ui";
|
|
3
|
+
import { NavigationEntry } from "../types";
|
|
4
|
+
import { IconForView } from "../util";
|
|
5
|
+
import { DrawerNavigationItem } from "./DrawerNavigationItem";
|
|
6
|
+
|
|
7
|
+
export interface DrawerNavigationGroupProps {
|
|
8
|
+
/**
|
|
9
|
+
* Group name to display in header
|
|
10
|
+
*/
|
|
11
|
+
group: string;
|
|
12
|
+
/**
|
|
13
|
+
* Navigation entries in this group
|
|
14
|
+
*/
|
|
15
|
+
entries: NavigationEntry[];
|
|
16
|
+
/**
|
|
17
|
+
* Whether the group is collapsed
|
|
18
|
+
*/
|
|
19
|
+
collapsed: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Callback when collapse state should toggle
|
|
22
|
+
*/
|
|
23
|
+
onToggleCollapsed: () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Whether the drawer is in open (expanded) state
|
|
26
|
+
*/
|
|
27
|
+
drawerOpen: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Whether tooltips should be shown (drawer closed + hovered)
|
|
30
|
+
*/
|
|
31
|
+
tooltipsOpen: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Whether admin menu is open (used to control tooltip visibility)
|
|
34
|
+
*/
|
|
35
|
+
adminMenuOpen?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Optional actions to render in the group header (e.g., "Add collection" button)
|
|
38
|
+
*/
|
|
39
|
+
headerActions?: React.ReactNode;
|
|
40
|
+
/**
|
|
41
|
+
* Optional callback when a navigation item is clicked
|
|
42
|
+
*/
|
|
43
|
+
onItemClick?: (entry: NavigationEntry) => void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Shared drawer navigation group component used by both DefaultDrawer and FireCMSCloudDrawer.
|
|
48
|
+
* Renders a collapsible group with header and navigation items.
|
|
49
|
+
*/
|
|
50
|
+
export function DrawerNavigationGroup({
|
|
51
|
+
group,
|
|
52
|
+
entries,
|
|
53
|
+
collapsed,
|
|
54
|
+
onToggleCollapsed,
|
|
55
|
+
drawerOpen,
|
|
56
|
+
tooltipsOpen,
|
|
57
|
+
adminMenuOpen,
|
|
58
|
+
headerActions,
|
|
59
|
+
onItemClick
|
|
60
|
+
}: DrawerNavigationGroupProps) {
|
|
61
|
+
return (
|
|
62
|
+
<div
|
|
63
|
+
className={"bg-surface-50 dark:bg-surface-800/30 my-4 rounded-lg ml-3 mr-1"}
|
|
64
|
+
key={`drawer_group_${group}`}
|
|
65
|
+
>
|
|
66
|
+
{/* Group Header */}
|
|
67
|
+
{drawerOpen ? (
|
|
68
|
+
<div
|
|
69
|
+
className="pl-4 pr-2 py-2 flex flex-row items-center cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-700/50 rounded-t-lg transition-colors"
|
|
70
|
+
onClick={onToggleCollapsed}
|
|
71
|
+
>
|
|
72
|
+
<ExpandMoreIcon
|
|
73
|
+
size={"smallest"}
|
|
74
|
+
className={cls(
|
|
75
|
+
"text-surface-500 dark:text-surface-400 transition-transform duration-200 mr-1",
|
|
76
|
+
collapsed ? "-rotate-90" : "rotate-0"
|
|
77
|
+
)}
|
|
78
|
+
/>
|
|
79
|
+
<Typography
|
|
80
|
+
variant={"caption"}
|
|
81
|
+
color={"secondary"}
|
|
82
|
+
className="font-medium flex-grow line-clamp-1"
|
|
83
|
+
>
|
|
84
|
+
{(group || "Views").toUpperCase()}
|
|
85
|
+
</Typography>
|
|
86
|
+
{headerActions && (
|
|
87
|
+
<div onClick={(e) => e.stopPropagation()}>
|
|
88
|
+
{headerActions}
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
91
|
+
</div>
|
|
92
|
+
) : (
|
|
93
|
+
<div className="w-full" />
|
|
94
|
+
)}
|
|
95
|
+
|
|
96
|
+
{/* Collapsible Content */}
|
|
97
|
+
<div
|
|
98
|
+
className={cls(
|
|
99
|
+
"overflow-hidden transition-all duration-200 ease-in-out",
|
|
100
|
+
collapsed ? "max-h-0 opacity-0" : "max-h-[2000px] opacity-100"
|
|
101
|
+
)}
|
|
102
|
+
>
|
|
103
|
+
{entries.map((entry) => (
|
|
104
|
+
<DrawerNavigationItem
|
|
105
|
+
key={entry.id}
|
|
106
|
+
icon={<IconForView collectionOrView={entry.collection ?? entry.view} size={18} />}
|
|
107
|
+
tooltipsOpen={!collapsed && tooltipsOpen}
|
|
108
|
+
adminMenuOpen={adminMenuOpen}
|
|
109
|
+
drawerOpen={drawerOpen}
|
|
110
|
+
onClick={() => onItemClick?.(entry)}
|
|
111
|
+
url={entry.url}
|
|
112
|
+
name={entry.name}
|
|
113
|
+
/>
|
|
114
|
+
))}
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -34,13 +34,13 @@ export function DrawerNavigationItem({
|
|
|
34
34
|
transition: drawerOpen ? "width 150ms ease-in" : undefined
|
|
35
35
|
}}
|
|
36
36
|
className={({ isActive }: any) => cls("rounded-lg truncate",
|
|
37
|
-
"hover:bg-surface-accent-300 hover:bg-opacity-75 dark:hover:bg-surface-accent-800 dark:hover:bg-opacity-75 text-text-primary dark:text-surface-200 hover:text-surface-900 hover:dark:text-white",
|
|
37
|
+
"hover:bg-surface-accent-300 hover:bg-opacity-75 hover:bg-surface-accent-300/75 dark:hover:bg-surface-accent-800 dark:hover:bg-opacity-75 dark:hover:bg-surface-accent-800/75 text-text-primary dark:text-surface-200 hover:text-surface-900 hover:dark:text-white hover:bg-surface-accent-300/75 dark:hover:bg-surface-accent-800/75",
|
|
38
38
|
"flex flex-row items-center mr-8",
|
|
39
39
|
// "transition-all ease-in-out delay-100 duration-300",
|
|
40
40
|
// drawerOpen ? "w-full" : "w-18",
|
|
41
41
|
drawerOpen ? "pl-4 h-10" : "pl-4 h-9",
|
|
42
42
|
"font-semibold text-xs",
|
|
43
|
-
isActive ? "bg-surface-accent-200 bg-opacity-60 dark:bg-surface-800 dark:bg-opacity-50" : ""
|
|
43
|
+
isActive ? "bg-surface-accent-200 bg-opacity-60 dark:bg-surface-800 dark:bg-opacity-50 bg-surface-accent-200/60 dark:bg-surface-800/50" : ""
|
|
44
44
|
)}
|
|
45
45
|
to={url}
|
|
46
46
|
>
|
|
@@ -49,8 +49,9 @@ export function DrawerNavigationItem({
|
|
|
49
49
|
|
|
50
50
|
<div
|
|
51
51
|
className={cls(
|
|
52
|
+
"text-text-primary dark:text-surface-200",
|
|
52
53
|
drawerOpen ? "opacity-100" : "opacity-0 hidden",
|
|
53
|
-
"ml-4 font-inherit
|
|
54
|
+
"ml-4 font-inherit"
|
|
54
55
|
)}>
|
|
55
56
|
{name.toUpperCase()}
|
|
56
57
|
</div>
|
|
@@ -75,7 +75,7 @@ export interface EntityEditViewProps<M extends Record<string, any>> {
|
|
|
75
75
|
copy?: boolean;
|
|
76
76
|
selectedTab?: string;
|
|
77
77
|
parentCollectionIds: string[];
|
|
78
|
-
onValuesModified?: (modified: boolean, values:M) => void;
|
|
78
|
+
onValuesModified?: (modified: boolean, values: M) => void;
|
|
79
79
|
onSaved?: (params: OnUpdateParams) => void;
|
|
80
80
|
onTabChange?: (props: OnTabChangeParams<M>) => void;
|
|
81
81
|
layout?: "side_panel" | "full_screen";
|
|
@@ -88,9 +88,9 @@ export interface EntityEditViewProps<M extends Record<string, any>> {
|
|
|
88
88
|
* an entity is opened.
|
|
89
89
|
*/
|
|
90
90
|
export function EntityEditView<M extends Record<string, any>, USER extends User>({
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
entityId,
|
|
92
|
+
...props
|
|
93
|
+
}: EntityEditViewProps<M>) {
|
|
94
94
|
|
|
95
95
|
const {
|
|
96
96
|
entity,
|
|
@@ -123,7 +123,7 @@ export function EntityEditView<M extends Record<string, any>, USER extends User>
|
|
|
123
123
|
}, [authController, entity, status]);
|
|
124
124
|
|
|
125
125
|
if ((dataLoading && !initialDirtyValues) || (!entity || canEdit === undefined) && (status === "existing" || status === "copy")) {
|
|
126
|
-
return <CircularProgressCenter/>;
|
|
126
|
+
return <CircularProgressCenter />;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
if (entityId && !entity && !initialDirtyValues) {
|
|
@@ -131,36 +131,36 @@ export function EntityEditView<M extends Record<string, any>, USER extends User>
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
return <EntityEditViewInner<M> {...props}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
134
|
+
entityId={entityId}
|
|
135
|
+
entity={entity}
|
|
136
|
+
initialDirtyValues={initialDirtyValues as Partial<M>}
|
|
137
|
+
dataLoading={dataLoading}
|
|
138
|
+
status={status}
|
|
139
|
+
setStatus={setStatus}
|
|
140
|
+
canEdit={canEdit}
|
|
141
141
|
/>;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
export function EntityEditViewInner<M extends Record<string, any>>({
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
145
|
+
path,
|
|
146
|
+
fullIdPath,
|
|
147
|
+
entityId,
|
|
148
|
+
selectedTab: selectedTabProp,
|
|
149
|
+
collection,
|
|
150
|
+
parentCollectionIds,
|
|
151
|
+
onValuesModified,
|
|
152
|
+
onSaved,
|
|
153
|
+
onTabChange,
|
|
154
|
+
entity,
|
|
155
|
+
initialDirtyValues,
|
|
156
|
+
dataLoading,
|
|
157
|
+
layout = "side_panel",
|
|
158
|
+
barActions,
|
|
159
|
+
status,
|
|
160
|
+
setStatus,
|
|
161
|
+
formProps,
|
|
162
|
+
canEdit
|
|
163
|
+
}: EntityEditViewProps<M> & {
|
|
164
164
|
entity?: Entity<M>,
|
|
165
165
|
initialDirtyValues?: Partial<M>, // dirty cached entity in memory
|
|
166
166
|
dataLoading: boolean,
|
|
@@ -312,7 +312,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
312
312
|
role="tabpanel">
|
|
313
313
|
<ErrorBoundary>
|
|
314
314
|
<EntityJsonPreview
|
|
315
|
-
values={formContext?.values ?? entity?.values ?? {}}/>
|
|
315
|
+
values={formContext?.values ?? entity?.values ?? {}} />
|
|
316
316
|
</ErrorBoundary>
|
|
317
317
|
</div>;
|
|
318
318
|
|
|
@@ -328,7 +328,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
328
328
|
key={`subcol_${subcollectionId}`}
|
|
329
329
|
role="tabpanel">
|
|
330
330
|
|
|
331
|
-
{globalLoading && <CircularProgressCenter/>}
|
|
331
|
+
{globalLoading && <CircularProgressCenter />}
|
|
332
332
|
|
|
333
333
|
{!globalLoading &&
|
|
334
334
|
(usedEntity && newFullPath
|
|
@@ -339,7 +339,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
339
339
|
isSubCollection={true}
|
|
340
340
|
updateUrl={false}
|
|
341
341
|
{...subcollection}
|
|
342
|
-
openEntityMode={layout}/>
|
|
342
|
+
openEntityMode={layout} />
|
|
343
343
|
: <div className="flex items-center justify-center w-full h-full p-3">
|
|
344
344
|
<Typography variant={"label"}>
|
|
345
345
|
You need to save your entity before
|
|
@@ -375,8 +375,8 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
375
375
|
className={"px-8 h-full overflow-auto"}
|
|
376
376
|
entity={entity}
|
|
377
377
|
path={path}
|
|
378
|
-
collection={collection}/>
|
|
379
|
-
<div className="h-16"/>
|
|
378
|
+
collection={collection} />
|
|
379
|
+
<div className="h-16" />
|
|
380
380
|
</div>
|
|
381
381
|
</div> : null;
|
|
382
382
|
|
|
@@ -396,7 +396,6 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
396
396
|
disabled={!canEdit}
|
|
397
397
|
{...formProps}
|
|
398
398
|
onEntityChange={(entity) => {
|
|
399
|
-
console.log("333 EntityEditView onEntityChange:", entity);
|
|
400
399
|
setUsedEntity(entity);
|
|
401
400
|
formProps?.onEntityChange?.(entity);
|
|
402
401
|
}}
|
|
@@ -452,7 +451,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
452
451
|
let result = <div className="relative flex flex-col h-full w-full bg-white dark:bg-surface-900">
|
|
453
452
|
|
|
454
453
|
{shouldShowTopBar && <div
|
|
455
|
-
className={cls("h-14 items-center
|
|
454
|
+
className={cls("h-14 items-center overflow-visible overflow-x-scroll w-full no-scrollbar border-b pl-2 pr-2 flex gap-2 bg-surface-50 dark:bg-surface-900", defaultBorderMixin)}>
|
|
456
455
|
|
|
457
456
|
{barActions?.({
|
|
458
457
|
path: fullIdPath ?? path,
|
|
@@ -461,16 +460,15 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
461
460
|
status
|
|
462
461
|
})}
|
|
463
462
|
|
|
464
|
-
<div className={"flex-grow"}/>
|
|
463
|
+
<div className={"flex-grow"} />
|
|
465
464
|
|
|
466
465
|
{pluginActionsTop}
|
|
467
466
|
|
|
468
467
|
{globalLoading && <div className="self-center">
|
|
469
|
-
<CircularProgress size={"small"}/>
|
|
468
|
+
<CircularProgress size={"small"} />
|
|
470
469
|
</div>}
|
|
471
470
|
|
|
472
471
|
{hasAdditionalViews && <Tabs
|
|
473
|
-
className={"self-end"}
|
|
474
472
|
value={selectedTab}
|
|
475
473
|
onValueChange={(value) => {
|
|
476
474
|
onSideTabClick(value);
|
|
@@ -480,7 +478,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
480
478
|
disabled={!hasAdditionalViews}
|
|
481
479
|
value={JSON_TAB_VALUE}
|
|
482
480
|
className={"text-sm"}>
|
|
483
|
-
<CodeIcon size={"small"}/>
|
|
481
|
+
<CodeIcon size={"small"} />
|
|
484
482
|
</Tab>}
|
|
485
483
|
|
|
486
484
|
{customViewTabsStart}
|
|
@@ -501,7 +499,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
501
499
|
|
|
502
500
|
{globalLoading
|
|
503
501
|
? <div className="w-full pt-12 pb-16 px-4 sm:px-8 md:px-10">
|
|
504
|
-
<CircularProgressCenter/>
|
|
502
|
+
<CircularProgressCenter />
|
|
505
503
|
</div>
|
|
506
504
|
: <>
|
|
507
505
|
{entityReadOnlyView}
|
package/src/core/SideDialogs.tsx
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React, { useContext, useEffect, useState } from "react";
|
|
2
2
|
import { useSideDialogsController } from "../hooks";
|
|
3
|
-
import { SideDialogPanelProps } from "../types";
|
|
3
|
+
import { EntitySidePanelProps, SideDialogPanelProps } from "../types";
|
|
4
4
|
import { Sheet } from "@firecms/ui";
|
|
5
5
|
import { useNavigationUnsavedChangesDialog } from "../internal/useUnsavedChangesDialog";
|
|
6
6
|
import { ErrorBoundary } from "../components";
|
|
7
7
|
import { UnsavedChangesDialog } from "../components/UnsavedChangesDialog";
|
|
8
|
+
import { EntitySidePanel } from "./EntitySidePanel";
|
|
8
9
|
|
|
9
10
|
export type SideDialogController = {
|
|
10
11
|
blocked: boolean,
|
|
@@ -157,7 +158,8 @@ function SideDialogView({
|
|
|
157
158
|
}}
|
|
158
159
|
>
|
|
159
160
|
<ErrorBoundary>
|
|
160
|
-
{
|
|
161
|
+
{/* Lazy render EntitySidePanel from props for better performance */}
|
|
162
|
+
{panel.component ?? (panel.additional ? <EntitySidePanel {...(panel.additional as EntitySidePanelProps)} /> : null)}
|
|
161
163
|
</ErrorBoundary>
|
|
162
164
|
</div>}
|
|
163
165
|
|
package/src/core/index.tsx
CHANGED
|
@@ -75,21 +75,21 @@ export const PropertyFieldBinding = React.memo(PropertyFieldBindingInternal, (a:
|
|
|
75
75
|
}) as typeof PropertyFieldBindingInternal;
|
|
76
76
|
|
|
77
77
|
function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Record<string, any> = any>
|
|
78
|
-
({
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
78
|
+
({
|
|
79
|
+
propertyKey,
|
|
80
|
+
property,
|
|
81
|
+
context,
|
|
82
|
+
includeDescription,
|
|
83
|
+
underlyingValueHasChanged,
|
|
84
|
+
disabled: disabledProp,
|
|
85
|
+
partOfArray,
|
|
86
|
+
partOfBlock,
|
|
87
|
+
minimalistView,
|
|
88
|
+
autoFocus,
|
|
89
|
+
index,
|
|
90
|
+
size,
|
|
91
|
+
onPropertyChange,
|
|
92
|
+
}: PropertyFieldBindingProps<T, M>): ReactElement<PropertyFieldBindingProps<T, M>> {
|
|
93
93
|
|
|
94
94
|
const authController = useAuthController();
|
|
95
95
|
const customizationController = useCustomizationController();
|
|
@@ -175,7 +175,7 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
|
|
|
175
175
|
return <FieldInternal
|
|
176
176
|
Component={Component as ComponentType<FieldProps>}
|
|
177
177
|
componentProps={componentProps}
|
|
178
|
-
formexFieldProps={fieldProps}/>;
|
|
178
|
+
formexFieldProps={fieldProps} />;
|
|
179
179
|
}}
|
|
180
180
|
</Field>
|
|
181
181
|
);
|
|
@@ -185,39 +185,54 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
|
|
|
185
185
|
type ResolvedPropertyFieldBindingProps<T extends CMSType = CMSType, M extends Record<string, any> = any> =
|
|
186
186
|
Omit<PropertyFieldBindingProps<T, M>, "property">
|
|
187
187
|
& {
|
|
188
|
-
|
|
189
|
-
};
|
|
188
|
+
property: ResolvedProperty<T>
|
|
189
|
+
};
|
|
190
190
|
|
|
191
191
|
function FieldInternal<T extends CMSType, CustomProps, M extends Record<string, any>>
|
|
192
|
-
({
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
192
|
+
({
|
|
193
|
+
Component,
|
|
194
|
+
componentProps: {
|
|
195
|
+
propertyKey,
|
|
196
|
+
property,
|
|
197
|
+
includeDescription,
|
|
198
|
+
underlyingValueHasChanged,
|
|
199
|
+
partOfArray,
|
|
200
|
+
partOfBlock,
|
|
201
|
+
minimalistView,
|
|
202
|
+
autoFocus,
|
|
203
|
+
context,
|
|
204
|
+
disabled,
|
|
205
|
+
size,
|
|
206
|
+
onPropertyChange
|
|
207
|
+
},
|
|
208
|
+
formexFieldProps
|
|
209
|
+
}:
|
|
210
|
+
{
|
|
211
|
+
Component: ComponentType<FieldProps<T, any, M>>,
|
|
212
|
+
componentProps: ResolvedPropertyFieldBindingProps<T, M>,
|
|
213
|
+
formexFieldProps: FormexFieldProps<T, any>
|
|
214
|
+
}) {
|
|
215
215
|
|
|
216
216
|
const { plugins } = useCustomizationController();
|
|
217
217
|
|
|
218
218
|
const customFieldProps: any = property.customProps;
|
|
219
219
|
const value = formexFieldProps.field.value;
|
|
220
|
-
|
|
220
|
+
|
|
221
|
+
// Get error for this field path, but avoid string indexing issues
|
|
222
|
+
// When an array has a string error like "Tags should have unique values",
|
|
223
|
+
// accessing errors["tags"]["0"] returns "T" (string indexing).
|
|
224
|
+
// We traverse the path manually and stop if we hit a string.
|
|
225
|
+
let error: any = formexFieldProps.form.errors;
|
|
226
|
+
for (const part of propertyKey.split(".")) {
|
|
227
|
+
if (error === undefined || error === null) break;
|
|
228
|
+
if (typeof error === "string") {
|
|
229
|
+
// Parent is a string error, children shouldn't inherit individual characters
|
|
230
|
+
error = undefined;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
error = error[part];
|
|
234
|
+
}
|
|
235
|
+
|
|
221
236
|
const touched = getIn(formexFieldProps.form.touched, propertyKey);
|
|
222
237
|
|
|
223
238
|
const showError: boolean = error &&
|
|
@@ -272,7 +287,7 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
|
|
|
272
287
|
return (
|
|
273
288
|
<ErrorBoundary>
|
|
274
289
|
|
|
275
|
-
<UsedComponent {...cmsFieldProps}/>
|
|
290
|
+
<UsedComponent {...cmsFieldProps} />
|
|
276
291
|
|
|
277
292
|
{underlyingValueHasChanged && !isSubmitting &&
|
|
278
293
|
<Typography variant={"caption"} className={"ml-3.5"}>
|
|
@@ -29,9 +29,10 @@ export function StorageItemPreview({
|
|
|
29
29
|
}: StorageItemPreviewProps) {
|
|
30
30
|
|
|
31
31
|
return (
|
|
32
|
-
<div className={cls(
|
|
32
|
+
<div className={cls(
|
|
33
33
|
"relative border-box flex items-center justify-center",
|
|
34
34
|
size === "large" ? "min-w-[220px] min-h-[220px] max-w-[220px]" : "min-w-[118px] min-h-[118px] max-w-[118px]",
|
|
35
|
+
paperMixin,
|
|
35
36
|
className)}>
|
|
36
37
|
|
|
37
38
|
{!placeholder && !disabled &&
|
|
@@ -19,17 +19,17 @@ type DateTimeFieldProps = FieldProps<Date>;
|
|
|
19
19
|
* @group Form fields
|
|
20
20
|
*/
|
|
21
21
|
export function DateTimeFieldBinding({
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
propertyKey,
|
|
23
|
+
value,
|
|
24
|
+
setValue,
|
|
25
|
+
autoFocus,
|
|
26
|
+
error,
|
|
27
|
+
showError,
|
|
28
|
+
disabled,
|
|
29
|
+
touched,
|
|
30
|
+
property,
|
|
31
|
+
includeDescription
|
|
32
|
+
}: DateTimeFieldProps) {
|
|
33
33
|
|
|
34
34
|
const { locale } = useCustomizationController();
|
|
35
35
|
const internalValue = value || null;
|
|
@@ -50,21 +50,22 @@ export function DateTimeFieldBinding({
|
|
|
50
50
|
mode={property.mode}
|
|
51
51
|
clearable={property.clearable}
|
|
52
52
|
locale={locale}
|
|
53
|
+
timezone={property.timezone}
|
|
53
54
|
error={showError}
|
|
54
55
|
disabled={disabled}
|
|
55
56
|
label={<LabelWithIcon
|
|
56
57
|
icon={getIconForProperty(property, "small")}
|
|
57
58
|
required={property.validation?.required}
|
|
58
59
|
className={showError ? "text-red-500 dark:text-red-500" : "text-text-secondary dark:text-text-secondary-dark"}
|
|
59
|
-
title={property.name}/>}
|
|
60
|
+
title={property.name} />}
|
|
60
61
|
/>
|
|
61
62
|
</PropertyIdCopyTooltip>
|
|
62
63
|
|
|
63
64
|
<FieldHelperText includeDescription={includeDescription}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
showError={showError}
|
|
66
|
+
error={error}
|
|
67
|
+
disabled={disabled}
|
|
68
|
+
property={property} />
|
|
68
69
|
|
|
69
70
|
</>
|
|
70
71
|
);
|