@firecms/core 3.0.0-canary.204 → 3.0.0-canary.206

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.
@@ -1,4 +1,4 @@
1
- import { EntityCollection, EntitySidePanelProps, NavigationController, SideDialogsController, SideEntityController } from "../types";
2
- export declare function getEntityViewWidth(props: EntitySidePanelProps<any>, small: boolean): string;
1
+ import { CustomizationController, EntityCollection, EntitySidePanelProps, NavigationController, SideDialogsController, SideEntityController } from "../types";
2
+ export declare function getEntityViewWidth(props: EntitySidePanelProps<any>, small: boolean, customizationController: CustomizationController): string;
3
3
  export declare const useBuildSideEntityController: (navigation: NavigationController, sideDialogsController: SideDialogsController) => SideEntityController;
4
4
  export declare function buildSidePanelsFromUrl(path: string, collections: EntityCollection[], newFlag: boolean): EntitySidePanelProps<any>[];
@@ -1,4 +1,4 @@
1
- import { ArrayProperty, CMSType, EntityCollection, EntityCustomView, EntityValues, EnumValueConfig, EnumValues, NumberProperty, PropertiesOrBuilders, PropertyConfig, PropertyOrBuilder, ResolvedArrayProperty, ResolvedEntityCollection, ResolvedNumberProperty, ResolvedProperties, ResolvedProperty, ResolvedStringProperty, StringProperty, UserConfigurationPersistence } from "../types";
1
+ import { ArrayProperty, CMSType, CustomizationController, EntityCollection, EntityCustomView, EntityValues, EnumValueConfig, EnumValues, NumberProperty, PropertiesOrBuilders, PropertyConfig, PropertyOrBuilder, ResolvedArrayProperty, ResolvedEntityCollection, ResolvedNumberProperty, ResolvedProperties, ResolvedProperty, ResolvedStringProperty, StringProperty, UserConfigurationPersistence } from "../types";
2
2
  export declare const resolveCollection: <M extends Record<string, any>>({ collection, path, entityId, values, previousValues, userConfigPersistence, propertyConfigs, ignoreMissingFields }: {
3
3
  collection: EntityCollection<M> | ResolvedEntityCollection<M>;
4
4
  path: string;
@@ -76,3 +76,8 @@ export declare function resolveProperties<M extends Record<string, any>>({ prope
76
76
  export declare function resolvePropertyEnum(property: StringProperty | NumberProperty, fromBuilder?: boolean): ResolvedStringProperty | ResolvedNumberProperty;
77
77
  export declare function resolveEnumValues(input: EnumValues): EnumValueConfig[] | undefined;
78
78
  export declare function resolveEntityView(entityView: string | EntityCustomView<any>, contextEntityViews?: EntityCustomView<any>[]): EntityCustomView<any> | undefined;
79
+ export declare function resolvedSelectedEntityView<M extends Record<string, any>>(customViews: (string | EntityCustomView<M>)[] | undefined, customizationController: CustomizationController, selectedTab?: string): {
80
+ resolvedEntityViews: EntityCustomView[];
81
+ selectedEntityView: EntityCustomView | undefined;
82
+ selectedSecondaryForm: EntityCustomView | undefined;
83
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@firecms/core",
3
3
  "type": "module",
4
- "version": "3.0.0-canary.204",
4
+ "version": "3.0.0-canary.206",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/firecmsco"
@@ -50,9 +50,9 @@
50
50
  "./package.json": "./package.json"
51
51
  },
52
52
  "dependencies": {
53
- "@firecms/editor": "^3.0.0-canary.204",
54
- "@firecms/formex": "^3.0.0-canary.204",
55
- "@firecms/ui": "^3.0.0-canary.204",
53
+ "@firecms/editor": "^3.0.0-canary.206",
54
+ "@firecms/formex": "^3.0.0-canary.206",
55
+ "@firecms/ui": "^3.0.0-canary.206",
56
56
  "@hello-pangea/dnd": "^17.0.0",
57
57
  "@radix-ui/react-portal": "^1.1.3",
58
58
  "clsx": "^2.1.1",
@@ -104,7 +104,7 @@
104
104
  "dist",
105
105
  "src"
106
106
  ],
107
- "gitHead": "2fb107e78d8fc3ade463adaf00908e3a8c812a0f",
107
+ "gitHead": "1e2b2703b9a4c0b7282a2a489193f57f1754730e",
108
108
  "publishConfig": {
109
109
  "access": "public"
110
110
  },
@@ -1,8 +1,13 @@
1
1
  import React, { useEffect, useMemo, useState } from "react";
2
- import { Entity, EntityCollection, EntityCustomView, EntityStatus, FireCMSPlugin, FormContext, User } from "../types";
2
+ import { Entity, EntityCollection, EntityStatus, FireCMSPlugin, FormContext, User } from "../types";
3
3
 
4
4
  import { CircularProgressCenter, EntityCollectionView, EntityView, ErrorBoundary } from "../components";
5
- import { canEditEntity, removeInitialAndTrailingSlashes, resolveDefaultSelectedView, resolveEntityView } from "../util";
5
+ import {
6
+ canEditEntity,
7
+ removeInitialAndTrailingSlashes,
8
+ resolveDefaultSelectedView,
9
+ resolvedSelectedEntityView
10
+ } from "../util";
6
11
 
7
12
  import {
8
13
  useAuthController,
@@ -13,7 +18,7 @@ import {
13
18
  } from "../hooks";
14
19
  import { CircularProgress, cls, defaultBorderMixin, Tab, Tabs, Typography } from "@firecms/ui";
15
20
  import { getEntityFromCache } from "../util/entity_cache";
16
- import { EntityForm, EntityFormProps, FormLayoutInner } from "../form";
21
+ import { EntityForm, EntityFormProps } from "../form";
17
22
  import { EntityEditViewFormActions } from "./EntityEditViewFormActions";
18
23
 
19
24
  const MAIN_TAB_VALUE = "main_##Q$SC^#S6";
@@ -120,43 +125,6 @@ export function EntityEditView<M extends Record<string, any>, USER extends User>
120
125
  />;
121
126
  }
122
127
 
123
- function SecondaryForm<M extends object>({
124
- collection,
125
- className,
126
- customView,
127
- entity,
128
- formContext,
129
- forceActionsAtTheBottom,
130
- }: {
131
- className?: string,
132
- customView: EntityCustomView,
133
- formContext: FormContext<M>,
134
- collection: EntityCollection<M>,
135
- forceActionsAtTheBottom?: boolean,
136
- entity: Entity<M> | undefined,
137
- }) {
138
-
139
- if (!customView.Builder) {
140
- console.error("customView.Builder is not defined");
141
- return null;
142
- }
143
-
144
- return <FormLayoutInner
145
- className={className}
146
- forceActionsAtTheBottom={forceActionsAtTheBottom}
147
- formContext={formContext}
148
- EntityFormActionsComponent={EntityEditViewFormActions}>
149
- <ErrorBoundary>
150
- {formContext && <customView.Builder
151
- collection={collection}
152
- entity={entity}
153
- modifiedValues={formContext.formex.values ?? entity?.values}
154
- formContext={formContext}
155
- />}
156
- </ErrorBoundary>
157
- </FormLayoutInner>;
158
- }
159
-
160
128
  export function EntityEditViewInner<M extends Record<string, any>>({
161
129
  path,
162
130
  entityId,
@@ -220,15 +188,11 @@ export function EntityEditViewInner<M extends Record<string, any>>({
220
188
  const customViewsCount = customViews?.length ?? 0;
221
189
  const hasAdditionalViews = customViewsCount > 0 || subcollectionsCount > 0;
222
190
 
223
- const resolvedEntityViews = customViews ? customViews
224
- .map(e => resolveEntityView(e, customizationController.entityViews))
225
- .filter(Boolean) as EntityCustomView[]
226
- : [];
227
-
228
- const selectedEntityView = resolvedEntityViews.find(e => e.key === selectedTab);
229
- const selectedSecondaryForm = formContext
230
- && customViews
231
- && resolvedEntityViews.filter(e => e.includeActions).find(e => e.key === selectedTab);
191
+ const {
192
+ resolvedEntityViews,
193
+ selectedEntityView,
194
+ selectedSecondaryForm
195
+ } = resolvedSelectedEntityView(customViews, customizationController, selectedTab);
232
196
 
233
197
  const actionsAtTheBottom = !largeLayout || layout === "side_panel" || selectedEntityView?.includeActions === "bottom";
234
198
 
@@ -305,7 +269,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
305
269
  path,
306
270
  entityId,
307
271
  selectedTab: value === MAIN_TAB_VALUE ? undefined : value,
308
- collection
272
+ collection,
309
273
  });
310
274
  }
311
275
  };
@@ -141,14 +141,14 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
141
141
  path,
142
142
  entityId,
143
143
  selectedTab,
144
- collection
144
+ collection,
145
145
  }) => {
146
146
  sideEntityController.replace({
147
147
  path,
148
148
  entityId,
149
149
  selectedTab,
150
150
  updateUrl: true,
151
- collection
151
+ collection,
152
152
  });
153
153
  }}
154
154
  formProps={props.formProps}
@@ -131,7 +131,7 @@ export function EntityForm<M extends Record<string, any>>({
131
131
  entityId: entityIdProp,
132
132
  collection,
133
133
  path,
134
- values: valuesToBeSaved,
134
+ values: valuesToBeSaved
135
135
  });
136
136
  }, false, 2000);
137
137
 
@@ -222,6 +222,29 @@ export function EntityForm<M extends Record<string, any>>({
222
222
  }
223
223
  });
224
224
 
225
+
226
+ useEffect(() => {
227
+
228
+ const handleKeyDown = (e: KeyboardEvent) => {
229
+ const isUndo = (e.metaKey || e.ctrlKey) && !e.shiftKey && e.key.toLowerCase() === "z";
230
+ const isRedo =
231
+ ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === "z") ||
232
+ ((e.metaKey || e.ctrlKey) && !e.shiftKey && e.key.toLowerCase() === "y");
233
+
234
+ if (isUndo && formex.canUndo) {
235
+ e.preventDefault();
236
+ formex.undo();
237
+ } else if (isRedo && formex.canRedo) {
238
+ e.preventDefault();
239
+ formex.redo();
240
+ }
241
+ };
242
+
243
+ window.addEventListener("keydown", handleKeyDown);
244
+ return () => window.removeEventListener("keydown", handleKeyDown);
245
+
246
+ }, [formex]);
247
+
225
248
  const resolvedCollection = useMemo(() => resolveCollection<M>({
226
249
  collection,
227
250
  path,
@@ -349,7 +372,7 @@ export function EntityForm<M extends Record<string, any>>({
349
372
  path,
350
373
  entityId,
351
374
  values,
352
- previousValues,
375
+ previousValues
353
376
  });
354
377
  }
355
378
  };
@@ -589,7 +612,7 @@ export function EntityForm<M extends Record<string, any>>({
589
612
 
590
613
  const formView = <ErrorBoundary>
591
614
  <>
592
- <div className={"w-full py-2 flex flex-col items-start my-4 lg:my-6"}>
615
+ {!Builder && <div className={"w-full py-2 flex flex-col items-start my-4 lg:my-6"}>
593
616
  <Typography
594
617
  className={"py-4 flex-grow line-clamp-1 " + (collection.hideIdFromForm ? "mb-2" : "mb-0")}
595
618
  variant={"h4"}>
@@ -601,11 +624,11 @@ export function EntityForm<M extends Record<string, any>>({
601
624
  {entity?.path ?? path}/{entityId}
602
625
  </code>
603
626
  </Alert>}
604
- </div>
627
+ </div>}
605
628
 
606
629
  {children}
607
630
 
608
- {!collection.hideIdFromForm &&
631
+ {!Builder && !collection.hideIdFromForm &&
609
632
  <CustomIdField customId={collection.customId}
610
633
  entityId={entityId}
611
634
  status={status}
@@ -631,104 +654,14 @@ export function EntityForm<M extends Record<string, any>>({
631
654
  onIdChange(entityId);
632
655
  }, [entityId, onIdChange]);
633
656
 
634
- return (
635
- <FormLayoutInner
636
- className={className}
637
- id={`form_${path}`}
638
- pluginActions={pluginActions}
639
- forceActionsAtTheBottom={forceActionsAtTheBottom}
640
- EntityFormActionsComponent={EntityFormActionsComponent}
641
- formContext={formContext}
642
- showDefaultActions={showDefaultActions}>
643
- {formView}
644
- </FormLayoutInner>
645
- );
646
- }
647
-
648
- function getInitialEntityValues<M extends object>(
649
- collection: EntityCollection,
650
- path: string,
651
- status: "new" | "existing" | "copy",
652
- entity: Entity<M> | undefined,
653
- propertyConfigs?: Record<string, PropertyConfig>
654
- ): Partial<EntityValues<M>> {
655
- const resolvedCollection = resolveCollection({
656
- collection,
657
- path,
658
- values: entity?.values,
659
- propertyConfigs
660
- });
661
- const properties = resolvedCollection.properties;
662
- if ((status === "existing" || status === "copy") && entity) {
663
- if (!collection.alwaysApplyDefaultValues) {
664
- return entity.values ?? getDefaultValuesFor(properties);
665
- } else {
666
- const defaultValues = getDefaultValuesFor(properties);
667
- return mergeDeep(defaultValues, entity.values ?? {});
668
- }
669
- } else if (status === "new") {
670
- return getDefaultValuesFor(properties);
671
- } else {
672
- console.error({
673
- status,
674
- entity
675
- });
676
- throw new Error("Form has not been initialised with the correct parameters");
677
- }
678
- }
679
-
680
- export function yupToFormErrors(yupError: ValidationError): Record<string, any> {
681
- let errors: Record<string, any> = {};
682
- if (yupError.inner) {
683
- if (yupError.inner.length === 0) {
684
- return setIn(errors, yupError.path!, yupError.message);
685
- }
686
- for (const err of yupError.inner) {
687
- if (!getIn(errors, err.path!)) {
688
- errors = setIn(errors, err.path!, err.message);
689
- }
690
- }
691
- }
692
- return errors;
693
- }
694
-
695
- export function FormLayoutInner({
696
- id,
697
- formContext,
698
- children,
699
- className,
700
- forceActionsAtTheBottom,
701
- pluginActions,
702
- EntityFormActionsComponent,
703
- showDefaultActions,
704
- }: {
705
- id?: string,
706
- formContext: FormContext,
707
- children: React.ReactNode,
708
- className?: string,
709
- forceActionsAtTheBottom?: boolean,
710
- pluginActions?: React.ReactNode[],
711
- EntityFormActionsComponent: React.FC<EntityFormActionsProps>;
712
- showDefaultActions?: boolean;
713
- }) {
714
-
715
- const formex = formContext.formex;
716
- const collection = formContext.collection;
717
- const path = formContext.path;
718
- const entity = formContext.entity;
719
- const savingError = formContext.savingError;
720
- const status = formContext.status;
721
- const openEntityMode = formContext.openEntityMode;
722
657
  const disabled = formex.isSubmitting || (!formex.dirty && status === "existing");
723
658
 
724
- const customizationController = useCustomizationController();
725
-
726
- if (!collection || !path) {
659
+ if (!resolvedCollection || !path) {
727
660
  throw Error("INTERNAL: Collection and path must be defined in form context");
728
661
  }
729
662
 
730
663
  const dialogActions = <EntityFormActionsComponent
731
- collection={collection}
664
+ collection={resolvedCollection}
732
665
  path={path}
733
666
  entity={entity}
734
667
  layout={forceActionsAtTheBottom ? "bottom" : "side"}
@@ -746,12 +679,12 @@ export function FormLayoutInner({
746
679
  <form
747
680
  onSubmit={formContext.formex.handleSubmit}
748
681
  onReset={() => formex.resetForm({
749
- values: getInitialEntityValues(collection, path, status, entity, customizationController.propertyConfigs),
682
+ values: getInitialEntityValues(collection, path, status, entity, customizationController.propertyConfigs) as M
750
683
  })}
751
684
  noValidate
752
685
  className={cls("flex-1 flex flex-row w-full overflow-y-auto justify-center", className)}>
753
686
  <div
754
- id={id}
687
+ id={`form_${path}`}
755
688
  className={cls("relative flex flex-row max-w-4xl lg:max-w-3xl xl:max-w-4xl 2xl:max-w-6xl w-full h-fit")}>
756
689
 
757
690
  <div className={cls("flex flex-col w-full pt-12 pb-16 px-4 sm:px-8 md:px-10")}>
@@ -769,7 +702,8 @@ export function FormLayoutInner({
769
702
  <CheckIcon size={"smallest"}/>
770
703
  </Chip>
771
704
  </Tooltip>}
772
- {children}
705
+
706
+ {formView}
773
707
 
774
708
  </div>
775
709
 
@@ -781,6 +715,53 @@ export function FormLayoutInner({
781
715
  );
782
716
  }
783
717
 
718
+ function getInitialEntityValues<M extends object>(
719
+ collection: EntityCollection,
720
+ path: string,
721
+ status: "new" | "existing" | "copy",
722
+ entity: Entity<M> | undefined,
723
+ propertyConfigs?: Record<string, PropertyConfig>
724
+ ): Partial<EntityValues<M>> {
725
+ const resolvedCollection = resolveCollection({
726
+ collection,
727
+ path,
728
+ values: entity?.values,
729
+ propertyConfigs
730
+ });
731
+ const properties = resolvedCollection.properties;
732
+ if ((status === "existing" || status === "copy") && entity) {
733
+ if (!collection.alwaysApplyDefaultValues) {
734
+ return entity.values ?? getDefaultValuesFor(properties);
735
+ } else {
736
+ const defaultValues = getDefaultValuesFor(properties);
737
+ return mergeDeep(defaultValues, entity.values ?? {});
738
+ }
739
+ } else if (status === "new") {
740
+ return getDefaultValuesFor(properties);
741
+ } else {
742
+ console.error({
743
+ status,
744
+ entity
745
+ });
746
+ throw new Error("Form has not been initialised with the correct parameters");
747
+ }
748
+ }
749
+
750
+ export function yupToFormErrors(yupError: ValidationError): Record<string, any> {
751
+ let errors: Record<string, any> = {};
752
+ if (yupError.inner) {
753
+ if (yupError.inner.length === 0) {
754
+ return setIn(errors, yupError.path!, yupError.message);
755
+ }
756
+ for (const err of yupError.inner) {
757
+ if (!getIn(errors, err.path!)) {
758
+ errors = setIn(errors, err.path!, err.message);
759
+ }
760
+ }
761
+ }
762
+ return errors;
763
+ }
764
+
784
765
  function useOnAutoSave(autoSave: undefined | boolean, formex: FormexController<any>, lastSavedValues: any, save: (values: EntityValues<any>) => Promise<void>) {
785
766
  if (!autoSave) return;
786
767
  useEffect(() => {
@@ -1,5 +1,6 @@
1
1
  import { useCallback, useEffect, useRef } from "react";
2
2
  import {
3
+ CustomizationController,
3
4
  EntityCollection,
4
5
  EntitySidePanelProps,
5
6
  NavigationController,
@@ -10,17 +11,28 @@ import {
10
11
  } from "../types";
11
12
  import { getNavigationEntriesFromPath, NavigationViewInternal } from "../util/navigation_from_path";
12
13
  import { useLocation } from "react-router-dom";
13
- import { removeInitialAndTrailingSlashes, resolveCollection, resolveDefaultSelectedView } from "../util";
14
+ import {
15
+ removeInitialAndTrailingSlashes,
16
+ resolveCollection,
17
+ resolveDefaultSelectedView,
18
+ resolvedSelectedEntityView
19
+ } from "../util";
14
20
  import { ADDITIONAL_TAB_WIDTH, CONTAINER_FULL_WIDTH, FORM_CONTAINER_WIDTH } from "./common";
15
- import { useLargeLayout } from "../hooks";
21
+ import { useCustomizationController, useLargeLayout } from "../hooks";
16
22
  import { EntitySidePanel } from "../core/EntitySidePanel";
17
23
 
18
24
  const NEW_URL_HASH = "new_side";
19
25
  const SIDE_URL_HASH = "side";
20
26
 
21
- export function getEntityViewWidth(props: EntitySidePanelProps<any>, small: boolean): string {
27
+ export function getEntityViewWidth(props: EntitySidePanelProps<any>, small: boolean, customizationController: CustomizationController): string {
22
28
  if (small) return CONTAINER_FULL_WIDTH;
23
- const mainViewSelected = !props.selectedTab;
29
+
30
+ const {
31
+ selectedSecondaryForm
32
+ } = resolvedSelectedEntityView(props.collection?.entityViews, customizationController, props.selectedTab);
33
+
34
+ const shouldUseSmallLayout = !props.selectedTab || Boolean(selectedSecondaryForm);
35
+
24
36
  let resolvedWidth: string | undefined;
25
37
  if (props.width) {
26
38
  resolvedWidth = typeof props.width === "number" ? `${props.width}px` : props.width;
@@ -28,7 +40,7 @@ export function getEntityViewWidth(props: EntitySidePanelProps<any>, small: bool
28
40
  resolvedWidth = typeof props.collection.sideDialogWidth === "number" ? `${props.collection.sideDialogWidth}px` : props.collection.sideDialogWidth;
29
41
  }
30
42
 
31
- if (!mainViewSelected) {
43
+ if (!shouldUseSmallLayout) {
32
44
  return `calc(${ADDITIONAL_TAB_WIDTH} + ${resolvedWidth ?? FORM_CONTAINER_WIDTH})`
33
45
  } else {
34
46
  if (resolvedWidth) {
@@ -89,6 +101,7 @@ export const useBuildSideEntityController = (navigation: NavigationController,
89
101
 
90
102
  const location = useLocation();
91
103
  const initialised = useRef<boolean>(false);
104
+ const customizationController = useCustomizationController();
92
105
 
93
106
  const smallLayout = !useLargeLayout();
94
107
 
@@ -105,9 +118,9 @@ export const useBuildSideEntityController = (navigation: NavigationController,
105
118
  for (let i = 0; i < panelsFromUrl.length; i++) {
106
119
  const props = panelsFromUrl[i];
107
120
  if (i === 0)
108
- sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout));
121
+ sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController));
109
122
  else
110
- sideDialogsController.open(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout))
123
+ sideDialogsController.open(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController))
111
124
  }
112
125
  }
113
126
  initialised.current = true;
@@ -127,7 +140,7 @@ export const useBuildSideEntityController = (navigation: NavigationController,
127
140
  return;
128
141
  }
129
142
  const lastPanel = panelsFromUrl[panelsFromUrl.length - 1];
130
- const panelProps = propsToSidePanel(lastPanel, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout);
143
+ const panelProps = propsToSidePanel(lastPanel, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController);
131
144
  const lastCurrentPanel = currentPanelKeys.length > 0 ? currentPanelKeys[currentPanelKeys.length - 1] : undefined;
132
145
  if (!lastCurrentPanel || lastCurrentPanel !== panelProps.key) {
133
146
  sideDialogsController.replace(panelProps);
@@ -140,7 +153,7 @@ export const useBuildSideEntityController = (navigation: NavigationController,
140
153
  useEffect(() => {
141
154
  const updatedSidePanels = sideDialogsController.sidePanels.map(sidePanelProps => {
142
155
  if (sidePanelProps.additional) {
143
- return propsToSidePanel(sidePanelProps.additional, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout);
156
+ return propsToSidePanel(sidePanelProps.additional, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController);
144
157
  }
145
158
  return sidePanelProps;
146
159
  });
@@ -172,7 +185,8 @@ export const useBuildSideEntityController = (navigation: NavigationController,
172
185
  },
173
186
  navigation.buildUrlCollectionPath,
174
187
  navigation.resolveIdsFrom,
175
- smallLayout
188
+ smallLayout,
189
+ customizationController
176
190
  ));
177
191
 
178
192
  }, [sideDialogsController, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout]);
@@ -183,7 +197,7 @@ export const useBuildSideEntityController = (navigation: NavigationController,
183
197
  throw Error("If you want to copy an entity you need to provide an entityId");
184
198
  }
185
199
 
186
- sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout));
200
+ sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController));
187
201
 
188
202
  }, [navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, sideDialogsController, smallLayout]);
189
203
 
@@ -242,11 +256,11 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
242
256
  return sidePanel ? [sidePanel] : [];
243
257
  }
244
258
 
245
-
246
259
  const propsToSidePanel = (props: EntitySidePanelProps,
247
260
  buildUrlCollectionPath: (path: string) => string,
248
261
  resolveIdsFrom: (pathWithAliases: string) => string,
249
- smallLayout: boolean): SideDialogPanelProps => {
262
+ smallLayout: boolean,
263
+ customizationController: CustomizationController): SideDialogPanelProps => {
250
264
 
251
265
  const collectionPath = removeInitialAndTrailingSlashes(props.path);
252
266
 
@@ -261,7 +275,7 @@ const propsToSidePanel = (props: EntitySidePanelProps,
261
275
  formProps: props.formProps
262
276
  };
263
277
 
264
- const entityViewWidth = getEntityViewWidth(props, smallLayout);
278
+ const entityViewWidth = getEntityViewWidth(props, smallLayout, customizationController);
265
279
 
266
280
  return {
267
281
  key: `${props.path}/${props.entityId}`,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  ArrayProperty,
3
3
  CMSType,
4
+ CustomizationController,
4
5
  EntityCollection,
5
6
  EntityCustomView,
6
7
  EntityValues,
@@ -218,11 +219,11 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
218
219
  }
219
220
 
220
221
  export function getArrayResolvedProperties<M>({
221
- propertyKey,
222
- propertyValue,
223
- property,
224
- ...props
225
- }: {
222
+ propertyKey,
223
+ propertyValue,
224
+ property,
225
+ ...props
226
+ }: {
226
227
  propertyValue: any,
227
228
  propertyKey?: string,
228
229
  property: ArrayProperty<any> | ResolvedArrayProperty<any>,
@@ -430,3 +431,23 @@ export function resolveEntityView(entityView: string | EntityCustomView<any>, co
430
431
  return entityView;
431
432
  }
432
433
  }
434
+
435
+ export function resolvedSelectedEntityView<M extends Record<string, any>>(
436
+ customViews: (string | EntityCustomView<M>)[] | undefined,
437
+ customizationController: CustomizationController,
438
+ selectedTab?: string
439
+ ) {
440
+ const resolvedEntityViews = customViews ? customViews
441
+ .map(e => resolveEntityView(e, customizationController.entityViews))
442
+ .filter(Boolean) as EntityCustomView[]
443
+ : [];
444
+
445
+ const selectedEntityView = resolvedEntityViews.find(e => e.key === selectedTab);
446
+ const selectedSecondaryForm = customViews
447
+ && resolvedEntityViews.filter(e => e.includeActions).find(e => e.key === selectedTab);
448
+ return {
449
+ resolvedEntityViews,
450
+ selectedEntityView,
451
+ selectedSecondaryForm
452
+ };
453
+ }