@rebasepro/admin 0.3.0 → 0.5.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 +135 -0
- package/dist/{CollectionEditorDialog-D0VqpLPO.js → CollectionEditorDialog-C8E440oK.js} +22 -5
- package/dist/CollectionEditorDialog-C8E440oK.js.map +1 -0
- package/dist/{CollectionsStudioView-Bc3Rxxc2.js → CollectionsStudioView-Brr_b06v.js} +4 -4
- package/dist/{CollectionsStudioView-Bc3Rxxc2.js.map → CollectionsStudioView-Brr_b06v.js.map} +1 -1
- package/dist/{ExportCollectionAction-Ckc-09BQ.js → ExportCollectionAction-D3TTYXrq.js} +35 -27
- package/dist/ExportCollectionAction-D3TTYXrq.js.map +1 -0
- package/dist/{ImportCollectionAction-BqjIrC3Z.js → ImportCollectionAction-Dn7lya6E.js} +2 -2
- package/dist/{ImportCollectionAction-BqjIrC3Z.js.map → ImportCollectionAction-Dn7lya6E.js.map} +1 -1
- package/dist/{PropertyEditView-CvRSV-A2.js → PropertyEditView-ChBleIbN.js} +4 -4
- package/dist/PropertyEditView-ChBleIbN.js.map +1 -0
- package/dist/collection_editor/ui/collection_editor/PropertyEditView.d.ts +1 -0
- package/dist/collection_editor/ui/collection_editor/templates/blog_template.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/templates/pages_template.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/templates/products_template.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/templates/users_template.d.ts +1 -1
- package/dist/collection_editor_ui.js +3 -3
- package/dist/components/CollectionPanel.d.ts +83 -0
- package/dist/components/EntityDetailView.d.ts +0 -3
- package/dist/components/EntityEditView.d.ts +2 -3
- package/dist/components/RebaseRouteDefs.d.ts +1 -1
- package/dist/components/SelectableTable/SelectableTable.d.ts +2 -2
- package/dist/components/SelectableTable/SelectableTableContext.d.ts +1 -1
- package/dist/components/SelectableTable/SelectionStore.d.ts +3 -3
- package/dist/components/admin/index.d.ts +1 -3
- package/dist/components/index.d.ts +1 -0
- package/dist/editor.js +15 -5
- package/dist/editor.js.map +1 -1
- package/dist/hooks/navigation/useBuildNavigationStateController.d.ts +1 -1
- package/dist/hooks/navigation/useResolvedViews.d.ts +2 -5
- package/dist/{index-BCcLwgfe.js → index-D3S9x_RP.js} +2 -2
- package/dist/{index-BCcLwgfe.js.map → index-D3S9x_RP.js.map} +1 -1
- package/dist/{index-DY2k5TtG.js → index-D9RNzm01.js} +3 -3
- package/dist/index-D9RNzm01.js.map +1 -0
- package/dist/{index-UQOMHwt1.js → index-DrrT332R.js} +3 -3
- package/dist/index-DrrT332R.js.map +1 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.js +228 -295
- package/dist/index.js.map +1 -1
- package/dist/util/entity_view_constants.d.ts +6 -0
- package/dist/util/resolutions.d.ts +1 -2
- package/dist/{util-ZM9gQuCv.js → util-COYYD8zr.js} +473 -880
- package/dist/util-COYYD8zr.js.map +1 -0
- package/package.json +9 -10
- package/src/collection_editor/pgColumnToProperty.ts +19 -2
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +2 -1
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +2 -1
- package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/templates/blog_template.ts +1 -1
- package/src/collection_editor/ui/collection_editor/templates/pages_template.ts +1 -1
- package/src/collection_editor/ui/collection_editor/templates/products_template.ts +1 -1
- package/src/collection_editor/ui/collection_editor/templates/users_template.ts +1 -1
- package/src/collection_editor/validateCollectionJson.ts +12 -12
- package/src/components/CollectionPanel.tsx +155 -0
- package/src/components/DefaultDrawer.tsx +2 -2
- package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +5 -2
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +64 -34
- package/src/components/EntityCollectionView/EntityCollectionListView.tsx +8 -1
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +4 -1
- package/src/components/EntityCollectionView/hooks/useCollectionInlineEditor.ts +1 -0
- package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +68 -18
- package/src/components/EntityDetailView.tsx +32 -36
- package/src/components/EntityEditView.tsx +101 -50
- package/src/components/EntityEditViewFormActions.tsx +4 -4
- package/src/components/EntitySidePanel.tsx +50 -14
- package/src/components/PropertyCollectionView.tsx +1 -0
- package/src/components/RebaseRouteDefs.tsx +4 -6
- package/src/components/SelectableTable/SelectableTable.tsx +24 -22
- package/src/components/SelectableTable/SelectableTableContext.tsx +2 -1
- package/src/components/SelectableTable/SelectionStore.ts +4 -4
- package/src/components/admin/index.ts +1 -3
- package/src/components/index.ts +3 -3
- package/src/data_export/export/BasicExportAction.tsx +11 -9
- package/src/data_export/export/ExportCollectionAction.tsx +15 -13
- package/src/editor/editor.tsx +20 -4
- package/src/form/EntityForm.tsx +3 -3
- package/src/form/PropertyFieldBinding.tsx +1 -1
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +1 -1
- package/src/form/field_bindings/MapFieldBinding.tsx +3 -45
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +3 -1
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +2 -3
- package/src/hooks/navigation/useResolvedCollections.ts +2 -10
- package/src/hooks/navigation/useResolvedViews.tsx +6 -48
- package/src/hooks/useBuildSideEntityController.tsx +20 -3
- package/src/index.ts +6 -5
- package/src/util/entity_view_constants.ts +6 -0
- package/src/util/previews.ts +9 -1
- package/src/util/resolutions.ts +2 -6
- package/dist/CollectionEditorDialog-D0VqpLPO.js.map +0 -1
- package/dist/ExportCollectionAction-Ckc-09BQ.js.map +0 -1
- package/dist/PropertyEditView-CvRSV-A2.js.map +0 -1
- package/dist/components/admin/RoleChip.d.ts +0 -4
- package/dist/components/admin/RolesFilterSelect.d.ts +0 -2
- package/dist/components/admin/RolesView.d.ts +0 -4
- package/dist/components/admin/UserRolesSelectField.d.ts +0 -2
- package/dist/components/admin/UsersView.d.ts +0 -4
- package/dist/index-DY2k5TtG.js.map +0 -1
- package/dist/index-UQOMHwt1.js.map +0 -1
- package/dist/util-ZM9gQuCv.js.map +0 -1
- package/src/components/admin/RoleChip.tsx +0 -23
- package/src/components/admin/RolesFilterSelect.tsx +0 -45
- package/src/components/admin/RolesView.tsx +0 -470
- package/src/components/admin/UserRolesSelectField.tsx +0 -50
- package/src/components/admin/UsersView.tsx +0 -693
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import type { AppView, AppViewsBuilder, EffectiveRoleController,
|
|
3
|
-
import
|
|
2
|
+
import type { AppView, AppViewsBuilder, EffectiveRoleController, RebasePlugin } from "@rebasepro/types";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Compare two view arrays by their slug identity.
|
|
@@ -17,14 +17,10 @@ function viewSlugsEqual(a: AppView[] | undefined, b: AppView[] | undefined): boo
|
|
|
17
17
|
return true;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
import { AuthController, RebaseData, User } from "@rebasepro/types";
|
|
21
|
-
import { UserManagementDelegate } from "@rebasepro/types";
|
|
20
|
+
import type { AuthController, RebaseData, User } from "@rebasepro/types";
|
|
22
21
|
|
|
23
22
|
import { resolveAppViews } from "./useNavigationResolution";
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
import { RolesView } from "../../components/admin/RolesView";
|
|
27
|
-
|
|
28
24
|
export type UseResolvedViewsProps<USER extends User> = {
|
|
29
25
|
authController: AuthController<USER>;
|
|
30
26
|
views?: AppView[] | AppViewsBuilder;
|
|
@@ -33,7 +29,6 @@ export type UseResolvedViewsProps<USER extends User> = {
|
|
|
33
29
|
plugins?: RebasePlugin[];
|
|
34
30
|
adminMode?: "content" | "studio" | "settings";
|
|
35
31
|
effectiveRoleController?: EffectiveRoleController;
|
|
36
|
-
userManagement?: UserManagementDelegate<USER>;
|
|
37
32
|
};
|
|
38
33
|
|
|
39
34
|
export type UseResolvedViewsResult = {
|
|
@@ -46,8 +41,7 @@ export type UseResolvedViewsResult = {
|
|
|
46
41
|
|
|
47
42
|
/**
|
|
48
43
|
* Hook that resolves view and admin view props (which may be async builders or arrays)
|
|
49
|
-
* into concrete AppView[].
|
|
50
|
-
* is provided with roles.
|
|
44
|
+
* into concrete AppView[].
|
|
51
45
|
*
|
|
52
46
|
* Uses refs for potentially-unstable dependencies (driver, authController,
|
|
53
47
|
* plugins) to avoid re-triggering effects when their object identity changes.
|
|
@@ -63,8 +57,7 @@ export function useResolvedViews<USER extends User>(
|
|
|
63
57
|
data,
|
|
64
58
|
plugins,
|
|
65
59
|
adminMode = "content",
|
|
66
|
-
effectiveRoleController
|
|
67
|
-
userManagement
|
|
60
|
+
effectiveRoleController
|
|
68
61
|
} = props;
|
|
69
62
|
|
|
70
63
|
const [loading, setLoading] = useState(true);
|
|
@@ -110,32 +103,6 @@ export function useResolvedViews<USER extends User>(
|
|
|
110
103
|
const resolvedAuthControllerRef = useRef(resolvedAuthController);
|
|
111
104
|
resolvedAuthControllerRef.current = resolvedAuthController;
|
|
112
105
|
|
|
113
|
-
// Memoize JSX element for injected Roles admin view to ensure stable reference.
|
|
114
|
-
const hasRoles = !!userManagement?.roles;
|
|
115
|
-
const rolesViewElement = useMemo(() =>
|
|
116
|
-
hasRoles ? <RolesView /> : null,
|
|
117
|
-
[hasRoles]
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
const injectedAdminViews: AppView[] = useMemo(() => {
|
|
121
|
-
const views: AppView[] = [];
|
|
122
|
-
const isUserAdmin = userManagement?.isAdmin !== false;
|
|
123
|
-
if (userManagement && isUserAdmin && userManagement.roles && rolesViewElement) {
|
|
124
|
-
views.push({
|
|
125
|
-
slug: "roles",
|
|
126
|
-
name: "Roles",
|
|
127
|
-
icon: "Shield",
|
|
128
|
-
view: rolesViewElement,
|
|
129
|
-
group: "Settings"
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
return views;
|
|
133
|
-
}, [userManagement, rolesViewElement]);
|
|
134
|
-
|
|
135
|
-
// Store injectedAdminViews in a ref for effect access
|
|
136
|
-
const injectedAdminViewsRef = useRef(injectedAdminViews);
|
|
137
|
-
injectedAdminViewsRef.current = injectedAdminViews;
|
|
138
|
-
|
|
139
106
|
const initialLoading = resolvedAuthController.initialLoading;
|
|
140
107
|
const user = resolvedAuthController.user;
|
|
141
108
|
|
|
@@ -146,20 +113,11 @@ export function useResolvedViews<USER extends User>(
|
|
|
146
113
|
|
|
147
114
|
(async () => {
|
|
148
115
|
try {
|
|
149
|
-
const [newViews,
|
|
116
|
+
const [newViews, newAdminViews] = await Promise.all([
|
|
150
117
|
resolveAppViews(viewsProp, resolvedAuthControllerRef.current, dataRef.current, pluginsRef.current),
|
|
151
118
|
resolveAppViews(adminViewsProp, resolvedAuthControllerRef.current, dataRef.current)
|
|
152
119
|
]);
|
|
153
120
|
|
|
154
|
-
// Generic dedup: developer-provided admin views override any injected ones with the same slug.
|
|
155
|
-
// No hardcoded slug checks — works for any slug generically.
|
|
156
|
-
const customSlugs = new Set(newAdminViewsProp.flatMap(v => Array.isArray(v.slug) ? v.slug : [v.slug]));
|
|
157
|
-
const finalInjected = injectedAdminViewsRef.current.filter(v => {
|
|
158
|
-
const slugs = Array.isArray(v.slug) ? v.slug : [v.slug];
|
|
159
|
-
return slugs.every(s => !customSlugs.has(s));
|
|
160
|
-
});
|
|
161
|
-
const newAdminViews = [...newAdminViewsProp, ...finalInjected];
|
|
162
|
-
|
|
163
121
|
// Compare views by slug identity rather than deepEqual.
|
|
164
122
|
// Views contain React elements (JSX) whose internal properties
|
|
165
123
|
// change on every render, making deepEqual unreliable.
|
|
@@ -26,7 +26,7 @@ export function getEntityViewWidth(props: EntitySidePanelProps<any>, small: bool
|
|
|
26
26
|
selectedSecondaryForm
|
|
27
27
|
} = resolvedSelectedEntityView(props.collection?.entityViews, customizationController, props.selectedTab);
|
|
28
28
|
|
|
29
|
-
const shouldUseSmallLayout = !props.selectedTab || props.selectedTab === JSON_TAB_VALUE || props.selectedTab === HISTORY_TAB_VALUE || Boolean(selectedSecondaryForm);
|
|
29
|
+
const shouldUseSmallLayout = !props.selectedTab || props.selectedTab === "edit" || props.selectedTab === JSON_TAB_VALUE || props.selectedTab === HISTORY_TAB_VALUE || Boolean(selectedSecondaryForm);
|
|
30
30
|
|
|
31
31
|
let resolvedWidth: string | undefined;
|
|
32
32
|
if (props.width) {
|
|
@@ -187,8 +187,8 @@ width: newWidth };
|
|
|
187
187
|
|
|
188
188
|
sideDialogsController.open(
|
|
189
189
|
propsToSidePanel({
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
...props,
|
|
191
|
+
selectedTab: props.selectedTab ?? defaultSelectedView,
|
|
192
192
|
},
|
|
193
193
|
urlController.buildUrlCollectionPath,
|
|
194
194
|
urlController.resolveDatabasePathsFrom,
|
|
@@ -241,6 +241,7 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
|
|
|
241
241
|
path: navigationEntry.slug,
|
|
242
242
|
entityId: navigationEntry.entityId,
|
|
243
243
|
copy: false,
|
|
244
|
+
collection: navigationEntry.parentCollection,
|
|
244
245
|
width: navigationEntry.parentCollection?.sideDialogWidth
|
|
245
246
|
};
|
|
246
247
|
} else if (navigationEntry.type === "custom_view") {
|
|
@@ -257,6 +258,22 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
|
|
|
257
258
|
|
|
258
259
|
}
|
|
259
260
|
|
|
261
|
+
// When the URL doesn't contain a tab segment but the collection has a
|
|
262
|
+
// defaultSelectedView, resolve it so the panel opens with the correct
|
|
263
|
+
// width and the URL is updated on the next replace() cycle.
|
|
264
|
+
if (sidePanel && !sidePanel.selectedTab && sidePanel.collection) {
|
|
265
|
+
const defaultView = resolveDefaultSelectedView(
|
|
266
|
+
sidePanel.collection.defaultSelectedView,
|
|
267
|
+
{
|
|
268
|
+
status: sidePanel.copy ? "copy" : (sidePanel.entityId ? "existing" : "new"),
|
|
269
|
+
entityId: sidePanel.entityId
|
|
270
|
+
}
|
|
271
|
+
);
|
|
272
|
+
if (defaultView) {
|
|
273
|
+
sidePanel.selectedTab = defaultView;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
260
277
|
if (newFlag) {
|
|
261
278
|
sidePanel = {
|
|
262
279
|
path: lastCollectionPath,
|
package/src/index.ts
CHANGED
|
@@ -45,7 +45,7 @@ export {
|
|
|
45
45
|
DefaultDrawer,
|
|
46
46
|
DrawerFooterActions,
|
|
47
47
|
AdminModeSyncer,
|
|
48
|
-
// ContentHomePage
|
|
48
|
+
// ContentHomePage is lazy-loaded — not re-exported here
|
|
49
49
|
RebaseCMS,
|
|
50
50
|
RebaseShell,
|
|
51
51
|
RebaseAuthGate,
|
|
@@ -53,12 +53,14 @@ export {
|
|
|
53
53
|
RebaseLayout,
|
|
54
54
|
RebaseRouteDefs,
|
|
55
55
|
SideDialogs,
|
|
56
|
-
useApp
|
|
56
|
+
useApp,
|
|
57
|
+
CollectionPanel
|
|
57
58
|
} from "./components";
|
|
58
59
|
export type {
|
|
59
60
|
EntityViewProps,
|
|
60
61
|
EntitySelectionProps,
|
|
61
|
-
SelectableTableProps
|
|
62
|
+
SelectableTableProps,
|
|
63
|
+
CollectionPanelProps
|
|
62
64
|
} from "./components";
|
|
63
65
|
|
|
64
66
|
export * from "./hooks";
|
|
@@ -97,7 +99,6 @@ export * from "./data_export";
|
|
|
97
99
|
// Collection editor — moved from @rebasepro/studio (CMS-dependent visual schema editor)
|
|
98
100
|
export * from "./collection_editor";
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
export { UserRolesSelectField } from "./components/admin/UserRolesSelectField";
|
|
102
|
+
|
|
102
103
|
export { CreationResultDialog } from "./components/admin/CreationResultDialog";
|
|
103
104
|
|
package/src/util/previews.ts
CHANGED
|
@@ -3,6 +3,11 @@ import { AuthController } from "@rebasepro/types";
|
|
|
3
3
|
import { isPropertyBuilder } from "@rebasepro/common";
|
|
4
4
|
import { isReferenceProperty, isRelationProperty } from "./property_utils";
|
|
5
5
|
|
|
6
|
+
function isHiddenProperty(property: Property | undefined): boolean {
|
|
7
|
+
if (!property) return false;
|
|
8
|
+
return Boolean(property.ui?.hideFromCollection);
|
|
9
|
+
}
|
|
10
|
+
|
|
6
11
|
export function getEntityPreviewKeys(
|
|
7
12
|
authController: AuthController,
|
|
8
13
|
targetCollection: EntityCollection<any>,
|
|
@@ -26,7 +31,7 @@ export function getEntityPreviewKeys(
|
|
|
26
31
|
})
|
|
27
32
|
.filter(key => {
|
|
28
33
|
const property = targetCollection.properties[key];
|
|
29
|
-
return property && !isPropertyBuilder(property) && !isReferenceProperty(property) && !isRelationProperty(property);
|
|
34
|
+
return property && !isPropertyBuilder(property) && !isReferenceProperty(property) && !isRelationProperty(property) && !isHiddenProperty(property);
|
|
30
35
|
}).slice(0, limit);
|
|
31
36
|
}
|
|
32
37
|
}
|
|
@@ -43,6 +48,9 @@ export function getEntityTitlePropertyKey<M extends Record<string, unknown>>(col
|
|
|
43
48
|
const property = collection.properties[key];
|
|
44
49
|
if (property && !isPropertyBuilder(property)) {
|
|
45
50
|
const prop = property as Property;
|
|
51
|
+
if (isHiddenProperty(prop)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
46
54
|
if (prop.type === "string" && !prop.ui?.multiline && !prop.ui?.markdown && !prop.storage && !prop.isId) {
|
|
47
55
|
if (!firstStringCandidate) {
|
|
48
56
|
firstStringCandidate = key;
|
package/src/util/resolutions.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { HistoryIcon } from "@rebasepro/ui";
|
|
2
|
-
import React
|
|
3
|
-
import type {
|
|
4
|
-
import type { CustomizationController, EntityAction } from "@rebasepro/types";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import type { CustomizationController, EntityAction, EntityCustomView } from "@rebasepro/types";
|
|
5
4
|
|
|
6
|
-
// Lazy-load: only resolved when HistoryIcon tab is visited
|
|
7
|
-
const EntityHistoryView = lazy(() => import("../components/history").then(m => ({ default: m.EntityHistoryView })));
|
|
8
5
|
/**
|
|
9
6
|
* Built-in entity views that are resolved by token name.
|
|
10
7
|
* These are always available without needing to be registered
|
|
@@ -15,7 +12,6 @@ const BUILTIN_ENTITY_VIEWS: Record<string, EntityCustomView> = {
|
|
|
15
12
|
key: "__rebase_history",
|
|
16
13
|
name: "History",
|
|
17
14
|
tabComponent: React.createElement(HistoryIcon, { size: 20 }),
|
|
18
|
-
Builder: EntityHistoryView,
|
|
19
15
|
position: "end"
|
|
20
16
|
}
|
|
21
17
|
};
|