@rebasepro/admin 0.4.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-Bo86h-d-.js → CollectionEditorDialog-C8E440oK.js} +3 -3
- package/dist/CollectionEditorDialog-C8E440oK.js.map +1 -0
- package/dist/{CollectionsStudioView-bsg4AT_Z.js → CollectionsStudioView-Brr_b06v.js} +4 -4
- package/dist/{CollectionsStudioView-bsg4AT_Z.js.map → CollectionsStudioView-Brr_b06v.js.map} +1 -1
- package/dist/{ExportCollectionAction-Cf-Id5uO.js → ExportCollectionAction-D3TTYXrq.js} +2 -2
- package/dist/{ExportCollectionAction-Cf-Id5uO.js.map → ExportCollectionAction-D3TTYXrq.js.map} +1 -1
- package/dist/{ImportCollectionAction-LN5sreK9.js → ImportCollectionAction-Dn7lya6E.js} +2 -2
- package/dist/{ImportCollectionAction-LN5sreK9.js.map → ImportCollectionAction-Dn7lya6E.js.map} +1 -1
- package/dist/{PropertyEditView-jCWCxmCz.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/{index-z3H8iqsj.js → index-D3S9x_RP.js} +2 -2
- package/dist/{index-z3H8iqsj.js.map → index-D3S9x_RP.js.map} +1 -1
- package/dist/{index-Cb0bPnzZ.js → index-D9RNzm01.js} +3 -3
- package/dist/index-D9RNzm01.js.map +1 -0
- package/dist/{index-BrqSvMG0.js → index-DrrT332R.js} +3 -3
- package/dist/index-DrrT332R.js.map +1 -0
- package/dist/index.js +4 -4
- package/dist/{util-CvNp6A-r.js → util-COYYD8zr.js} +79 -110
- package/dist/util-COYYD8zr.js.map +1 -0
- package/package.json +9 -10
- 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/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +5 -2
- package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +3 -4
- package/src/components/EntityDetailView.tsx +6 -9
- package/src/components/EntityEditView.tsx +9 -15
- package/src/components/EntitySidePanel.tsx +3 -0
- 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/dist/CollectionEditorDialog-Bo86h-d-.js.map +0 -1
- package/dist/PropertyEditView-jCWCxmCz.js.map +0 -1
- package/dist/index-BrqSvMG0.js.map +0 -1
- package/dist/index-Cb0bPnzZ.js.map +0 -1
- package/dist/util-CvNp6A-r.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.5.0",
|
|
5
5
|
"description": "Rebase CMS — content management views, forms, and routing",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/rebaseco"
|
|
@@ -80,17 +80,16 @@
|
|
|
80
80
|
"prosemirror-tables": "^1.8.5",
|
|
81
81
|
"prosemirror-transform": "^1.12.0",
|
|
82
82
|
"prosemirror-view": "^1.41.8",
|
|
83
|
-
"
|
|
83
|
+
"zod": "^3.25.76",
|
|
84
84
|
"react-dropzone": "^14.4.1",
|
|
85
85
|
"react-use-measure": "^2.1.7",
|
|
86
|
-
"
|
|
87
|
-
"@rebasepro/
|
|
88
|
-
"@rebasepro/
|
|
89
|
-
"@rebasepro/
|
|
90
|
-
"@rebasepro/
|
|
91
|
-
"@rebasepro/types": "0.
|
|
92
|
-
"@rebasepro/
|
|
93
|
-
"@rebasepro/ui": "0.4.0"
|
|
86
|
+
"@rebasepro/common": "0.5.0",
|
|
87
|
+
"@rebasepro/formex": "0.5.0",
|
|
88
|
+
"@rebasepro/core": "0.5.0",
|
|
89
|
+
"@rebasepro/schema-inference": "0.5.0",
|
|
90
|
+
"@rebasepro/utils": "0.5.0",
|
|
91
|
+
"@rebasepro/types": "0.5.0",
|
|
92
|
+
"@rebasepro/ui": "0.5.0"
|
|
94
93
|
},
|
|
95
94
|
"peerDependencies": {
|
|
96
95
|
"react": ">=19.0.0",
|
|
@@ -85,7 +85,7 @@ export function CollectionRelationsTab() {
|
|
|
85
85
|
<Button variant="filled" color="neutral" onClick={() => {
|
|
86
86
|
setEditingRelationIndex(-1);
|
|
87
87
|
setEditingRelationState({ relationName: "",
|
|
88
|
-
target: ""
|
|
88
|
+
target: "",
|
|
89
89
|
cardinality: "many",
|
|
90
90
|
direction: "owning" });
|
|
91
91
|
}}>
|
|
@@ -134,7 +134,7 @@ direction: "owning" });
|
|
|
134
134
|
<Button variant="text" onClick={() => {
|
|
135
135
|
setEditingRelationIndex(-1);
|
|
136
136
|
setEditingRelationState({ relationName: "",
|
|
137
|
-
target: ""
|
|
137
|
+
target: "",
|
|
138
138
|
cardinality: "many",
|
|
139
139
|
direction: "owning" });
|
|
140
140
|
}}>Create your first relation</Button>
|
|
@@ -50,7 +50,8 @@ import { MarkdownPropertyField } from "./properties/MarkdownPropertyField";
|
|
|
50
50
|
import { isValidRegExp, mergeDeep } from "@rebasepro/utils";
|
|
51
51
|
|
|
52
52
|
export type PropertyWithId = Property & {
|
|
53
|
-
id?: string
|
|
53
|
+
id?: string;
|
|
54
|
+
conditions?: import('@rebasepro/types').PropertyConditions;
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
export type OnPropertyChangedParams = {
|
|
@@ -76,7 +76,7 @@ export function PropertyFieldPreview({
|
|
|
76
76
|
|
|
77
77
|
<ErrorBoundary>
|
|
78
78
|
<Typography variant="caption" component="span" className="ml-auto shrink-0 text-text-disabled dark:text-text-disabled-dark font-mono bg-surface-100 dark:bg-surface-900 px-1.5 py-0.5 rounded mr-8">
|
|
79
|
-
{
|
|
79
|
+
{"columnType" in property ? (property as { columnType?: string }).columnType ?? property.type : property.type}
|
|
80
80
|
</Typography>
|
|
81
81
|
</ErrorBoundary>
|
|
82
82
|
|
|
@@ -146,7 +146,7 @@ export function NonEditablePropertyPreview({
|
|
|
146
146
|
|
|
147
147
|
{property && !isPropertyBuilder(property) && <ErrorBoundary>
|
|
148
148
|
<Typography variant="caption" component="span" className="ml-auto shrink-0 text-text-disabled dark:text-text-disabled-dark font-mono bg-surface-100 dark:bg-surface-900 px-1.5 py-0.5 rounded mr-8">
|
|
149
|
-
{
|
|
149
|
+
{"columnType" in property ? (property as { columnType?: string }).columnType ?? property.type : property.type}
|
|
150
150
|
</Typography>
|
|
151
151
|
</ErrorBoundary>}
|
|
152
152
|
</Paper>
|
package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from "@rebasepro/ui";
|
|
19
19
|
import { getFieldConfig, DEFAULT_FIELD_CONFIGS } from "../../../../_cms_internals";
|
|
20
20
|
import { Properties, Property, EnumValueConfig } from "@rebasepro/types";
|
|
21
|
+
import type { PropertyConditions } from "@rebasepro/types";
|
|
21
22
|
import { isPropertyBuilder } from "@rebasepro/common";
|
|
22
23
|
import { PropertyWithId } from "../../PropertyEditView";
|
|
23
24
|
import { getPropertyPaths } from "./property_paths";
|
|
@@ -817,7 +818,7 @@ export function ConditionsEditor({ disabled, collectionProperties }: ConditionsE
|
|
|
817
818
|
: [];
|
|
818
819
|
|
|
819
820
|
// Get current conditions from form values
|
|
820
|
-
const conditions:
|
|
821
|
+
const conditions: PropertyConditions = values.conditions ?? {};
|
|
821
822
|
|
|
822
823
|
const activeConditions: { type: ConditionType; group: ConditionGroup }[] = [];
|
|
823
824
|
|
package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx
CHANGED
|
@@ -528,7 +528,7 @@ export function EnumConditionsEditor({ disabled, collectionProperties }: EnumCon
|
|
|
528
528
|
const allEnumIds = propertyEnumValues.map(ev => String(ev.id));
|
|
529
529
|
|
|
530
530
|
// Get conditions from the correct path: values.conditions
|
|
531
|
-
const conditions =
|
|
531
|
+
const conditions = values.conditions ?? {};
|
|
532
532
|
|
|
533
533
|
// Parse existing enum conditions
|
|
534
534
|
const activeConditions: { type: EnumConditionType; config: EnumConditionConfig }[] = [];
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import React, { useCallback, useEffect } from "react";
|
|
2
2
|
|
|
3
|
+
/** Tracks events originating inside the inner (non-draggable) area. */
|
|
4
|
+
const innerClicked = new WeakSet<MouseEvent>();
|
|
5
|
+
|
|
3
6
|
interface DraggableProps {
|
|
4
7
|
containerRef: React.RefObject<HTMLDivElement | null>,
|
|
5
8
|
innerRef: React.RefObject<HTMLDivElement | null>,
|
|
@@ -22,7 +25,7 @@ export function useDraggable({
|
|
|
22
25
|
const listeningRef = React.useRef(false);
|
|
23
26
|
|
|
24
27
|
const onMouseDown = useCallback((event: MouseEvent) => {
|
|
25
|
-
if (event.button !== 0 || !containerRef.current || event.defaultPrevented || (event
|
|
28
|
+
if (event.button !== 0 || !containerRef.current || event.defaultPrevented || innerClicked.has(event)) {
|
|
26
29
|
return;
|
|
27
30
|
}
|
|
28
31
|
|
|
@@ -41,7 +44,7 @@ export function useDraggable({
|
|
|
41
44
|
}, [containerRef, onMove]);
|
|
42
45
|
|
|
43
46
|
const onMouseDownInner = useCallback((event: MouseEvent) => {
|
|
44
|
-
(event
|
|
47
|
+
innerClicked.add(event);
|
|
45
48
|
}, [])
|
|
46
49
|
|
|
47
50
|
const onSelect = useCallback((event: Event) => {
|
|
@@ -451,9 +451,8 @@ function resolveRelationDisplayName(
|
|
|
451
451
|
|
|
452
452
|
// Helper to check if a property is hidden/internal
|
|
453
453
|
const isHiddenProp = (p: Property): boolean => {
|
|
454
|
-
|
|
455
|
-
if (ui?.
|
|
456
|
-
if (ui?.disabled?.hidden) return true;
|
|
454
|
+
if (p.ui?.hideFromCollection) return true;
|
|
455
|
+
if (typeof p.ui?.disabled === "object" && p.ui.disabled.hidden) return true;
|
|
457
456
|
return false;
|
|
458
457
|
};
|
|
459
458
|
|
|
@@ -502,7 +501,7 @@ function resolveRelationDisplayName(
|
|
|
502
501
|
// 2. Try the entity cache (sessionStorage) as a fallback
|
|
503
502
|
if (id !== undefined && targetCollection) {
|
|
504
503
|
try {
|
|
505
|
-
const slug = targetCollection.slug ?? (targetCollection
|
|
504
|
+
const slug = targetCollection.slug ?? ("table" in targetCollection ? targetCollection.table : undefined);
|
|
506
505
|
if (slug) {
|
|
507
506
|
const cacheKey = `${slug}/${id}`;
|
|
508
507
|
const cached = getEntityFromCache(cacheKey) as { values?: Record<string, unknown> } | undefined;
|
|
@@ -152,27 +152,23 @@ function EntityDetailViewInner<M extends Record<string, unknown>>({
|
|
|
152
152
|
{ status: "existing", entityId }
|
|
153
153
|
), [collection, entityId]);
|
|
154
154
|
|
|
155
|
-
// Track whether
|
|
156
|
-
// See
|
|
157
|
-
const
|
|
155
|
+
// Track whether the user has explicitly clicked a tab in this component
|
|
156
|
+
// instance. See EntityEditViewInner for full explanation.
|
|
157
|
+
const userHasChangedTab = useRef(false);
|
|
158
158
|
|
|
159
159
|
const [selectedTab, setSelectedTab] = useState<string>(() => {
|
|
160
160
|
const val = selectedTabProp ?? defaultSelectedView ?? MAIN_TAB_VALUE;
|
|
161
|
-
hasAppliedDefault.current = true;
|
|
162
161
|
return val === "edit" ? MAIN_TAB_VALUE : val;
|
|
163
162
|
});
|
|
164
163
|
useEffect(() => {
|
|
165
|
-
const val =
|
|
164
|
+
const val = userHasChangedTab.current
|
|
166
165
|
? (selectedTabProp ?? MAIN_TAB_VALUE)
|
|
167
166
|
: (selectedTabProp ?? defaultSelectedView ?? MAIN_TAB_VALUE);
|
|
168
167
|
const target = val === "edit" ? MAIN_TAB_VALUE : val;
|
|
169
|
-
if (!hasAppliedDefault.current) {
|
|
170
|
-
hasAppliedDefault.current = true;
|
|
171
|
-
}
|
|
172
168
|
if (target !== selectedTab) {
|
|
173
169
|
setSelectedTab(target);
|
|
174
170
|
}
|
|
175
|
-
}, [selectedTabProp]);
|
|
171
|
+
}, [selectedTabProp, defaultSelectedView]);
|
|
176
172
|
|
|
177
173
|
const subcollections = getSubcollections(collection).filter(c => !c.hideFromNavigation);
|
|
178
174
|
const subcollectionsCount = subcollections?.length ?? 0;
|
|
@@ -347,6 +343,7 @@ function EntityDetailViewInner<M extends Record<string, unknown>>({
|
|
|
347
343
|
}).filter(Boolean);
|
|
348
344
|
|
|
349
345
|
const onSideTabClick = useCallback((value: string) => {
|
|
346
|
+
userHasChangedTab.current = true;
|
|
350
347
|
setSelectedTab(value);
|
|
351
348
|
onTabChange?.({
|
|
352
349
|
path,
|
|
@@ -224,33 +224,26 @@ export function EntityEditViewInner<M extends Record<string, unknown>>({
|
|
|
224
224
|
}
|
|
225
225
|
), [collection, status, entityId]);
|
|
226
226
|
|
|
227
|
-
// Track whether
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
const hasAppliedDefault = useRef(false);
|
|
227
|
+
// Track whether the user has explicitly clicked a tab in this component
|
|
228
|
+
// instance. When false, we fall back to defaultSelectedView (which may
|
|
229
|
+
// resolve asynchronously if the collection loads from the registry after
|
|
230
|
+
// mount). Once true, selectedTabProp=undefined means the user selected
|
|
231
|
+
// the form tab, so we must NOT re-apply defaultSelectedView.
|
|
232
|
+
const userHasChangedTab = useRef(false);
|
|
234
233
|
|
|
235
234
|
const [selectedTab, setSelectedTab] = useState<string>(() => {
|
|
236
235
|
const val = selectedTabProp ?? defaultSelectedView ?? MAIN_TAB_VALUE;
|
|
237
|
-
hasAppliedDefault.current = true;
|
|
238
236
|
return val === "edit" ? MAIN_TAB_VALUE : val;
|
|
239
237
|
});
|
|
240
238
|
useEffect(() => {
|
|
241
|
-
|
|
242
|
-
// back to defaultSelectedView, because undefined now means "form tab".
|
|
243
|
-
const val = hasAppliedDefault.current
|
|
239
|
+
const val = userHasChangedTab.current
|
|
244
240
|
? (selectedTabProp ?? MAIN_TAB_VALUE)
|
|
245
241
|
: (selectedTabProp ?? defaultSelectedView ?? MAIN_TAB_VALUE);
|
|
246
242
|
const target = val === "edit" ? MAIN_TAB_VALUE : val;
|
|
247
|
-
if (!hasAppliedDefault.current) {
|
|
248
|
-
hasAppliedDefault.current = true;
|
|
249
|
-
}
|
|
250
243
|
if (target !== selectedTab) {
|
|
251
244
|
setSelectedTab(target);
|
|
252
245
|
}
|
|
253
|
-
}, [selectedTabProp]);
|
|
246
|
+
}, [selectedTabProp, defaultSelectedView]);
|
|
254
247
|
|
|
255
248
|
const subcollections = getSubcollections(collection).filter(c => !c.hideFromNavigation);
|
|
256
249
|
const subcollectionsCount = subcollections?.length ?? 0;
|
|
@@ -420,6 +413,7 @@ export function EntityEditViewInner<M extends Record<string, unknown>>({
|
|
|
420
413
|
}).filter(Boolean);
|
|
421
414
|
|
|
422
415
|
const onSideTabClick = useCallback((value: string) => {
|
|
416
|
+
userHasChangedTab.current = true;
|
|
423
417
|
setSelectedTab(value);
|
|
424
418
|
if (status === "existing") {
|
|
425
419
|
onTabChange?.({
|
|
@@ -102,6 +102,9 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
102
102
|
// editor / Studio and is not available on the collection object the
|
|
103
103
|
// caller passed to sideEntityController.open().
|
|
104
104
|
const hasCorrectedDefaultView = useRef(false);
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
hasCorrectedDefaultView.current = false;
|
|
107
|
+
}, [entityId]);
|
|
105
108
|
useEffect(() => {
|
|
106
109
|
if (hasCorrectedDefaultView.current) return;
|
|
107
110
|
if (selectedTab) return; // Already has a tab — no correction needed
|
|
@@ -219,7 +219,7 @@ function FieldInternal<CustomProps, M extends Record<string, unknown>>
|
|
|
219
219
|
collection: context.collection,
|
|
220
220
|
propertyKey: propertyKey,
|
|
221
221
|
property: property,
|
|
222
|
-
Component: Component as
|
|
222
|
+
Component: Component as ComponentType<FieldProps<Property, unknown, M>>,
|
|
223
223
|
plugins: plugins
|
|
224
224
|
});
|
|
225
225
|
const UsedComponent: ComponentType<FieldProps<Property, any, any>> = WrappedComponent ?? Component;
|
|
@@ -348,7 +348,7 @@ function MapKeyValueRow<T extends Record<string, unknown>>({
|
|
|
348
348
|
value={arrayValue[index]}
|
|
349
349
|
disabled={disabled || !fieldKey}
|
|
350
350
|
setValue={(newValue) => {
|
|
351
|
-
const newArrayValue = [...arrayValue] as
|
|
351
|
+
const newArrayValue = [...arrayValue] as unknown[];
|
|
352
352
|
newArrayValue[index] = newValue;
|
|
353
353
|
setValue({
|
|
354
354
|
...value,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Properties } from "@rebasepro/types";
|
|
2
1
|
import type { FieldProps, PropertyFieldBindingProps } from "../../types/fields";
|
|
3
2
|
import type { MapProperty } from "@rebasepro/types";
|
|
4
3
|
import React from "react";
|
|
@@ -10,8 +9,7 @@ import { getIconForProperty } from "../../util/property_utils";
|
|
|
10
9
|
import { isHidden, isReadOnly } from "@rebasepro/common";
|
|
11
10
|
import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
|
|
12
11
|
import { PropertyFieldBinding } from "../PropertyFieldBinding";
|
|
13
|
-
import { cls, ExpandablePanel
|
|
14
|
-
import { pick } from "@rebasepro/utils";
|
|
12
|
+
import { cls, ExpandablePanel } from "@rebasepro/ui";
|
|
15
13
|
|
|
16
14
|
/**
|
|
17
15
|
* Field that renders the children property fields
|
|
@@ -35,7 +33,6 @@ export function MapFieldBinding({
|
|
|
35
33
|
onPropertyChange
|
|
36
34
|
}: FieldProps<MapProperty>) {
|
|
37
35
|
|
|
38
|
-
const pickOnlySomeKeys = property.pickOnlySomeKeys || false;
|
|
39
36
|
const expanded = property.ui?.expanded === undefined ? true : property.ui?.expanded;
|
|
40
37
|
const minimalistView = minimalistViewProp || property.ui?.minimalistView;
|
|
41
38
|
const { t } = useTranslation();
|
|
@@ -44,19 +41,7 @@ export function MapFieldBinding({
|
|
|
44
41
|
throw Error(`You need to specify a 'properties' prop (or specify a custom field) in your map property ${propertyKey}`);
|
|
45
42
|
}
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
if (pickOnlySomeKeys) {
|
|
49
|
-
if (value) {
|
|
50
|
-
mapProperties = pick(property.properties,
|
|
51
|
-
...Object.keys(value)
|
|
52
|
-
.filter(key => key in property.properties!)
|
|
53
|
-
) as Properties;
|
|
54
|
-
} else {
|
|
55
|
-
mapProperties = {};
|
|
56
|
-
}
|
|
57
|
-
} else {
|
|
58
|
-
mapProperties = property.properties;
|
|
59
|
-
}
|
|
44
|
+
const mapProperties = property.properties;
|
|
60
45
|
|
|
61
46
|
const mapFormView = <>
|
|
62
47
|
<div
|
|
@@ -96,7 +81,7 @@ export function MapFieldBinding({
|
|
|
96
81
|
}
|
|
97
82
|
</div>
|
|
98
83
|
|
|
99
|
-
|
|
84
|
+
|
|
100
85
|
|
|
101
86
|
</>
|
|
102
87
|
;
|
|
@@ -133,30 +118,3 @@ export function MapFieldBinding({
|
|
|
133
118
|
);
|
|
134
119
|
}
|
|
135
120
|
|
|
136
|
-
const buildPickKeysSelect = (disabled: boolean, properties: Properties, setValue: (value: Record<string, unknown> | null) => void, value: Record<string, unknown> | undefined) => {
|
|
137
|
-
|
|
138
|
-
const keys = Object.keys(properties)
|
|
139
|
-
.filter((key) => !value || !(key in value));
|
|
140
|
-
|
|
141
|
-
const handleAddProperty = (updatedValue: string | string[]) => {
|
|
142
|
-
setValue({
|
|
143
|
-
...value,
|
|
144
|
-
[updatedValue as string]: null
|
|
145
|
-
});
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
if (!keys.length) return <></>;
|
|
149
|
-
|
|
150
|
-
return <div className={"m-4"}>
|
|
151
|
-
<InputLabel>Add property</InputLabel>
|
|
152
|
-
<Select
|
|
153
|
-
value={""}
|
|
154
|
-
fullWidth={true}
|
|
155
|
-
disabled={disabled}
|
|
156
|
-
onValueChange={handleAddProperty}
|
|
157
|
-
renderValue={(key) => (properties as Properties)[key].name || key}>
|
|
158
|
-
{keys.map((key) => <SelectItem key={key}
|
|
159
|
-
value={key}>{(properties as Properties)[key].name || key}</SelectItem>)}
|
|
160
|
-
</Select>
|
|
161
|
-
</div>;
|
|
162
|
-
};
|