@rebasepro/admin 0.0.1-canary.f81da60 → 0.1.2
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/dist/{CollectionEditorDialog-D509-IMx.js → CollectionEditorDialog-ywdxhs1L.js} +18 -18
- package/dist/CollectionEditorDialog-ywdxhs1L.js.map +1 -0
- package/dist/{CollectionsStudioView-B549BDpU.js → CollectionsStudioView-BDzMFzqH.js} +4 -4
- package/dist/{CollectionsStudioView-B549BDpU.js.map → CollectionsStudioView-BDzMFzqH.js.map} +1 -1
- package/dist/{ContentHomePage--Bl1FXk7.js → ContentHomePage-0tHuEIm_.js} +26 -26
- package/dist/ContentHomePage-0tHuEIm_.js.map +1 -0
- package/dist/{ExportCollectionAction-CttNAdM1.js → ExportCollectionAction-BIrq92To.js} +2 -2
- package/dist/{ExportCollectionAction-CttNAdM1.js.map → ExportCollectionAction-BIrq92To.js.map} +1 -1
- package/dist/{ImportCollectionAction-BB33kxAN.js → ImportCollectionAction-h8yg_To8.js} +2 -2
- package/dist/{ImportCollectionAction-BB33kxAN.js.map → ImportCollectionAction-h8yg_To8.js.map} +1 -1
- package/dist/{PropertyEditView-UtDO8g0A.js → PropertyEditView-BuZrNnBN.js} +79 -101
- package/dist/PropertyEditView-BuZrNnBN.js.map +1 -0
- package/dist/{RolesView-B0E7L0hE.js → RolesView-CMPsaIXo.js} +2 -2
- package/dist/{RolesView-B0E7L0hE.js.map → RolesView-CMPsaIXo.js.map} +1 -1
- package/dist/{UsersView-BM2_7VPV.js → UsersView-BkeblMVT.js} +6 -28
- package/dist/UsersView-BkeblMVT.js.map +1 -0
- package/dist/collection_editor/ConfigControllerProvider.d.ts +0 -4
- package/dist/collection_editor/ui/collection_editor/CollectionDetailsForm.d.ts +1 -3
- package/dist/collection_editor/ui/collection_editor/CollectionEditorDialog.d.ts +0 -2
- package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +1 -2
- package/dist/collection_editor_ui.js +3 -3
- package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -1
- package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +2 -1
- package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +2 -1
- package/dist/components/EntityEditView.d.ts +6 -0
- package/dist/components/RebaseCMS.d.ts +1 -1
- package/dist/{index-C9YDsMC9.js → index-BuZaHcyc.js} +3 -3
- package/dist/index-BuZaHcyc.js.map +1 -0
- package/dist/{index-CNDetux9.js → index-CS6uJ7oW.js} +2 -2
- package/dist/{index-CNDetux9.js.map → index-CS6uJ7oW.js.map} +1 -1
- package/dist/{index-DO7lMeNB.js → index-eRJbMvHi.js} +3 -3
- package/dist/index-eRJbMvHi.js.map +1 -0
- package/dist/index.js +18 -14
- package/dist/index.js.map +1 -1
- package/dist/util/navigation_utils.d.ts +10 -1
- package/dist/{util-DK1O3uM0.js → util-zfU1zOCX.js} +713 -603
- package/dist/util-zfU1zOCX.js.map +1 -0
- package/package.json +8 -8
- package/src/collection_editor/ConfigControllerProvider.tsx +1 -10
- package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +3 -47
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +2 -10
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +1 -3
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +0 -1
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +6 -6
- package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +15 -49
- package/src/collection_editor/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +2 -3
- package/src/collection_editor/ui/collection_editor/templates/pages_template.ts +1 -1
- package/src/collection_editor/ui/collection_editor/templates/products_template.ts +2 -2
- package/src/components/DefaultAppBar.tsx +2 -2
- package/src/components/DefaultDrawer.tsx +25 -17
- package/src/components/DrawerNavigationGroup.tsx +4 -4
- package/src/components/DrawerNavigationItem.tsx +6 -6
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +5 -3
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +8 -2
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +2 -2
- package/src/components/EntityCollectionTable/table_bindings.tsx +37 -27
- package/src/components/EntityCollectionView/EntityCard.tsx +2 -2
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +4 -3
- package/src/components/EntityCollectionView/EntityCollectionListView.tsx +7 -6
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +50 -7
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +17 -8
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +8 -4
- package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +33 -5
- package/src/components/EntityEditView.tsx +80 -81
- package/src/components/EntitySidePanel.tsx +11 -7
- package/src/components/HomePage/ContentHomePage.tsx +24 -15
- package/src/components/HomePage/NavigationCard.tsx +4 -4
- package/src/components/HomePage/NavigationGroup.tsx +2 -2
- package/src/components/RebaseAuthGate.tsx +2 -0
- package/src/components/RebaseCMS.tsx +4 -3
- package/src/components/RebaseNavigation.tsx +7 -4
- package/src/components/RelationSelector.tsx +30 -2
- package/src/components/SelectableTable/SelectableTable.tsx +2 -2
- package/src/components/UserSelector.tsx +1 -1
- package/src/components/admin/UsersView.tsx +2 -17
- package/src/components/app/Scaffold.tsx +3 -3
- package/src/components/field_configs.tsx +3 -3
- package/src/form/PropertyFieldBinding.tsx +10 -6
- package/src/hooks/navigation/useResolvedViews.tsx +1 -3
- package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
- package/src/hooks/navigation/utils.ts +1 -1
- package/src/preview/PropertyPreview.tsx +17 -13
- package/src/routes/RebaseRoute.tsx +27 -2
- package/src/util/navigation_utils.ts +16 -2
- package/src/util/previews.ts +14 -5
- package/dist/CollectionEditorDialog-D509-IMx.js.map +0 -1
- package/dist/ContentHomePage--Bl1FXk7.js.map +0 -1
- package/dist/PropertyEditView-UtDO8g0A.js.map +0 -1
- package/dist/UsersView-BM2_7VPV.js.map +0 -1
- package/dist/index-C9YDsMC9.js.map +0 -1
- package/dist/index-DO7lMeNB.js.map +0 -1
- package/dist/util-DK1O3uM0.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/admin",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.1.2",
|
|
5
5
|
"description": "Rebase CMS — content management views, forms, and routing",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/rebaseco"
|
|
@@ -77,13 +77,13 @@
|
|
|
77
77
|
"react-use-measure": "^2.1.7",
|
|
78
78
|
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz",
|
|
79
79
|
"zod": "^3.25.0",
|
|
80
|
-
"@rebasepro/common": "0.
|
|
81
|
-
"@rebasepro/core": "0.
|
|
82
|
-
"@rebasepro/formex": "0.
|
|
83
|
-
"@rebasepro/schema-inference": "0.
|
|
84
|
-
"@rebasepro/types": "0.
|
|
85
|
-
"@rebasepro/ui": "0.
|
|
86
|
-
"@rebasepro/utils": "0.
|
|
80
|
+
"@rebasepro/common": "0.1.2",
|
|
81
|
+
"@rebasepro/core": "0.1.2",
|
|
82
|
+
"@rebasepro/formex": "0.1.2",
|
|
83
|
+
"@rebasepro/schema-inference": "0.1.2",
|
|
84
|
+
"@rebasepro/types": "0.1.2",
|
|
85
|
+
"@rebasepro/ui": "0.1.2",
|
|
86
|
+
"@rebasepro/utils": "0.1.2"
|
|
87
87
|
},
|
|
88
88
|
"peerDependencies": {
|
|
89
89
|
"react": ">=19.0.0",
|
|
@@ -32,11 +32,6 @@ export interface ConfigControllerProviderProps {
|
|
|
32
32
|
*/
|
|
33
33
|
configPermissions?: CollectionEditorPermissionsBuilder;
|
|
34
34
|
|
|
35
|
-
/**
|
|
36
|
-
* Groups that cannot be used to create new collections.
|
|
37
|
-
*/
|
|
38
|
-
reservedGroups?: string[];
|
|
39
|
-
|
|
40
35
|
extraView?: {
|
|
41
36
|
View: React.ComponentType<{
|
|
42
37
|
path: string
|
|
@@ -65,7 +60,6 @@ export const ConfigControllerProvider = React.memo(
|
|
|
65
60
|
children,
|
|
66
61
|
collectionConfigController,
|
|
67
62
|
configPermissions,
|
|
68
|
-
reservedGroups,
|
|
69
63
|
collectionInference,
|
|
70
64
|
extraView,
|
|
71
65
|
getUser,
|
|
@@ -105,7 +99,6 @@ export const ConfigControllerProvider = React.memo(
|
|
|
105
99
|
parentCollectionSlugs: string[], parentEntityIds: string[],
|
|
106
100
|
initialValues?: {
|
|
107
101
|
path?: string,
|
|
108
|
-
group?: string,
|
|
109
102
|
name?: string
|
|
110
103
|
},
|
|
111
104
|
copyFrom?: EntityCollection,
|
|
@@ -225,7 +218,6 @@ export const ConfigControllerProvider = React.memo(
|
|
|
225
218
|
parentCollectionSlugs: string[], parentEntityIds: string[],
|
|
226
219
|
parentCollection?: EntityCollection
|
|
227
220
|
initialValues?: {
|
|
228
|
-
group?: string,
|
|
229
221
|
path?: string,
|
|
230
222
|
name?: string
|
|
231
223
|
},
|
|
@@ -270,7 +262,6 @@ export const ConfigControllerProvider = React.memo(
|
|
|
270
262
|
collectionInference,
|
|
271
263
|
...currentDialog,
|
|
272
264
|
getData,
|
|
273
|
-
reservedGroups,
|
|
274
265
|
extraView,
|
|
275
266
|
getUser,
|
|
276
267
|
generateCollection,
|
|
@@ -289,7 +280,7 @@ export const ConfigControllerProvider = React.memo(
|
|
|
289
280
|
};
|
|
290
281
|
}, [
|
|
291
282
|
currentDialog, collectionConfigController, collectionInference,
|
|
292
|
-
getData,
|
|
283
|
+
getData, extraView, getUser, generateCollection,
|
|
293
284
|
onAnalyticsEvent, unmappedTables, onFetchTableMetadata,
|
|
294
285
|
urlController, navigate
|
|
295
286
|
]);
|
|
@@ -5,7 +5,7 @@ import React, { useMemo, useState } from "react";
|
|
|
5
5
|
import { useAuthController, useCustomizationController } from "@rebasepro/core";
|
|
6
6
|
import { getFieldConfig, PropertyConfigBadge, SearchIconsView } from "../../_cms_internals";
|
|
7
7
|
import { EntityCollection, Property } from "@rebasepro/types";
|
|
8
|
-
import { BooleanSwitchWithLabel, Chip, cls, Container, DebouncedTextField, Dialog, IconButton, Select, SelectItem, TextField, Tooltip, Typography,
|
|
8
|
+
import { BooleanSwitchWithLabel, Chip, cls, Container, DebouncedTextField, Dialog, IconButton, Select, SelectItem, TextField, Tooltip, Typography, Button, iconSize } from "@rebasepro/ui";
|
|
9
9
|
import { XIcon, HistoryIcon } from "lucide-react";
|
|
10
10
|
|
|
11
11
|
import { Field, getIn, useFormex } from "@rebasepro/formex";
|
|
@@ -18,24 +18,20 @@ import { singular, toSnakeCase, unslugify } from "@rebasepro/utils";
|
|
|
18
18
|
|
|
19
19
|
export function CollectionDetailsForm({
|
|
20
20
|
isNewCollection,
|
|
21
|
-
reservedGroups,
|
|
22
21
|
existingPaths,
|
|
23
22
|
existingIds,
|
|
24
|
-
groups,
|
|
25
23
|
parentCollection,
|
|
26
24
|
expandKanban
|
|
27
25
|
}: {
|
|
28
26
|
isNewCollection: boolean,
|
|
29
|
-
reservedGroups?: string[];
|
|
30
27
|
existingPaths?: string[];
|
|
31
28
|
existingIds?: string[];
|
|
32
|
-
groups: string[] | null;
|
|
33
29
|
parentCollection?: EntityCollection;
|
|
34
30
|
parentCollectionSlugs?: string[], parentEntityIds?: string[];
|
|
35
31
|
expandKanban?: boolean;
|
|
36
32
|
}) {
|
|
37
33
|
|
|
38
|
-
|
|
34
|
+
|
|
39
35
|
const {
|
|
40
36
|
values,
|
|
41
37
|
setFieldValue,
|
|
@@ -98,15 +94,7 @@ export function CollectionDetailsForm({
|
|
|
98
94
|
|
|
99
95
|
const collectionIcon = <IconForView collectionOrView={values}/>;
|
|
100
96
|
|
|
101
|
-
const groupOptions = groups?.filter((group) => !reservedGroups?.includes(group));
|
|
102
97
|
|
|
103
|
-
const {
|
|
104
|
-
inputFocused,
|
|
105
|
-
autoCompleteOpen,
|
|
106
|
-
setAutoCompleteOpen
|
|
107
|
-
} = useAutoComplete({
|
|
108
|
-
ref: groupRef
|
|
109
|
-
});
|
|
110
98
|
|
|
111
99
|
const isSubcollection = !!parentCollection;
|
|
112
100
|
|
|
@@ -172,39 +160,7 @@ export function CollectionDetailsForm({
|
|
|
172
160
|
|
|
173
161
|
</div>
|
|
174
162
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
{/* <TextField error={showErrors && Boolean(errors.group)}*/}
|
|
178
|
-
{/* disabled={isSubmitting}*/}
|
|
179
|
-
{/* value={values.group ?? ""}*/}
|
|
180
|
-
{/* autoComplete="off"*/}
|
|
181
|
-
{/* onChange={(event) => setFieldValue("group", event.target.value)}*/}
|
|
182
|
-
{/* name={"group"}*/}
|
|
183
|
-
{/* inputRef={groupRef}*/}
|
|
184
|
-
{/* label="Group"/>*/}
|
|
185
|
-
{/* <Autocomplete*/}
|
|
186
|
-
{/* open={autoCompleteOpen && (groupOptions ?? []).length > 0}*/}
|
|
187
|
-
{/* setOpen={setAutoCompleteOpen}>*/}
|
|
188
|
-
{/* {groupOptions?.map((group, index) => {*/}
|
|
189
|
-
{/* return <AutocompleteItem*/}
|
|
190
|
-
{/* key={index + "_" + group}*/}
|
|
191
|
-
{/* className={"pr-6 pl-14"}*/}
|
|
192
|
-
{/* onClick={() => {*/}
|
|
193
|
-
{/* setAutoCompleteOpen(false);*/}
|
|
194
|
-
{/* setFieldValue("group", group ?? null);*/}
|
|
195
|
-
{/* }}*/}
|
|
196
|
-
{/* >*/}
|
|
197
|
-
{/* <div className={"flex-grow"}>*/}
|
|
198
|
-
{/* {group}*/}
|
|
199
|
-
{/* </div>*/}
|
|
200
|
-
{/* </AutocompleteItem>;*/}
|
|
201
|
-
{/* })}*/}
|
|
202
|
-
{/* </Autocomplete>*/}
|
|
203
|
-
{/* <FieldCaption>*/}
|
|
204
|
-
{/* {showErrors && Boolean(errors.group) ? errors.group : "Group in the home page"}*/}
|
|
205
|
-
{/* </FieldCaption>*/}
|
|
206
|
-
|
|
207
|
-
{/*</div>}*/}
|
|
163
|
+
|
|
208
164
|
|
|
209
165
|
<LayoutModeSwitch
|
|
210
166
|
className={"col-span-12"}
|
|
@@ -37,7 +37,6 @@ export interface CollectionEditorDialogProps {
|
|
|
37
37
|
open: boolean;
|
|
38
38
|
isNewCollection: boolean;
|
|
39
39
|
initialValues?: {
|
|
40
|
-
group?: string,
|
|
41
40
|
slug?: string,
|
|
42
41
|
name?: string,
|
|
43
42
|
}
|
|
@@ -51,7 +50,6 @@ export interface CollectionEditorDialogProps {
|
|
|
51
50
|
parentCollectionSlugs?: string[], parentEntityIds?: string[]; // path ids of the parent collection, like [`products`]
|
|
52
51
|
handleClose: (collection?: EntityCollection) => void;
|
|
53
52
|
configController: CollectionsConfigController;
|
|
54
|
-
reservedGroups?: string[];
|
|
55
53
|
collectionInference?: CollectionInference;
|
|
56
54
|
extraView?: {
|
|
57
55
|
View: React.ComponentType<{
|
|
@@ -200,7 +198,7 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
|
200
198
|
}
|
|
201
199
|
}, [props.editedCollectionId, props.parentCollectionSlugs, props.parentEntityIds, collectionRegistry.initialised, collectionRegistry.getRawCollection]);
|
|
202
200
|
|
|
203
|
-
|
|
201
|
+
|
|
204
202
|
|
|
205
203
|
const initialCollection = collection
|
|
206
204
|
? {
|
|
@@ -226,7 +224,6 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
|
226
224
|
slug: initialValuesProp?.slug ?? randomString(16),
|
|
227
225
|
table: initialValuesProp?.slug ?? "",
|
|
228
226
|
name: initialValuesProp?.name ?? "",
|
|
229
|
-
group: initialValuesProp?.group ?? "",
|
|
230
227
|
properties: {} as Properties,
|
|
231
228
|
propertiesOrder: [],
|
|
232
229
|
icon: coolIconKeys[Math.floor(Math.random() * coolIconKeys.length)],
|
|
@@ -249,7 +246,6 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
|
249
246
|
includeTemplates={includeTemplates}
|
|
250
247
|
collection={collection}
|
|
251
248
|
setCollection={setCollection}
|
|
252
|
-
groups={groups}
|
|
253
249
|
propertyConfigs={propertyConfigs}/>
|
|
254
250
|
|
|
255
251
|
}
|
|
@@ -262,7 +258,6 @@ function CollectionEditorInternal<M extends Record<string, unknown>>({
|
|
|
262
258
|
path,
|
|
263
259
|
collectionInference,
|
|
264
260
|
handleClose,
|
|
265
|
-
reservedGroups,
|
|
266
261
|
extraView,
|
|
267
262
|
handleCancel,
|
|
268
263
|
setFormDirty,
|
|
@@ -276,7 +271,6 @@ function CollectionEditorInternal<M extends Record<string, unknown>>({
|
|
|
276
271
|
setCollection,
|
|
277
272
|
initialValues,
|
|
278
273
|
propertyConfigs,
|
|
279
|
-
groups,
|
|
280
274
|
existingEntities,
|
|
281
275
|
initialView: initialViewProp,
|
|
282
276
|
expandKanban,
|
|
@@ -295,7 +289,6 @@ function CollectionEditorInternal<M extends Record<string, unknown>>({
|
|
|
295
289
|
collection: EntityCollection<M> | undefined,
|
|
296
290
|
setCollection: (collection: EntityCollection<M>) => void,
|
|
297
291
|
propertyConfigs: Record<string, PropertyConfig>,
|
|
298
|
-
groups: string[],
|
|
299
292
|
}
|
|
300
293
|
) {
|
|
301
294
|
|
|
@@ -619,7 +612,7 @@ function CollectionEditorInternal<M extends Record<string, unknown>>({
|
|
|
619
612
|
<Formex value={formController}>
|
|
620
613
|
|
|
621
614
|
<>
|
|
622
|
-
{!isNewCollection && <div className={cls("px-4 py-2 w-full flex shrink-0 items-center justify-between gap-4 bg-
|
|
615
|
+
{!isNewCollection && <div className={cls("px-4 py-2 w-full flex shrink-0 items-center justify-between gap-4 bg-surface-50 dark:bg-surface-950 border-b", defaultBorderMixin)}>
|
|
623
616
|
<div className="flex flex-1 items-center justify-end gap-4 min-w-0">
|
|
624
617
|
<Tabs value={currentView}
|
|
625
618
|
className="bg-transparent !w-fit max-w-full"
|
|
@@ -756,7 +749,6 @@ function CollectionEditorInternal<M extends Record<string, unknown>>({
|
|
|
756
749
|
<CollectionPropertiesEditorForm
|
|
757
750
|
showErrors={submitCount > 0}
|
|
758
751
|
isNewCollection={isNewCollection}
|
|
759
|
-
reservedGroups={reservedGroups}
|
|
760
752
|
onPropertyError={(propertyKey, namespace, error) => {
|
|
761
753
|
const current = removeUndefined({
|
|
762
754
|
...propertyErrorsRef.current,
|
|
@@ -27,7 +27,6 @@ type CollectionEditorFormProps = {
|
|
|
27
27
|
propertyErrorsRef?: React.MutableRefObject<any>;
|
|
28
28
|
onPropertyError: (propertyKey: string, namespace: string | undefined, error?: Record<string, any>) => void;
|
|
29
29
|
setDirty?: (dirty: boolean) => void;
|
|
30
|
-
reservedGroups?: string[];
|
|
31
30
|
extraIcon: React.ReactNode | any;
|
|
32
31
|
getUser?: (uid: string) => User | null;
|
|
33
32
|
getData?: () => Promise<object[]>;
|
|
@@ -42,7 +41,6 @@ export function CollectionPropertiesEditorForm({
|
|
|
42
41
|
propertyErrorsRef,
|
|
43
42
|
onPropertyError,
|
|
44
43
|
setDirty,
|
|
45
|
-
reservedGroups,
|
|
46
44
|
extraIcon,
|
|
47
45
|
getUser,
|
|
48
46
|
getData,
|
|
@@ -391,7 +389,7 @@ export function CollectionPropertiesEditorForm({
|
|
|
391
389
|
};
|
|
392
390
|
|
|
393
391
|
const body = (
|
|
394
|
-
<div className={"grid grid-cols-12 gap-2 h-full bg-
|
|
392
|
+
<div className={"grid grid-cols-12 gap-2 h-full bg-white dark:bg-surface-950"}>
|
|
395
393
|
<div className={cls(
|
|
396
394
|
"bg-surface-50 dark:bg-surface-900",
|
|
397
395
|
"p-4 md:p-8",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import React, { useState } from "react";
|
|
3
|
-
import { Button, IconButton, Typography, Table, TableHeader, TableCell, TableBody, TableRow, TextField, Select, SelectItem, Container, Dialog, DialogTitle, DialogContent, DialogActions } from "@rebasepro/ui";
|
|
3
|
+
import { Button, IconButton, Typography, Table, TableHeader, TableCell, TableBody, TableRow, TextField, Select, SelectItem, Container, Dialog, DialogTitle, DialogContent, DialogActions, cls, defaultBorderMixin } from "@rebasepro/ui";
|
|
4
4
|
import { Trash2Icon } from "lucide-react";
|
|
5
5
|
import { useFormex } from "@rebasepro/formex";
|
|
6
6
|
import { PostgresCollection, Relation } from "@rebasepro/types";
|
|
@@ -128,7 +128,7 @@ direction: "owning" });
|
|
|
128
128
|
<DialogTitle className="flex justify-between items-center w-full" variant="h6">
|
|
129
129
|
{editingRelationIndex === -1 ? "New Relation" : "Edit Relation"}
|
|
130
130
|
</DialogTitle>
|
|
131
|
-
<DialogContent includeMargin={false} className="p-4 md:p-6 border-t
|
|
131
|
+
<DialogContent includeMargin={false} className={cls("p-4 md:p-6 border-t bg-white dark:bg-surface-900", defaultBorderMixin)}>
|
|
132
132
|
<div className="flex flex-col gap-4 max-w-2xl mx-auto">
|
|
133
133
|
<TextField
|
|
134
134
|
label="Relation Name"
|
|
@@ -178,7 +178,7 @@ direction: val as Relation["direction"] } : null)}
|
|
|
178
178
|
</Select>
|
|
179
179
|
|
|
180
180
|
{editingRelationState.cardinality === "many" && editingRelationState.direction === "owning" && (
|
|
181
|
-
<div className="flex flex-col gap-4 mt-4 pt-4 border-t
|
|
181
|
+
<div className={cls("flex flex-col gap-4 mt-4 pt-4 border-t", defaultBorderMixin)}>
|
|
182
182
|
<Typography variant="subtitle2" className="text-text-primary">Intermediate Table</Typography>
|
|
183
183
|
<Typography variant="body2" className="text-text-secondary -mt-3">
|
|
184
184
|
Required for many-to-many relationships. This defines the junction table linking both collections.
|
|
@@ -123,7 +123,6 @@ function collectionToCode(collection: EntityCollection): object {
|
|
|
123
123
|
description: collection.description,
|
|
124
124
|
|
|
125
125
|
icon: collection.icon,
|
|
126
|
-
group: collection.group,
|
|
127
126
|
defaultFilter: collection.defaultFilter,
|
|
128
127
|
sort: collection.sort,
|
|
129
128
|
properties: Object.entries({
|
|
@@ -39,10 +39,10 @@ export function PropertyFieldPreview({
|
|
|
39
39
|
<div onClick={onClick} className={onClick ? "cursor-pointer" : ""}>
|
|
40
40
|
<Paper
|
|
41
41
|
className={cls(
|
|
42
|
-
"w-full flex flex-row gap-3 items-center px-3 py-2 rounded-lg transition-all duration-200 border
|
|
42
|
+
"w-full flex flex-row gap-3 items-center px-3 py-2 rounded-lg transition-all duration-200 border bg-white dark:bg-surface-800 border-surface-200 dark:border-surface-700 shadow-xs",
|
|
43
43
|
selected
|
|
44
|
-
? "bg-primary/5 dark:bg-primary/10 ring-1 ring-inset ring-primary"
|
|
45
|
-
: "hover:bg-surface-50 dark:hover:bg-surface-
|
|
44
|
+
? "bg-primary/5 dark:bg-primary/10 ring-1 ring-inset ring-primary border-primary/30"
|
|
45
|
+
: "hover:bg-surface-50 dark:hover:bg-surface-750"
|
|
46
46
|
)}
|
|
47
47
|
>
|
|
48
48
|
<PropertyConfigBadge propertyConfig={propertyConfig} size="small"/>
|
|
@@ -105,10 +105,10 @@ export function NonEditablePropertyPreview({
|
|
|
105
105
|
<div onClick={onClick} className={onClick ? "cursor-pointer" : ""}>
|
|
106
106
|
<Paper
|
|
107
107
|
className={cls(
|
|
108
|
-
"w-full flex flex-row gap-3 items-center px-3 py-2 rounded-lg transition-all duration-200 border
|
|
108
|
+
"w-full flex flex-row gap-3 items-center px-3 py-2 rounded-lg transition-all duration-200 border bg-white dark:bg-surface-800 border-surface-200 dark:border-surface-700 shadow-xs",
|
|
109
109
|
selected
|
|
110
|
-
? "bg-primary/5 dark:bg-primary/10 ring-1 ring-inset ring-primary"
|
|
111
|
-
: "hover:bg-surface-50 dark:hover:bg-surface-
|
|
110
|
+
? "bg-primary/5 dark:bg-primary/10 ring-1 ring-inset ring-primary border-primary/30"
|
|
111
|
+
: "hover:bg-surface-50 dark:hover:bg-surface-750"
|
|
112
112
|
)}
|
|
113
113
|
>
|
|
114
114
|
<div className={"relative shrink-0"}>
|
|
@@ -111,7 +111,7 @@ export function MapPropertyField({ disabled, getData, allowDataInference, proper
|
|
|
111
111
|
position={"start"}
|
|
112
112
|
size={"medium"}
|
|
113
113
|
label={t("spread_children_as_columns")}
|
|
114
|
-
onValueChange={(v) => setFieldValue("spreadChildren", v)}
|
|
114
|
+
onValueChange={(v) => setFieldValue("ui.spreadChildren", v)}
|
|
115
115
|
value={values.ui?.spreadChildren ?? false}
|
|
116
116
|
/>
|
|
117
117
|
<FieldCaption>
|
|
@@ -4,7 +4,7 @@ import React from "react";
|
|
|
4
4
|
import { Field, getIn, useFormex } from "@rebasepro/formex";
|
|
5
5
|
;
|
|
6
6
|
import { NumberProperty, StringProperty } from "@rebasepro/types";
|
|
7
|
-
import { CircularProgress, Select,
|
|
7
|
+
import { CircularProgress, Select, SelectItem, Typography } from "@rebasepro/ui";
|
|
8
8
|
|
|
9
9
|
export function ReferencePropertyField({
|
|
10
10
|
existing,
|
|
@@ -81,12 +81,6 @@ export function CollectionsSelect({
|
|
|
81
81
|
|
|
82
82
|
const collections = collectionRegistry.collections ?? [];
|
|
83
83
|
|
|
84
|
-
const groups: string[] = Array.from(new Set(
|
|
85
|
-
Object.values(collections).map(e => e.group).filter(Boolean) as string[]
|
|
86
|
-
).values());
|
|
87
|
-
|
|
88
|
-
const ungroupedCollections = collections.filter((col) => !col.group);
|
|
89
|
-
|
|
90
84
|
return (
|
|
91
85
|
<>
|
|
92
86
|
<Select
|
|
@@ -113,48 +107,20 @@ export function CollectionsSelect({
|
|
|
113
107
|
}}
|
|
114
108
|
{...props}>
|
|
115
109
|
|
|
116
|
-
{
|
|
117
|
-
<
|
|
118
|
-
key={
|
|
119
|
-
{
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
{collection?.name.toUpperCase()}
|
|
131
|
-
</Typography>
|
|
132
|
-
</div>
|
|
133
|
-
</SelectItem>;
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
</SelectGroup>
|
|
138
|
-
))}
|
|
139
|
-
|
|
140
|
-
{ungroupedCollections && <SelectGroup label={"Views"}>
|
|
141
|
-
{ungroupedCollections
|
|
142
|
-
.map((collection) => {
|
|
143
|
-
return <SelectItem key={collection.slug}
|
|
144
|
-
value={collection.slug}>
|
|
145
|
-
<div className="flex flex-row">
|
|
146
|
-
<IconForView collectionOrView={collection}/>
|
|
147
|
-
<Typography
|
|
148
|
-
variant={"subtitle2"}
|
|
149
|
-
className="ml-4">
|
|
150
|
-
{collection?.name.toUpperCase()}
|
|
151
|
-
</Typography>
|
|
152
|
-
</div>
|
|
153
|
-
</SelectItem>;
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
</SelectGroup>}
|
|
110
|
+
{collections.map((collection) => {
|
|
111
|
+
return <SelectItem
|
|
112
|
+
key={collection.slug}
|
|
113
|
+
value={collection.slug}>
|
|
114
|
+
<div className="flex flex-row">
|
|
115
|
+
<IconForView collectionOrView={collection}/>
|
|
116
|
+
<Typography
|
|
117
|
+
variant={"subtitle2"}
|
|
118
|
+
className="ml-4">
|
|
119
|
+
{collection?.name.toUpperCase()}
|
|
120
|
+
</Typography>
|
|
121
|
+
</div>
|
|
122
|
+
</SelectItem>;
|
|
123
|
+
})}
|
|
158
124
|
|
|
159
125
|
</Select>
|
|
160
126
|
|
|
@@ -7,9 +7,8 @@ export function AdvancedPropertyValidation({ disabled }: {
|
|
|
7
7
|
disabled: boolean
|
|
8
8
|
}) {
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const readOnly = "readOnly";
|
|
10
|
+
const hideFromCollection = "ui.hideFromCollection";
|
|
11
|
+
const readOnly = "ui.readOnly";
|
|
13
12
|
|
|
14
13
|
return (
|
|
15
14
|
|
|
@@ -41,7 +41,7 @@ export const productsCollectionTemplate = {
|
|
|
41
41
|
available: {
|
|
42
42
|
type: "boolean",
|
|
43
43
|
name: "Available",
|
|
44
|
-
columnWidth: 100,
|
|
44
|
+
ui: { columnWidth: 100 },
|
|
45
45
|
description: "Is this product available in the website"
|
|
46
46
|
},
|
|
47
47
|
price: {
|
|
@@ -55,7 +55,7 @@ export const productsCollectionTemplate = {
|
|
|
55
55
|
images: {
|
|
56
56
|
type: "array",
|
|
57
57
|
name: "Images",
|
|
58
|
-
hideFromCollection: true,
|
|
58
|
+
ui: { hideFromCollection: true },
|
|
59
59
|
of: {
|
|
60
60
|
type: "string",
|
|
61
61
|
storage: {
|
|
@@ -110,9 +110,9 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
110
110
|
<div
|
|
111
111
|
style={style}
|
|
112
112
|
role="banner"
|
|
113
|
-
className={cls("w-full h-
|
|
113
|
+
className={cls("w-full h-14 transition-all ease-in duration-75 absolute top-0 max-w-full overflow-x-auto no-scrollbar",
|
|
114
114
|
"flex flex-row gap-2 px-4 items-center",
|
|
115
|
-
"backdrop-blur-
|
|
115
|
+
"backdrop-blur-sm bg-surface-50/95 dark:bg-surface-900/80",
|
|
116
116
|
{
|
|
117
117
|
"pl-[19rem]": drawerOpen && largeLayout,
|
|
118
118
|
"pl-24": hasDrawer && !(drawerOpen && largeLayout),
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { NavigationEntry, NavigationResult } from "@rebasepro/types";
|
|
2
|
-
import React from "react";
|
|
2
|
+
import React, { useMemo } from "react";
|
|
3
3
|
|
|
4
|
-
import { useCollapsedGroups, useLargeLayout, useAdminModeController,
|
|
4
|
+
import { useCollapsedGroups, buildCollapsedDefaults, useLargeLayout, useAdminModeController, useTranslation, useSlot, useRebaseContext, useAnalyticsController, useRebaseRegistry } from "@rebasepro/core";
|
|
5
5
|
import { useNavigationStateController, useUrlController } from "../hooks";
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
import { Link, useNavigate } from "react-router-dom";
|
|
8
9
|
import { AnalyticsEvent } from "@rebasepro/types";
|
|
9
10
|
import { cls, Tooltip, Typography , iconSize } from "@rebasepro/ui";
|
|
@@ -57,22 +58,31 @@ export function DefaultDrawer({
|
|
|
57
58
|
|
|
58
59
|
const tooltipsOpen = drawerHovered && !drawerOpen && !adminMenuOpen;
|
|
59
60
|
const largeLayout = useLargeLayout();
|
|
60
|
-
const navigate = useNavigate();
|
|
61
61
|
const adminModeController = useAdminModeController();
|
|
62
|
-
const effectiveRoleController = useEffectiveRoleController();
|
|
63
62
|
const registry = useRebaseRegistry();
|
|
64
63
|
|
|
65
|
-
const
|
|
64
|
+
const allNavigationEntries = navigationState.topLevelNavigation?.navigationEntries ?? [];
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
// Studio mode shows view-type entries (devViews) + admin entries (Users/Roles).
|
|
67
|
+
// Content mode shows collections and custom entries + admin entries (Users/Roles), but not studio views.
|
|
68
|
+
const filteredEntries = adminModeController.mode === "studio"
|
|
69
|
+
? allNavigationEntries.filter(e => e.type === "view" || e.type === "admin")
|
|
70
|
+
: allNavigationEntries.filter(e => e.type !== "view");
|
|
71
|
+
|
|
72
|
+
// Derive groups from the filtered entries, preserving the order from topLevelNavigation.groups
|
|
73
|
+
const entryGroups = new Set(filteredEntries.map(e => e.group).filter(Boolean));
|
|
74
|
+
const orderedGroups = navigationState.topLevelNavigation?.groups ?? [];
|
|
75
|
+
const groupsToRender = [
|
|
76
|
+
...orderedGroups.filter(g => entryGroups.has(g)),
|
|
77
|
+
...[...entryGroups].filter(g => !orderedGroups.includes(g))
|
|
78
|
+
];
|
|
73
79
|
|
|
74
80
|
// Collapsible groups state - using "drawer" namespace for independent state from home page
|
|
75
|
-
const
|
|
81
|
+
const collapsedDefaults = useMemo(
|
|
82
|
+
() => buildCollapsedDefaults(registry.cmsConfig?.navigationGroupMappings, "drawer"),
|
|
83
|
+
[registry.cmsConfig?.navigationGroupMappings]
|
|
84
|
+
);
|
|
85
|
+
const { isGroupCollapsed, toggleGroupCollapsed } = useCollapsedGroups(groupsToRender, "drawer", collapsedDefaults);
|
|
76
86
|
|
|
77
87
|
const headerSlot = useSlot("navigation.header", { drawerOpen,
|
|
78
88
|
drawerHovered,
|
|
@@ -84,7 +94,6 @@ context });
|
|
|
84
94
|
if (!navigationState.topLevelNavigation)
|
|
85
95
|
return null;
|
|
86
96
|
|
|
87
|
-
const navigationEntries = navigationState.topLevelNavigation.navigationEntries;
|
|
88
97
|
const groups = navigationState.topLevelNavigation.groups;
|
|
89
98
|
|
|
90
99
|
const onItemClick = (view: NavigationEntry) => {
|
|
@@ -126,7 +135,7 @@ context });
|
|
|
126
135
|
<div
|
|
127
136
|
ref={scrollRef}
|
|
128
137
|
onScroll={handleScroll}
|
|
129
|
-
className={"flex-grow min-h-0 overflow-y-auto overflow-x-
|
|
138
|
+
className={"flex-grow min-h-0 overflow-y-auto overflow-x-hidden no-scrollbar"}
|
|
130
139
|
style={{
|
|
131
140
|
maskImage: scrolled
|
|
132
141
|
? "linear-gradient(to bottom, transparent 0, black 20px, black calc(100% - 20px), transparent 100%)"
|
|
@@ -134,7 +143,7 @@ context });
|
|
|
134
143
|
}}>
|
|
135
144
|
|
|
136
145
|
{groupsToRender.map((group) => {
|
|
137
|
-
const entriesInGroup =
|
|
146
|
+
const entriesInGroup = filteredEntries.filter(e => e.group === group);
|
|
138
147
|
return (
|
|
139
148
|
<DrawerNavigationGroup
|
|
140
149
|
key={`drawer_group_${group}`}
|
|
@@ -146,7 +155,6 @@ context });
|
|
|
146
155
|
tooltipsOpen={tooltipsOpen}
|
|
147
156
|
adminMenuOpen={adminMenuOpen}
|
|
148
157
|
onItemClick={onItemClick}
|
|
149
|
-
hideHeader={adminModeController.mode === "studio"}
|
|
150
158
|
/>
|
|
151
159
|
);
|
|
152
160
|
})}
|
|
@@ -306,7 +314,7 @@ function DrawerModeSwitch({
|
|
|
306
314
|
return (
|
|
307
315
|
<div
|
|
308
316
|
className={cls(
|
|
309
|
-
"overflow-hidden transition-all duration-200 ease-in-out px-3",
|
|
317
|
+
"shrink-0 overflow-hidden transition-all duration-200 ease-in-out px-3",
|
|
310
318
|
showSwitch ? "opacity-100 h-7 mt-2 mb-0" : "opacity-0 pointer-events-none h-7 mt-2 mb-0"
|
|
311
319
|
)}
|
|
312
320
|
>
|
|
@@ -75,7 +75,7 @@ export function DrawerNavigationGroup({
|
|
|
75
75
|
{/* Group Header */}
|
|
76
76
|
{!hideHeader && (
|
|
77
77
|
<div
|
|
78
|
-
className={cls("pl-
|
|
78
|
+
className={cls("pl-3 pr-2 py-0.5 flex flex-row items-center transition-colors",
|
|
79
79
|
drawerOpen ? "cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-800/40 rounded-lg" : "opacity-0 invisible pointer-events-none"
|
|
80
80
|
)}
|
|
81
81
|
onClick={drawerOpen ? onToggleCollapsed : undefined}
|
|
@@ -83,14 +83,14 @@ export function DrawerNavigationGroup({
|
|
|
83
83
|
<ChevronDownIcon
|
|
84
84
|
size={iconSize.small}
|
|
85
85
|
className={cls(
|
|
86
|
-
"text-surface-
|
|
86
|
+
"text-surface-400 dark:text-surface-400 transition-transform duration-200 mr-1",
|
|
87
87
|
collapsed ? "-rotate-90" : "rotate-0"
|
|
88
88
|
)}
|
|
89
89
|
/>
|
|
90
90
|
<Typography
|
|
91
91
|
variant={"caption"}
|
|
92
92
|
color={"secondary"}
|
|
93
|
-
className="font-
|
|
93
|
+
className="font-semibold text-[11px] uppercase tracking-wider flex-grow line-clamp-1 text-surface-400 dark:text-surface-400"
|
|
94
94
|
>
|
|
95
95
|
{(group || t("views_group"))}
|
|
96
96
|
</Typography>
|
|
@@ -106,7 +106,7 @@ export function DrawerNavigationGroup({
|
|
|
106
106
|
<div
|
|
107
107
|
className={cls(
|
|
108
108
|
"transition-all duration-200 ease-in-out",
|
|
109
|
-
|
|
109
|
+
"overflow-hidden",
|
|
110
110
|
!hideHeader && "dark:bg-transparent",
|
|
111
111
|
!hideHeader ? (drawerOpen ? "rounded-lg" : "rounded-lg") : "rounded-lg",
|
|
112
112
|
(!hideHeader && collapsed) ? "max-h-0 opacity-0" : "max-h-[2000px] opacity-100"
|