@rebasepro/admin 0.12.1-canary.gf5f1d39 → 0.13.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/README.md +1 -1
- package/dist/{CollectionEditorDialog-Dpc75wIZ.js → CollectionEditorDialog-CjXkWZ64.js} +75 -62
- package/dist/{CollectionEditorDialog-Dpc75wIZ.js.map → CollectionEditorDialog-CjXkWZ64.js.map} +1 -1
- package/dist/{PropertyEditView-DH3XZC2x.js → PropertyEditView-W8I3YV89.js} +36 -16
- package/dist/{PropertyEditView-DH3XZC2x.js.map → PropertyEditView-W8I3YV89.js.map} +1 -1
- package/dist/{RouterCollectionsStudioView-BZLq4MGp.js → RouterCollectionsStudioView-BsLTNoqX.js} +5 -5
- package/dist/{RouterCollectionsStudioView-BZLq4MGp.js.map → RouterCollectionsStudioView-BsLTNoqX.js.map} +1 -1
- package/dist/collection_editor/serializable_types.d.ts +4 -1
- package/dist/collection_editor/ui/collection_editor/CollectionRelationsTab.d.ts +1 -0
- package/dist/collection_editor/useLocalCollectionsConfigController.d.ts +8 -0
- package/dist/collection_editor_ui.js +5 -5
- package/dist/collection_editor_ui.js.map +1 -1
- package/dist/components/CollectionTableBinding/column_utils.d.ts +17 -0
- package/dist/components/CollectionViewBinding/CollectionViewStartActions.d.ts +7 -2
- package/dist/components/CollectionViewBinding/SortButton.d.ts +24 -0
- package/dist/components/CollectionViewBinding/SplitListCloseButton.d.ts +10 -0
- package/dist/components/CollectionViewBinding/SplitViewContext.d.ts +23 -0
- package/dist/components/CollectionViewBinding/hooks/useKanbanDragAndDrop.d.ts +26 -0
- package/dist/components/DetailViewBinding.d.ts +5 -0
- package/dist/components/EditFormActions.d.ts +12 -1
- package/dist/components/EditViewBinding.d.ts +6 -1
- package/dist/components/EntityIdentityBar.d.ts +53 -0
- package/dist/components/EntityInspector.d.ts +35 -0
- package/dist/components/EntityPreviewNesting.d.ts +25 -0
- package/dist/components/EntityViewBinding.d.ts +9 -0
- package/dist/components/InlineEntityPreview.d.ts +47 -0
- package/dist/components/history/EntityHistoryView.d.ts +4 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/editor.js +18 -10
- package/dist/editor.js.map +1 -1
- package/dist/{export-BzIpUdSK.js → export-J79rMoNj.js} +2 -2
- package/dist/{export-BzIpUdSK.js.map → export-J79rMoNj.js.map} +1 -1
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/EntityFormActions.d.ts +11 -1
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/components/FieldBlock.d.ts +30 -0
- package/dist/form/components/FormRail.d.ts +18 -0
- package/dist/form/components/FormSections.d.ts +16 -0
- package/dist/form/components/index.d.ts +3 -2
- package/dist/form/components/useRailVisible.d.ts +24 -0
- package/dist/form/field_bindings/BinaryFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/DateTimeFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/GeopointFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MultiSelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/UserSelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/VectorFieldBinding.d.ts +1 -1
- package/dist/{history-g9688IaK.js → history-D7L_JlLO.js} +35 -33
- package/dist/history-D7L_JlLO.js.map +1 -0
- package/dist/hooks/navigation/utils.d.ts +16 -0
- package/dist/hooks/useBuildSidePanel.d.ts +14 -0
- package/dist/hooks/useEntityDisplayTitle.d.ts +18 -0
- package/dist/hooks/useHistory.d.ts +7 -0
- package/dist/hooks/useRecordActions.d.ts +17 -0
- package/dist/{import-BjUG-cIY.js → import-BvYl--U4.js} +2 -2
- package/dist/{import-BjUG-cIY.js.map → import-BvYl--U4.js.map} +1 -1
- package/dist/index.js +106 -35
- package/dist/index.js.map +1 -1
- package/dist/markdown-CklalUUk.js.map +1 -1
- package/dist/preview/components/InlineEntityListPreview.d.ts +15 -0
- package/dist/preview/index.d.ts +1 -0
- package/dist/preview/property_previews/ArrayOfReferencesPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfRelationsPreview.d.ts +1 -1
- package/dist/types/components/EntityFormActionsProps.d.ts +0 -1
- package/dist/types/components/EntityFormProps.d.ts +0 -5
- package/dist/types/fields.d.ts +24 -0
- package/dist/{util-B5fJm1FA.js → util-GiwPgxnL.js} +2106 -1117
- package/dist/util-GiwPgxnL.js.map +1 -0
- package/package.json +32 -34
- package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
- package/src/collection_editor/serializable_types.ts +4 -3
- package/src/collection_editor/serializable_utils.ts +51 -17
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +65 -22
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +38 -30
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +3 -1
- package/src/collection_editor/ui/collection_editor/RouterCollectionStudioView.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +16 -0
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +127 -15
- package/src/collection_editor/validateCollectionJson.ts +3 -3
- package/src/components/AdminModeSyncer.tsx +1 -1
- package/src/components/CollectionTableBinding/PropertyTableCell.tsx +10 -2
- package/src/components/CollectionTableBinding/column_utils.tsx +59 -2
- package/src/components/CollectionTableBinding/table_bindings.tsx +2 -1
- package/src/components/CollectionViewBinding/CollectionBoardViewBinding.tsx +23 -16
- package/src/components/CollectionViewBinding/CollectionViewActions.tsx +7 -1
- package/src/components/CollectionViewBinding/CollectionViewBinding.tsx +9 -2
- package/src/components/CollectionViewBinding/CollectionViewStartActions.tsx +47 -12
- package/src/components/CollectionViewBinding/SortButton.tsx +189 -0
- package/src/components/CollectionViewBinding/SplitListCloseButton.tsx +33 -0
- package/src/components/CollectionViewBinding/SplitListView.tsx +18 -3
- package/src/components/CollectionViewBinding/SplitViewContext.tsx +34 -0
- package/src/components/CollectionViewBinding/hooks/useKanbanDragAndDrop.ts +48 -9
- package/src/components/CollectionViewBinding/useBoardDataController.tsx +80 -25
- package/src/components/CollectionViewBinding/usePreviewSlots.ts +18 -6
- package/src/components/DefaultAppBar.tsx +1 -1
- package/src/components/DefaultDrawer.tsx +1 -1
- package/src/components/DetailViewBinding.tsx +112 -148
- package/src/components/DrawerNavigationItem.tsx +1 -1
- package/src/components/EditFormActions.tsx +54 -129
- package/src/components/EditViewBinding.tsx +202 -99
- package/src/components/EntityIdentityBar.tsx +288 -0
- package/src/components/EntityInspector.tsx +137 -0
- package/src/components/EntityPreviewBinding.tsx +6 -2
- package/src/components/EntityPreviewNesting.tsx +50 -0
- package/src/components/EntityViewBinding.tsx +35 -32
- package/src/components/HomePage/FavouritesView.tsx +1 -1
- package/src/components/HomePage/NavigationCardBinding.tsx +1 -1
- package/src/components/HomePage/SmallNavigationCard.tsx +1 -1
- package/src/components/InlineEntityPreview.tsx +149 -0
- package/src/components/RebaseLayout.tsx +1 -1
- package/src/components/RebaseNavigation.tsx +45 -5
- package/src/components/RebaseRouteDefs.tsx +1 -1
- package/src/components/SelectableTable/SelectableTable.tsx +2 -2
- package/src/components/SidePanelBinding.tsx +19 -13
- package/src/components/UserSelector.tsx +12 -6
- package/src/components/common/default_entity_actions.tsx +4 -3
- package/src/components/history/EntityHistoryEntry.tsx +28 -7
- package/src/components/history/EntityHistoryView.tsx +29 -24
- package/src/components/history/LastEditedByIndicator.tsx +4 -3
- package/src/components/index.ts +2 -0
- package/src/data_import/utils/get_import_inference_type.ts +6 -0
- package/src/form/EntityForm.tsx +267 -179
- package/src/form/EntityFormActions.tsx +50 -99
- package/src/form/EntityFormBinding.tsx +4 -2
- package/src/form/PropertyFieldBinding.tsx +4 -0
- package/src/form/components/FieldBlock.tsx +119 -0
- package/src/form/components/FormRail.tsx +125 -0
- package/src/form/components/FormSections.tsx +118 -0
- package/src/form/components/index.tsx +3 -2
- package/src/form/components/useRailVisible.tsx +46 -0
- package/src/form/field_bindings/BinaryFieldBinding.tsx +3 -2
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +3 -2
- package/src/form/field_bindings/GeopointFieldBinding.tsx +3 -2
- package/src/form/field_bindings/MapFieldBinding.tsx +1 -2
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +3 -2
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +2 -1
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -1
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +2 -1
- package/src/form/field_bindings/RelationFieldBinding.tsx +6 -4
- package/src/form/field_bindings/RepeatFieldBinding.tsx +4 -1
- package/src/form/field_bindings/SelectFieldBinding.tsx +3 -2
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +31 -8
- package/src/form/field_bindings/SwitchFieldBinding.tsx +7 -3
- package/src/form/field_bindings/TextFieldBinding.tsx +18 -16
- package/src/form/field_bindings/UserSelectFieldBinding.tsx +3 -2
- package/src/form/field_bindings/VectorFieldBinding.tsx +2 -1
- package/src/hooks/navigation/useBuildUrlController.tsx +1 -1
- package/src/hooks/navigation/useTopLevelNavigation.ts +18 -7
- package/src/hooks/navigation/utils.ts +20 -0
- package/src/hooks/useBuildSideDialogsController.tsx +2 -2
- package/src/hooks/useBuildSidePanel.tsx +22 -61
- package/src/hooks/useEntityDisplayTitle.tsx +60 -0
- package/src/hooks/useHistory.ts +20 -10
- package/src/hooks/useRecordActions.tsx +69 -0
- package/src/hooks/useResolvedUsers.ts +10 -5
- package/src/preview/PropertyPreview.tsx +48 -22
- package/src/preview/components/InlineEntityListPreview.tsx +42 -0
- package/src/preview/components/ReferencePreview.tsx +34 -14
- package/src/preview/components/RelationPreview.tsx +34 -14
- package/src/preview/index.ts +1 -0
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +24 -1
- package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +25 -1
- package/src/routes/RebaseRoute.tsx +2 -2
- package/src/types/components/EntityFormActionsProps.tsx +0 -1
- package/src/types/components/EntityFormProps.tsx +0 -6
- package/src/types/fields.tsx +27 -0
- package/dist/form/components/FormEntry.d.ts +0 -6
- package/dist/form/components/FormLayout.d.ts +0 -5
- package/dist/history-g9688IaK.js.map +0 -1
- package/dist/util-B5fJm1FA.js.map +0 -1
- package/src/form/components/FormEntry.tsx +0 -22
- package/src/form/components/FormLayout.tsx +0 -16
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
HistoryIcon,
|
|
19
19
|
IconButton,
|
|
20
20
|
Maximize2Icon,
|
|
21
|
+
MenuItem,
|
|
21
22
|
Skeleton,
|
|
22
23
|
Tab,
|
|
23
24
|
Tabs,
|
|
@@ -42,13 +43,18 @@ import { EntityFormBinding } from "../form";
|
|
|
42
43
|
import type { EntityFormBindingProps } from "../form";
|
|
43
44
|
import type { OnUpdateParams } from "../types/components/EntityFormProps";
|
|
44
45
|
import { EditFormActions } from "./EditFormActions";
|
|
45
|
-
import {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
import { EntityIdentityBar } from "./EntityIdentityBar";
|
|
47
|
+
import { SplitListCloseButton } from "./CollectionViewBinding/SplitListCloseButton";
|
|
48
|
+
import { useRecordActions } from "../hooks/useRecordActions";
|
|
49
|
+
import { useSideDialogContext } from "./SideDialogs";
|
|
50
|
+
import { useAdminContext } from "../hooks/useAdminContext";
|
|
51
|
+
import { EntityInspector, InspectorTab } from "./EntityInspector";
|
|
52
|
+
import { useEntityDisplayTitle } from "../hooks/useEntityDisplayTitle";
|
|
48
53
|
import { createFormexStub, getEntityFromCache } from "@rebasepro/app";
|
|
49
54
|
import { usePermissions } from "@rebasepro/app";
|
|
50
55
|
import { useUrlController } from "../hooks/navigation/contexts/UrlContext";
|
|
51
|
-
import {
|
|
56
|
+
import { withViewMode } from "../util/view_mode";
|
|
57
|
+
import { useNavigate } from "react-router";
|
|
52
58
|
|
|
53
59
|
import { MAIN_TAB_VALUE, JSON_TAB_VALUE, HISTORY_TAB_VALUE } from "../util/view_constants";
|
|
54
60
|
export { MAIN_TAB_VALUE, JSON_TAB_VALUE, HISTORY_TAB_VALUE };
|
|
@@ -85,6 +91,11 @@ export interface EditViewBindingProps<M extends Record<string, unknown> = Record
|
|
|
85
91
|
navigateBack?: () => void;
|
|
86
92
|
layout?: "side_panel" | "full_screen" | "split" | "dialog";
|
|
87
93
|
barActions?: (params: BarActionsParams) => React.ReactNode;
|
|
94
|
+
/**
|
|
95
|
+
* Controls the owning panel puts at the identity bar's leading edge, ahead
|
|
96
|
+
* of the breadcrumb — the side panel's close button.
|
|
97
|
+
*/
|
|
98
|
+
barActionsStart?: React.ReactNode;
|
|
88
99
|
formProps?: Partial<EntityFormBindingProps<M>>,
|
|
89
100
|
/**
|
|
90
101
|
* Pre-populate the form with these values when creating a new entity.
|
|
@@ -180,6 +191,7 @@ export function EditViewBindingInner<M extends Record<string, unknown>>({
|
|
|
180
191
|
dataLoading,
|
|
181
192
|
layout = "side_panel",
|
|
182
193
|
barActions,
|
|
194
|
+
barActionsStart,
|
|
183
195
|
status,
|
|
184
196
|
setStatus,
|
|
185
197
|
formProps,
|
|
@@ -198,6 +210,7 @@ export function EditViewBindingInner<M extends Record<string, unknown>>({
|
|
|
198
210
|
const ResolvedCollectionView = useComponentOverride("Collection.View", CollectionViewBinding);
|
|
199
211
|
|
|
200
212
|
const context = useRebaseContext();
|
|
213
|
+
const adminContext = useAdminContext();
|
|
201
214
|
const urlController = useUrlController();
|
|
202
215
|
const navigate = useNavigate();
|
|
203
216
|
|
|
@@ -265,22 +278,30 @@ parentEntityIds,
|
|
|
265
278
|
const customViewsCount = customViews?.length ?? 0;
|
|
266
279
|
const includeJsonView = collection.includeJsonView === undefined ? true : collection.includeJsonView;
|
|
267
280
|
const includeHistoryView = Boolean(collection.history);
|
|
268
|
-
|
|
281
|
+
// The inspector holds the developer tools; the tab strip holds destinations.
|
|
282
|
+
// A strip with only the record in it has nothing to choose between, so it
|
|
283
|
+
// does not render at all.
|
|
284
|
+
const hasAdditionalViews = customViewsCount > 0 || subcollectionsCount > 0;
|
|
269
285
|
|
|
270
286
|
const {
|
|
271
287
|
resolvedEntityViews
|
|
272
288
|
} = resolvedSelectedEntityView(customViews, customizationController, undefined, canEdit);
|
|
273
289
|
|
|
290
|
+
// JSON and history are no longer tab values, but a bookmarked or in-flight
|
|
291
|
+
// URL may still name one. They resolve to the record, and open the
|
|
292
|
+
// inspector on that pane, so an old link keeps working.
|
|
293
|
+
const legacyInspectorTab = selectedTab === JSON_TAB_VALUE
|
|
294
|
+
? "json"
|
|
295
|
+
: selectedTab === HISTORY_TAB_VALUE ? "history" : undefined;
|
|
296
|
+
|
|
274
297
|
const validTabValues = useMemo(() => {
|
|
275
298
|
const set = new Set<string>([
|
|
276
299
|
MAIN_TAB_VALUE,
|
|
277
|
-
...(includeJsonView ? [JSON_TAB_VALUE] : []),
|
|
278
|
-
...(includeHistoryView ? [HISTORY_TAB_VALUE] : []),
|
|
279
300
|
...resolvedEntityViews.map(v => v.key),
|
|
280
301
|
...subcollections.map(s => s.slug)
|
|
281
302
|
]);
|
|
282
303
|
return set;
|
|
283
|
-
}, [
|
|
304
|
+
}, [resolvedEntityViews, subcollections]);
|
|
284
305
|
|
|
285
306
|
const activeTab = validTabValues.has(selectedTab) ? selectedTab : MAIN_TAB_VALUE;
|
|
286
307
|
|
|
@@ -289,7 +310,6 @@ parentEntityIds,
|
|
|
289
310
|
selectedSecondaryForm
|
|
290
311
|
} = resolvedSelectedEntityView(customViews, customizationController, activeTab, canEdit);
|
|
291
312
|
|
|
292
|
-
const actionsAtTheBottom = layout === "side_panel" || layout === "dialog" || selectedEntityView?.includeActions === "bottom";
|
|
293
313
|
|
|
294
314
|
const mainViewVisible = activeTab === MAIN_TAB_VALUE || Boolean(selectedSecondaryForm);
|
|
295
315
|
|
|
@@ -381,35 +401,76 @@ parentEntityIds,
|
|
|
381
401
|
|
|
382
402
|
const globalLoading = (dataLoading && !usedEntity) || (canEdit === undefined && (status === "existing" || status === "copy"));
|
|
383
403
|
|
|
384
|
-
|
|
385
|
-
const jsonTabMounted = mountedTabsRef.current.has(JSON_TAB_VALUE);
|
|
386
|
-
const jsonView = (activeTab === JSON_TAB_VALUE || jsonTabMounted) ? <div
|
|
387
|
-
className={cls("relative flex-1 h-full overflow-auto w-full",
|
|
388
|
-
{ "hidden": activeTab !== JSON_TAB_VALUE })}
|
|
389
|
-
key={"json_view"}
|
|
390
|
-
role="tabpanel">
|
|
391
|
-
<ErrorBoundary>
|
|
392
|
-
<JsonPreviewBinding
|
|
393
|
-
values={formContext?.values ?? entity?.values ?? {}} />
|
|
394
|
-
</ErrorBoundary>
|
|
395
|
-
</div> : null;
|
|
404
|
+
/* ---- identity bar ---------------------------------------------------- */
|
|
396
405
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
406
|
+
const displayTitle = useEntityDisplayTitle({
|
|
407
|
+
collection,
|
|
408
|
+
values: (formContext?.values ?? usedEntity?.values) as Record<string, unknown> | undefined,
|
|
409
|
+
entityId,
|
|
410
|
+
status
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
const formex = formContext?.formex;
|
|
414
|
+
const hasFormErrors = Boolean(formex && Object.keys(formex.errors).length > 0 && formex.submitCount > 0);
|
|
415
|
+
// Same rule the footer used: an untouched existing record has nothing to save.
|
|
416
|
+
const saveDisabled = Boolean(
|
|
417
|
+
!formContext
|
|
418
|
+
|| formContext.disabled
|
|
419
|
+
|| formex?.isSubmitting
|
|
420
|
+
|| (status === "existing" && !formex?.dirty)
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
const [inspectorTab, setInspectorTab] = useState<InspectorTab | null>(null);
|
|
424
|
+
// A save adds a revision, and the inspector can be open while it happens:
|
|
425
|
+
// Save lives in the identity bar, above the panel. Counting saves gives the
|
|
426
|
+
// history list something to react to.
|
|
427
|
+
const [savedCount, setSavedCount] = useState(0);
|
|
428
|
+
|
|
429
|
+
/* ---- record actions, in the bar's overflow menu ---------------------- */
|
|
430
|
+
|
|
431
|
+
const sideDialogContext = useSideDialogContext();
|
|
432
|
+
const canCloseAfterSave = layout === "side_panel" || layout === "dialog";
|
|
433
|
+
|
|
434
|
+
const recordActions = useRecordActions({
|
|
435
|
+
collection,
|
|
436
|
+
path,
|
|
437
|
+
entity: usedEntity
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const recordActionItems = usedEntity && recordActions.length
|
|
441
|
+
? recordActions.map((action, index) => {
|
|
442
|
+
const clickProps = {
|
|
443
|
+
view: "form" as const,
|
|
444
|
+
entity: usedEntity,
|
|
445
|
+
path,
|
|
446
|
+
collection,
|
|
447
|
+
context,
|
|
448
|
+
sidePanelController: adminContext.sidePanelController,
|
|
449
|
+
openEntityMode: layout,
|
|
450
|
+
navigateBack: navigateBack ?? (() => undefined),
|
|
451
|
+
formContext
|
|
452
|
+
};
|
|
453
|
+
const enabled = !action.isEnabled || action.isEnabled(clickProps as never);
|
|
454
|
+
return (
|
|
455
|
+
<MenuItem key={action.key ?? action.name ?? index}
|
|
456
|
+
disabled={!enabled}
|
|
457
|
+
onClick={() => action.onClick(clickProps as never)}>
|
|
458
|
+
{getIcon(action.icon, undefined, undefined, "smallest")}
|
|
459
|
+
{action.name}
|
|
460
|
+
</MenuItem>
|
|
461
|
+
);
|
|
462
|
+
})
|
|
463
|
+
: null;
|
|
464
|
+
|
|
465
|
+
// Plugin form actions (Autofill and friends) render inline in the bar; the
|
|
466
|
+
// form no longer has a footer to put them in.
|
|
467
|
+
const formPluginActions = useSlot("form.actions", formActionTopProps);
|
|
468
|
+
|
|
469
|
+
// A URL still naming the old `json`/`history` tab opens the inspector on
|
|
470
|
+
// that pane instead of 404-ing into the record with nothing shown.
|
|
471
|
+
useEffect(() => {
|
|
472
|
+
if (legacyInspectorTab) setInspectorTab(legacyInspectorTab);
|
|
473
|
+
}, [legacyInspectorTab]);
|
|
413
474
|
|
|
414
475
|
const subCollectionsViews = childViews && childViews.map(({ collection: subcollection }) => {
|
|
415
476
|
const subcollectionId = subcollection.slug;
|
|
@@ -520,7 +581,10 @@ parentEntityIds,
|
|
|
520
581
|
entity={entity}
|
|
521
582
|
initialDirtyValues={initialDirtyValues}
|
|
522
583
|
openEntityMode={layout}
|
|
523
|
-
|
|
584
|
+
// Save and Discard live in the identity bar now, where they stay
|
|
585
|
+
// visible while the form scrolls. The form's own footer would be a
|
|
586
|
+
// second copy of them.
|
|
587
|
+
showDefaultActions={false}
|
|
524
588
|
initialStatus={status}
|
|
525
589
|
className={cls((!mainViewVisible || !canEdit) && !selectedSecondaryForm ? "hidden" : "", formProps?.className)}
|
|
526
590
|
EntityFormActionsComponent={ResolvedFormActions as React.FC<typeof ResolvedFormActions extends React.ComponentType<infer P> ? P : never>}
|
|
@@ -540,6 +604,7 @@ parentEntityIds,
|
|
|
540
604
|
formProps?.onFormContextReady?.(formContext);
|
|
541
605
|
}}
|
|
542
606
|
onSaved={(params) => {
|
|
607
|
+
setSavedCount(count => count + 1);
|
|
543
608
|
const res = {
|
|
544
609
|
...params,
|
|
545
610
|
selectedTab: MAIN_TAB_VALUE === activeTab ? undefined : activeTab
|
|
@@ -601,9 +666,9 @@ parentEntityIds,
|
|
|
601
666
|
);
|
|
602
667
|
});
|
|
603
668
|
|
|
604
|
-
const
|
|
605
|
-
|
|
606
|
-
|
|
669
|
+
const fullScreenButton = !barActions && // Not in split: the list panel beside it carries the close control,
|
|
670
|
+
// and an expand button there competes with it.
|
|
671
|
+
(layout === "side_panel" || layout === "dialog") && entityId ? (
|
|
607
672
|
<Tooltip title={"Open full screen"}>
|
|
608
673
|
<IconButton
|
|
609
674
|
size="small"
|
|
@@ -620,75 +685,113 @@ parentEntityIds,
|
|
|
620
685
|
|
|
621
686
|
let result = <div className="relative flex flex-col h-full w-full bg-white dark:bg-surface-800">
|
|
622
687
|
|
|
623
|
-
|
|
624
|
-
|
|
688
|
+
<EntityIdentityBar
|
|
689
|
+
collection={collection as AdminCollection}
|
|
690
|
+
title={displayTitle}
|
|
691
|
+
entityId={status === "existing" ? entityId : undefined}
|
|
692
|
+
status={status}
|
|
693
|
+
dirty={Boolean(formContext?.formex?.dirty)}
|
|
694
|
+
saving={Boolean(formContext?.isSaving)}
|
|
695
|
+
hasErrors={hasFormErrors}
|
|
696
|
+
saveDisabled={!canEdit || saveDisabled}
|
|
697
|
+
// Full screen replaces the collection entirely, leaving browser Back
|
|
698
|
+
// as the only route to it. The detail view has carried this arrow
|
|
699
|
+
// for that reason; the edit view is reached the same way.
|
|
700
|
+
onBack={layout === "full_screen"
|
|
701
|
+
? () => navigate(withViewMode(urlController.buildUrlCollectionPath(path)))
|
|
702
|
+
: undefined}
|
|
703
|
+
onSave={canEdit && formContext ? () => {
|
|
704
|
+
sideDialogContext.setPendingClose?.(false);
|
|
705
|
+
formContext.submit();
|
|
706
|
+
} : undefined}
|
|
707
|
+
onSaveAndClose={canEdit && formContext && canCloseAfterSave ? () => {
|
|
708
|
+
sideDialogContext.setPendingClose?.(true);
|
|
709
|
+
formContext.submit();
|
|
710
|
+
} : undefined}
|
|
711
|
+
onDiscard={canEdit && formContext ? () => formContext.formex.resetForm() : undefined}
|
|
712
|
+
onInspect={includeJsonView ? () => setInspectorTab("json") : undefined}
|
|
713
|
+
onViewHistory={includeHistoryView ? () => setInspectorTab("history") : undefined}
|
|
714
|
+
recordActions={recordActionItems}
|
|
715
|
+
pluginActions={formPluginActions}
|
|
716
|
+
leading={<>
|
|
717
|
+
{barActionsStart}
|
|
718
|
+
{/* Split view: closing the list is opening this record
|
|
719
|
+
full screen, and the control for it belongs at this
|
|
720
|
+
bar's leading edge. */}
|
|
721
|
+
{layout === "split" && <SplitListCloseButton/>}
|
|
722
|
+
</>}
|
|
723
|
+
trailing={<>
|
|
724
|
+
{pluginActionsTop}
|
|
725
|
+
{fullScreenButton}
|
|
726
|
+
{barActions?.({
|
|
727
|
+
path,
|
|
728
|
+
entityId,
|
|
729
|
+
values: formContext?.values ?? usedEntity?.values ?? {},
|
|
730
|
+
status
|
|
731
|
+
})}
|
|
732
|
+
</>}
|
|
733
|
+
/>
|
|
625
734
|
|
|
626
|
-
|
|
735
|
+
{/* Destinations only: the record is the page, so its tab leads rather
|
|
736
|
+
than sitting third behind two unlabelled developer tools. The row
|
|
737
|
+
disappears entirely when there is nowhere else to go. */}
|
|
738
|
+
{hasAdditionalViews && <div className={cls(
|
|
739
|
+
"h-10 shrink-0 flex items-stretch border-b px-2 min-w-0",
|
|
740
|
+
defaultBorderMixin
|
|
741
|
+
)}>
|
|
742
|
+
<Tabs
|
|
743
|
+
className={"!w-full"}
|
|
744
|
+
innerClassName={"h-full"}
|
|
745
|
+
variant={"boxy"}
|
|
746
|
+
value={activeTab}
|
|
747
|
+
onValueChange={(value) => {
|
|
748
|
+
onSideTabClick(value);
|
|
749
|
+
}}>
|
|
627
750
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
{pluginActionsTop}
|
|
636
|
-
|
|
637
|
-
{hasAdditionalViews && <div className={"flex-1 flex justify-end min-w-0 shrink-0"}>
|
|
638
|
-
<Tabs
|
|
639
|
-
className={"!w-fit max-w-full"}
|
|
640
|
-
value={activeTab}
|
|
641
|
-
onValueChange={(value) => {
|
|
642
|
-
onSideTabClick(value);
|
|
643
|
-
}}>
|
|
644
|
-
|
|
645
|
-
{includeJsonView && <Tab
|
|
646
|
-
disabled={!hasAdditionalViews}
|
|
647
|
-
value={JSON_TAB_VALUE}
|
|
648
|
-
className={"text-sm"}>
|
|
649
|
-
<CodeIcon size={iconSize.smallest} />
|
|
650
|
-
</Tab>}
|
|
651
|
-
|
|
652
|
-
{includeHistoryView && <Tab
|
|
653
|
-
disabled={!hasAdditionalViews}
|
|
654
|
-
value={HISTORY_TAB_VALUE}
|
|
655
|
-
className={"text-sm"}>
|
|
656
|
-
<HistoryIcon size={iconSize.smallest} />
|
|
657
|
-
</Tab>}
|
|
658
|
-
|
|
659
|
-
<Tab
|
|
660
|
-
disabled={!hasAdditionalViews}
|
|
661
|
-
value={MAIN_TAB_VALUE}
|
|
662
|
-
className={"text-sm min-w-[90px]"}>
|
|
663
|
-
<span className="flex items-center gap-1.5">
|
|
664
|
-
{getIcon(collection.icon, undefined, undefined, "smallest")}
|
|
665
|
-
{collection.singularName ?? collection.name}
|
|
666
|
-
</span>
|
|
667
|
-
</Tab>
|
|
751
|
+
<Tab value={MAIN_TAB_VALUE}>
|
|
752
|
+
<span className="flex items-center gap-1.5">
|
|
753
|
+
{getIcon(collection.icon, undefined, undefined, "smallest")}
|
|
754
|
+
{collection.singularName ?? collection.name}
|
|
755
|
+
</span>
|
|
756
|
+
</Tab>
|
|
668
757
|
|
|
669
|
-
|
|
758
|
+
{customViewTabsStart}
|
|
670
759
|
|
|
671
|
-
|
|
760
|
+
{customViewTabsEnd}
|
|
672
761
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
</div>}
|
|
762
|
+
{subcollectionTabs}
|
|
763
|
+
</Tabs>
|
|
676
764
|
</div>}
|
|
677
765
|
|
|
678
|
-
{
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
{entityView}
|
|
683
|
-
</>}
|
|
766
|
+
{/* The record and the inspector share the space below the bar rather
|
|
767
|
+
than stacking, so the form stays reachable while the panel is open.
|
|
768
|
+
`min-w-0` keeps a wide form from pushing the panel off the edge. */}
|
|
769
|
+
<div className={"flex-1 min-h-0 flex"}>
|
|
684
770
|
|
|
685
|
-
|
|
771
|
+
<div className={"flex-1 min-w-0 flex flex-col"}>
|
|
772
|
+
{globalLoading
|
|
773
|
+
? <EntityFormSkeleton collection={collection} />
|
|
774
|
+
: <>
|
|
775
|
+
{entityReadOnlyView}
|
|
776
|
+
{entityView}
|
|
777
|
+
</>}
|
|
686
778
|
|
|
687
|
-
|
|
779
|
+
{customViewsView}
|
|
688
780
|
|
|
689
|
-
|
|
781
|
+
{subCollectionsViews}
|
|
782
|
+
</div>
|
|
690
783
|
|
|
691
|
-
|
|
784
|
+
<EntityInspector
|
|
785
|
+
tab={inspectorTab}
|
|
786
|
+
onTabChange={setInspectorTab}
|
|
787
|
+
onClose={() => setInspectorTab(null)}
|
|
788
|
+
collection={collection as AdminCollection}
|
|
789
|
+
entity={usedEntity as Entity<Record<string, unknown>> | undefined}
|
|
790
|
+
formContext={formContext as FormContext<Record<string, unknown>> | undefined}
|
|
791
|
+
values={formContext?.values ?? usedEntity?.values}
|
|
792
|
+
refreshToken={savedCount}
|
|
793
|
+
includeHistory={includeHistoryView}/>
|
|
794
|
+
</div>
|
|
692
795
|
|
|
693
796
|
</div>;
|
|
694
797
|
|