@firecms/core 3.0.0-beta.2 → 3.0.0-beta.4.pre.1

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.
Files changed (157) hide show
  1. package/README.md +1 -1
  2. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +3 -7
  3. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  4. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +2 -2
  5. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +1 -2
  6. package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
  7. package/dist/components/EntityPreview.d.ts +25 -7
  8. package/dist/components/EntityView.d.ts +11 -0
  9. package/dist/components/FieldCaption.d.ts +4 -0
  10. package/dist/components/HomePage/NavigationCard.d.ts +8 -0
  11. package/dist/components/HomePage/{NavigationCollectionCard.d.ts → NavigationCardBinding.d.ts} +2 -2
  12. package/dist/components/HomePage/SmallNavigationCard.d.ts +6 -0
  13. package/dist/components/HomePage/index.d.ts +3 -1
  14. package/dist/components/ReferenceWidget.d.ts +3 -3
  15. package/dist/components/VirtualTable/VirtualTableProps.d.ts +1 -1
  16. package/dist/components/index.d.ts +4 -3
  17. package/dist/{internal/EntityView.d.ts → core/EntityEditView.d.ts} +2 -2
  18. package/dist/core/SideEntityView.d.ts +7 -0
  19. package/dist/core/index.d.ts +0 -2
  20. package/dist/form/EntityForm.d.ts +1 -1
  21. package/dist/form/components/StorageItemPreview.d.ts +3 -2
  22. package/dist/form/components/StorageUploadProgress.d.ts +1 -1
  23. package/dist/form/components/index.d.ts +1 -0
  24. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  25. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  26. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +4 -3
  27. package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
  28. package/dist/form/index.d.ts +1 -0
  29. package/dist/form/validation.d.ts +1 -1
  30. package/dist/hooks/data/useDataSource.d.ts +2 -2
  31. package/dist/hooks/index.d.ts +2 -1
  32. package/dist/{core → hooks}/useBuildModeController.d.ts +1 -1
  33. package/dist/hooks/useBuildNavigationController.d.ts +5 -2
  34. package/dist/hooks/useProjectLog.d.ts +5 -1
  35. package/dist/hooks/useStorageSource.d.ts +2 -2
  36. package/dist/index.es.js +8444 -8152
  37. package/dist/index.es.js.map +1 -1
  38. package/dist/index.umd.js +5 -5
  39. package/dist/index.umd.js.map +1 -1
  40. package/dist/internal/useBuildDataSource.d.ts +4 -0
  41. package/dist/internal/useRestoreScroll.d.ts +1 -1
  42. package/dist/preview/PropertyPreview.d.ts +1 -1
  43. package/dist/preview/components/BooleanPreview.d.ts +5 -1
  44. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  45. package/dist/preview/components/ReferencePreview.d.ts +1 -7
  46. package/dist/types/analytics.d.ts +1 -1
  47. package/dist/types/auth.d.ts +8 -1
  48. package/dist/types/collections.d.ts +14 -1
  49. package/dist/types/entities.d.ts +1 -0
  50. package/dist/types/entity_overrides.d.ts +6 -0
  51. package/dist/types/index.d.ts +1 -0
  52. package/dist/types/navigation.d.ts +10 -9
  53. package/dist/types/permissions.d.ts +5 -1
  54. package/dist/types/plugins.d.ts +15 -17
  55. package/dist/types/properties.d.ts +2 -2
  56. package/dist/types/property_config.d.ts +2 -2
  57. package/dist/util/collections.d.ts +9 -1
  58. package/dist/util/icons.d.ts +8 -2
  59. package/dist/util/index.d.ts +1 -0
  60. package/dist/util/permissions.d.ts +4 -4
  61. package/dist/util/references.d.ts +4 -2
  62. package/dist/util/resolutions.d.ts +1 -1
  63. package/package.json +31 -23
  64. package/src/components/DeleteEntityDialog.tsx +4 -4
  65. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +35 -39
  66. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +276 -282
  67. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
  68. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +13 -13
  69. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +9 -16
  70. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +3 -3
  71. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +1 -1
  72. package/src/components/EntityCollectionTable/internal/default_entity_actions.tsx +9 -5
  73. package/src/components/EntityCollectionView/EntityCollectionView.tsx +37 -58
  74. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
  75. package/src/components/EntityCollectionView/useSelectionController.tsx +30 -0
  76. package/src/components/EntityPreview.tsx +204 -70
  77. package/src/components/EntityView.tsx +84 -0
  78. package/src/components/FieldCaption.tsx +13 -0
  79. package/src/components/FireCMSAppBar.tsx +8 -0
  80. package/src/components/HomePage/DefaultHomePage.tsx +13 -9
  81. package/src/components/HomePage/NavigationCard.tsx +69 -0
  82. package/src/components/HomePage/NavigationCardBinding.tsx +116 -0
  83. package/src/components/HomePage/SmallNavigationCard.tsx +45 -0
  84. package/src/components/HomePage/index.tsx +3 -1
  85. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +3 -4
  86. package/src/components/ReferenceWidget.tsx +7 -7
  87. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +11 -19
  88. package/src/components/VirtualTable/VirtualTableProps.tsx +1 -1
  89. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +1 -1
  90. package/src/components/index.tsx +4 -3
  91. package/src/core/Drawer.tsx +66 -39
  92. package/src/{internal/EntityView.tsx → core/EntityEditView.tsx} +22 -39
  93. package/src/core/EntitySidePanel.tsx +2 -2
  94. package/src/core/FireCMS.tsx +18 -2
  95. package/src/core/NavigationRoutes.tsx +8 -0
  96. package/src/core/SideEntityView.tsx +38 -0
  97. package/src/core/index.tsx +0 -2
  98. package/src/form/EntityForm.tsx +19 -11
  99. package/src/form/components/StorageItemPreview.tsx +5 -3
  100. package/src/form/components/StorageUploadProgress.tsx +6 -5
  101. package/src/form/components/index.tsx +1 -0
  102. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +2 -3
  103. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +12 -15
  104. package/src/form/field_bindings/BlockFieldBinding.tsx +2 -3
  105. package/src/form/field_bindings/DateTimeFieldBinding.tsx +3 -3
  106. package/src/form/field_bindings/KeyValueFieldBinding.tsx +18 -18
  107. package/src/form/field_bindings/MapFieldBinding.tsx +17 -17
  108. package/src/form/field_bindings/MarkdownFieldBinding.tsx +1 -2
  109. package/src/form/field_bindings/MultiSelectBinding.tsx +2 -3
  110. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +3 -3
  111. package/src/form/field_bindings/ReferenceFieldBinding.tsx +6 -4
  112. package/src/form/field_bindings/RepeatFieldBinding.tsx +3 -3
  113. package/src/form/field_bindings/SelectFieldBinding.tsx +2 -3
  114. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +15 -6
  115. package/src/form/field_bindings/SwitchFieldBinding.tsx +2 -3
  116. package/src/form/field_bindings/TextFieldBinding.tsx +10 -9
  117. package/src/form/index.tsx +1 -0
  118. package/src/form/validation.ts +3 -4
  119. package/src/hooks/data/useCollectionFetch.tsx +1 -1
  120. package/src/hooks/data/useDataSource.tsx +8 -3
  121. package/src/hooks/data/useEntityFetch.tsx +1 -1
  122. package/src/hooks/index.tsx +3 -1
  123. package/src/{core → hooks}/useBuildModeController.tsx +1 -1
  124. package/src/hooks/useBuildNavigationController.tsx +105 -49
  125. package/src/hooks/useProjectLog.tsx +11 -3
  126. package/src/hooks/useReferenceDialog.tsx +2 -2
  127. package/src/hooks/useStorageSource.tsx +7 -2
  128. package/src/internal/useBuildDataSource.ts +7 -2
  129. package/src/preview/PropertyPreview.tsx +2 -2
  130. package/src/preview/components/BooleanPreview.tsx +16 -3
  131. package/src/preview/components/EnumValuesChip.tsx +1 -1
  132. package/src/preview/components/ReferencePreview.tsx +55 -147
  133. package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
  134. package/src/types/analytics.ts +1 -0
  135. package/src/types/auth.tsx +11 -1
  136. package/src/types/collections.ts +16 -1
  137. package/src/types/entities.ts +4 -0
  138. package/src/types/entity_actions.tsx +4 -0
  139. package/src/types/entity_overrides.tsx +7 -0
  140. package/src/types/firecms.tsx +0 -1
  141. package/src/types/index.ts +1 -0
  142. package/src/types/navigation.ts +11 -10
  143. package/src/types/permissions.ts +6 -1
  144. package/src/types/plugins.tsx +22 -25
  145. package/src/types/properties.ts +1 -1
  146. package/src/types/property_config.tsx +2 -2
  147. package/src/types/side_entity_controller.tsx +1 -0
  148. package/src/util/collections.ts +22 -0
  149. package/src/util/icons.tsx +11 -3
  150. package/src/util/index.ts +1 -0
  151. package/src/util/permissions.ts +11 -8
  152. package/src/util/references.ts +36 -5
  153. package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
  154. /package/dist/{components → form/components}/LabelWithIcon.d.ts +0 -0
  155. /package/dist/{core → hooks}/useBuildLocalConfigurationPersistence.d.ts +0 -0
  156. /package/src/{components → form/components}/LabelWithIcon.tsx +0 -0
  157. /package/src/{core → hooks}/useBuildLocalConfigurationPersistence.tsx +0 -0
@@ -330,6 +330,10 @@ export function useBuildDataSource({
330
330
  * bindings.
331
331
  * Also, Firestore references are replaced with {@link EntityReference}
332
332
  * @param data
333
+ * @param buildReference
334
+ * @param buildGeoPoint
335
+ * @param buildDate
336
+ * @param buildDelete
333
337
  * @group Firestore
334
338
  */
335
339
  export function cmsToDelegateModel(data: any,
@@ -340,9 +344,11 @@ export function cmsToDelegateModel(data: any,
340
344
  ): any {
341
345
  if (data === undefined) {
342
346
  return buildDelete();
347
+ } else if (data === null) {
348
+ return null;
343
349
  } else if (Array.isArray(data)) {
344
350
  return data.map(v => cmsToDelegateModel(v, buildReference, buildGeoPoint, buildDate, buildDelete));
345
- } else if (data instanceof EntityReference) {
351
+ } else if (data.isEntityReference && data.isEntityReference()) {
346
352
  return buildReference(data);
347
353
  } else if (data instanceof GeoPoint) {
348
354
  return buildGeoPoint(data);
@@ -355,4 +361,3 @@ export function cmsToDelegateModel(data: any,
355
361
  }
356
362
  return data;
357
363
  }
358
-
@@ -178,7 +178,7 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
178
178
  }
179
179
  } else if (property.dataType === "reference") {
180
180
  if (typeof property.path === "string") {
181
- if (value instanceof EntityReference) {
181
+ if (typeof value === "object" && "isEntityReference" in value && value.isEntityReference()) {
182
182
  content = <ReferencePreview
183
183
  disabled={!property.path}
184
184
  previewProperties={property.previewProperties}
@@ -195,7 +195,7 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
195
195
 
196
196
  } else if (property.dataType === "boolean") {
197
197
  if (typeof value === "boolean") {
198
- content = <BooleanPreview value={value}/>;
198
+ content = <BooleanPreview value={value} size={size} property={property}/>;
199
199
  } else {
200
200
  content = buildWrongValueType(propertyKey, property.dataType, value);
201
201
  }
@@ -1,11 +1,24 @@
1
1
  import React from "react";
2
2
  import { Checkbox } from "@firecms/ui";
3
+ import { PreviewSize } from "../PropertyPreviewProps";
4
+ import { Property } from "../../types";
3
5
 
4
6
  /**
5
7
  * @group Preview components
6
8
  */
7
- export function BooleanPreview({ value }: {
8
- value: boolean
9
+ export function BooleanPreview({
10
+ value,
11
+ size,
12
+ property
13
+ }: {
14
+ value: boolean,
15
+ size: PreviewSize,
16
+ property: Property,
9
17
  }): React.ReactElement {
10
- return <Checkbox checked={value} color={"secondary"}/>;
18
+ return <div className={"flex flex-row gap-2 items-center"}>
19
+ <Checkbox checked={value}
20
+ size={size}
21
+ color={"secondary"}/>
22
+ {property.name && <span className={size === "tiny" ? "text-sm" : ""}>{property.name}</span>}
23
+ </div>;
11
24
  }
@@ -6,7 +6,7 @@ import { Chip } from "@firecms/ui";
6
6
  export interface EnumValuesChipProps {
7
7
  enumValues?: EnumValues;
8
8
  enumKey: string | number;
9
- size: "small" | "medium";
9
+ size: "tiny" | "small" | "medium";
10
10
  className?: string;
11
11
  children?: React.ReactNode;
12
12
  }
@@ -1,21 +1,17 @@
1
1
  import * as React from "react";
2
- import { useMemo } from "react";
3
2
 
4
- import { Entity, EntityCollection, EntityReference, ResolvedProperty } from "../../types";
5
-
6
- import { getReferencePreviewKeys, getValueInPath, resolveCollection } from "../../util";
3
+ import { Entity, EntityCollection, EntityReference } from "../../types";
7
4
  import {
8
5
  useCustomizationController,
9
6
  useEntityFetch,
10
7
  useNavigationController,
11
8
  useSideEntityController
12
9
  } from "../../hooks";
13
- import { PropertyPreview } from "../PropertyPreview";
14
10
  import { PreviewSize } from "../PropertyPreviewProps";
15
- import { SkeletonPropertyComponent } from "../property_previews/SkeletonPropertyComponent";
16
- import { cn, IconButton, KeyboardTabIcon, Skeleton, Tooltip, Typography } from "@firecms/ui";
11
+ import { IconButton, KeyboardTabIcon, Skeleton, Tooltip } from "@firecms/ui";
17
12
  import { ErrorView } from "../../components";
18
13
  import { useAnalyticsController } from "../../hooks/useAnalyticsController";
14
+ import { EntityPreview, EntityPreviewContainer } from "../../components/EntityPreview";
19
15
 
20
16
  export type ReferencePreviewProps = {
21
17
  disabled?: boolean;
@@ -23,7 +19,7 @@ export type ReferencePreviewProps = {
23
19
  size: PreviewSize;
24
20
  previewProperties?: string[];
25
21
  onClick?: (e: React.SyntheticEvent) => void;
26
- onHover?: boolean;
22
+ hover?: boolean;
27
23
  allowEntityNavigation?: boolean;
28
24
  };
29
25
 
@@ -32,14 +28,14 @@ export type ReferencePreviewProps = {
32
28
  */
33
29
  export const ReferencePreview = React.memo<ReferencePreviewProps>(function ReferencePreview(props: ReferencePreviewProps) {
34
30
  const reference = props.reference;
35
- if (!((reference as unknown) instanceof EntityReference)) {
31
+ if (!(typeof reference === "object" && "isEntityReference" in reference && reference.isEntityReference())) {
36
32
  console.warn("Reference preview received value of type", typeof reference);
37
- return <ReferencePreviewContainer
33
+ return <EntityPreviewContainer
38
34
  onClick={props.onClick}
39
35
  size={props.size}>
40
36
  <ErrorView error={"Unexpected value. Click to edit"}
41
37
  tooltip={JSON.stringify(reference)}/>
42
- </ReferencePreviewContainer>;
38
+ </EntityPreviewContainer>;
43
39
  }
44
40
  return <ReferencePreviewInternal {...props} />;
45
41
  }, areEqual) as React.FunctionComponent<ReferencePreviewProps>;
@@ -47,7 +43,7 @@ export const ReferencePreview = React.memo<ReferencePreviewProps>(function Refer
47
43
  function areEqual(prevProps: ReferencePreviewProps, nextProps: ReferencePreviewProps) {
48
44
  return prevProps.disabled === nextProps.disabled &&
49
45
  prevProps.size === nextProps.size &&
50
- prevProps.onHover === nextProps.onHover &&
46
+ prevProps.hover === nextProps.hover &&
51
47
  prevProps.reference?.id === nextProps.reference?.id &&
52
48
  prevProps.reference?.path === nextProps.reference?.path &&
53
49
  prevProps.allowEntityNavigation === nextProps.allowEntityNavigation
@@ -59,7 +55,7 @@ function ReferencePreviewInternal<M extends Record<string, any>>({
59
55
  reference,
60
56
  previewProperties,
61
57
  size,
62
- onHover,
58
+ hover,
63
59
  onClick,
64
60
  allowEntityNavigation = true
65
61
  }: ReferencePreviewProps) {
@@ -85,18 +81,22 @@ function ReferencePreviewInternal<M extends Record<string, any>>({
85
81
  disabled={disabled}
86
82
  allowEntityNavigation={allowEntityNavigation}
87
83
  onClick={onClick}
88
- onHover={onHover}/>
84
+ hover={hover}/>
89
85
  }
90
86
 
91
- function ReferencePreviewExisting<M extends Record<string, any> = any>({ reference, collection, previewProperties, size, disabled, allowEntityNavigation, onClick, onHover }: ReferencePreviewProps & {
87
+ function ReferencePreviewExisting<M extends Record<string, any> = any>({
88
+ reference,
89
+ collection,
90
+ previewProperties,
91
+ size,
92
+ disabled,
93
+ allowEntityNavigation,
94
+ onClick,
95
+ hover
96
+ }: ReferencePreviewProps & {
92
97
  collection: EntityCollection<M>
93
98
  }) {
94
99
 
95
- const customizationController = useCustomizationController();
96
-
97
- const analyticsController = useAnalyticsController();
98
- const sideEntityController = useSideEntityController();
99
-
100
100
  const {
101
101
  entity,
102
102
  dataLoading,
@@ -114,145 +114,53 @@ function ReferencePreviewExisting<M extends Record<string, any> = any>({ referen
114
114
 
115
115
  const usedEntity = entity ?? referencesCache.get(reference.pathWithId);
116
116
 
117
- const resolvedCollection = useMemo(() => resolveCollection({
118
- collection,
119
- path: reference.path,
120
- values: usedEntity?.values,
121
- fields: customizationController.propertyConfigs
122
- }), [collection]);
123
-
124
- const listProperties = useMemo(() => getReferencePreviewKeys(resolvedCollection, customizationController.propertyConfigs, previewProperties, size === "small" || size === "medium" ? 3 : 1),
125
- [previewProperties, resolvedCollection, size]);
126
-
127
117
  let body: React.ReactNode;
128
118
 
129
- if (!resolvedCollection) {
130
- return <ErrorView
131
- error={"Could not find collection with id " + resolvedCollection}/>
132
- }
133
-
134
119
  if (!reference) {
135
120
  body = <ErrorView error={"Reference not set"}/>;
136
121
  } else if (usedEntity && !usedEntity.values) {
137
122
  body = <ErrorView error={"Reference does not exist"}
138
123
  tooltip={reference.path}/>;
139
- } else {
140
- body = (
141
- <>
142
- <div
143
- className="flex flex-col flex-grow w-full max-w-[calc(100%-52px)] m-1">
144
-
145
- {size !== "tiny" && (
146
- reference
147
- ? <div className={`${
148
- size !== "medium"
149
- ? "block whitespace-nowrap overflow-hidden truncate"
150
- : ""
151
- }`}>
152
- <Typography variant={"caption"}
153
- className={"font-mono"}>
154
- {reference.id}
155
- </Typography>
156
- </div>
157
- : <Skeleton/>)}
158
-
159
- {listProperties && listProperties.map((key) => {
160
- const childProperty = resolvedCollection.properties[key as string];
161
- if (!childProperty) return null;
162
-
163
- return (
164
- <div key={"ref_prev_" + (key as string)}
165
- className={listProperties.length > 1 ? "my-0.5" : "my-0"}>
166
- {
167
- usedEntity
168
- ? <PropertyPreview
169
- propertyKey={key as string}
170
- value={getValueInPath(usedEntity.values, key)}
171
- property={childProperty as ResolvedProperty}
172
- // entity={usedEntity}
173
- size={"tiny"}/>
174
- : <SkeletonPropertyComponent
175
- property={childProperty as ResolvedProperty}
176
- size={"tiny"}/>
177
- }
178
- </div>
179
- );
180
- })}
181
-
182
- </div>
183
- <div className={`my-${size === "tiny" ? 2 : 4}`}>
184
- {!disabled && usedEntity && allowEntityNavigation &&
185
- <Tooltip title={`See details for ${usedEntity.id}`}>
186
- <IconButton
187
- color={"inherit"}
188
- size={"small"}
189
- onClick={(e) => {
190
- e.stopPropagation();
191
- analyticsController.onAnalyticsEvent?.("entity_click_from_reference", {
192
- path: usedEntity.path,
193
- entityId: usedEntity.id
194
- });
195
- sideEntityController.open({
196
- entityId: usedEntity.id,
197
- path: usedEntity.path,
198
- collection: resolvedCollection,
199
- updateUrl: true
200
- });
201
- }}>
202
- <KeyboardTabIcon size={"small"}/>
203
- </IconButton>
204
- </Tooltip>}
205
- </div>
206
- </>
124
+ }
125
+ if (body) {
126
+
127
+ return (
128
+ <EntityPreviewContainer onClick={disabled ? undefined : onClick}
129
+ hover={disabled ? undefined : hover}
130
+ size={size}>
131
+ {body}
132
+ </EntityPreviewContainer>
207
133
  );
208
134
  }
209
135
 
210
- return (
211
- <ReferencePreviewContainer onClick={disabled ? undefined : onClick}
212
- onHover={disabled ? undefined : onHover}
213
- size={size}>
214
- {body}
215
- </ReferencePreviewContainer>
216
- );
217
- }
218
-
219
- export function ReferencePreviewContainer({
220
- children,
221
- onHover,
222
- size,
223
- onClick
224
- }: {
225
- children: React.ReactNode;
226
- onHover?: boolean;
227
- size: PreviewSize;
228
- onClick?: (e: React.SyntheticEvent) => void;
229
- }) {
230
- return <Typography variant={"label"}
231
- className={cn("bg-opacity-70 bg-gray-100 dark:bg-gray-800 dark:bg-opacity-60",
232
- "w-full",
233
- "flex",
234
- "rounded-md",
235
- "overflow-hidden",
236
- onHover ? "hover:bg-opacity-90 dark:hover:bg-opacity-90" : "",
237
- size === "medium" ? "p-2" : "p-1",
238
- size === "tiny" ? "items-center" : "",
239
- "transition-colors duration-300 ease-in-out ",
240
- // onHover ? "shadow-outline" : "",
241
- onClick ? "cursor-pointer" : "")}
242
- style={{
243
- // @ts-ignore
244
- tabindex: 0
245
- }}
246
- onClick={(event) => {
247
- if (onClick) {
248
- event.preventDefault();
249
- onClick(event);
250
- }
251
- }}>
136
+ if (dataLoading && !usedEntity) {
137
+ return (
138
+ <EntityPreviewContainer onClick={disabled ? undefined : onClick}
139
+ hover={disabled ? undefined : hover}
140
+ size={size}>
141
+ <Skeleton/>
142
+ </EntityPreviewContainer>
143
+ );
144
+ }
252
145
 
253
- {children}
146
+ if (!usedEntity) {
147
+ return (
148
+ <EntityPreviewContainer onClick={disabled ? undefined : onClick}
149
+ hover={disabled ? undefined : hover}
150
+ size={size}>
151
+ <ErrorView error={"Entity not found"}/>
152
+ </EntityPreviewContainer>
153
+ );
154
+ }
155
+ return <EntityPreview size={size}
156
+ previewProperties={previewProperties}
157
+ disabled={disabled}
158
+ entity={usedEntity}
159
+ collection={collection}
160
+ onClick={onClick}
161
+ includeEntityNavigation={allowEntityNavigation}
162
+ hover={hover}/>;
254
163
 
255
- </Typography>
256
164
  }
257
165
 
258
166
  const referencesCache = new Map<string, Entity<any>>();
@@ -6,7 +6,7 @@ import { PreviewType } from "../../types";
6
6
  import { UrlComponentPreview } from "../components/UrlComponentPreview";
7
7
  import { PropertyPreviewProps } from "../PropertyPreviewProps";
8
8
  import { ErrorBoundary } from "../../components";
9
- import { Chip, getColorSchemeForSeed } from "@firecms/ui";
9
+ import { Chip, cn, getColorSchemeForSeed } from "@firecms/ui";
10
10
 
11
11
  /**
12
12
  * @group Preview components
@@ -24,14 +24,14 @@ export function StringPropertyPreview({
24
24
  return <EnumValuesChip
25
25
  enumKey={enumKey}
26
26
  enumValues={resolvedProperty.enumValues}
27
- size={size !== "medium" ? "small" : "medium"}/>;
27
+ size={size}/>;
28
28
  } else if (property.previewAsTag) {
29
29
  const colorScheme = getColorSchemeForSeed(propertyKey ?? "");
30
30
  return (
31
31
  <ErrorBoundary>
32
32
  <Chip
33
33
  colorScheme={colorScheme}
34
- size={size !== "medium" ? "small" : "medium"}>
34
+ size={size}>
35
35
  {value}
36
36
  </Chip>
37
37
  </ErrorBoundary>);
@@ -45,15 +45,16 @@ export function StringPropertyPreview({
45
45
  if (!value) return <></>;
46
46
  const lines = value.split("\n");
47
47
  return value && value.includes("\n")
48
- ? <div className={"overflow-x-scroll"}>
48
+ ? <div className={cn("overflow-x-scroll", size === "tiny" ? "text-sm" : "")}>
49
49
  {lines.map((str, index) =>
50
50
  <React.Fragment key={`string_preview_${index}`}>
51
51
  <span>{str}</span>
52
52
  {index !== lines.length - 1 && <br/>}
53
53
  </React.Fragment>)}
54
54
  </div>
55
- : <>
56
- {value}
57
- </>;
55
+ : (size === "tiny"
56
+ ? <span className={"text-sm"}>{value}</span>
57
+ : <>{value}</>
58
+ );
58
59
  }
59
60
  }
@@ -26,6 +26,7 @@ export type CMSAnalyticsEvent =
26
26
  | "home_navigate_to_collection"
27
27
  | "home_favorite_navigate_to_collection"
28
28
  | "home_navigate_to_view"
29
+ | "home_navigate_to_admin_view"
29
30
  | "home_favorite_navigate_to_view"
30
31
 
31
32
  | "collection_inline_editing"
@@ -6,7 +6,7 @@ import { User } from "./user";
6
6
  * to do it as the result of a hook.
7
7
  * @group Hooks and utilities
8
8
  */
9
- export type AuthController<UserType extends User = User> = {
9
+ export type AuthController<UserType extends User = User, ExtraData extends any = any> = {
10
10
 
11
11
  /**
12
12
  * The user currently logged in
@@ -21,6 +21,12 @@ export type AuthController<UserType extends User = User> = {
21
21
  */
22
22
  initialLoading?: boolean;
23
23
 
24
+ /**
25
+ * Loading flag. It is used to display a loading screen when the user is
26
+ * logging in or out.
27
+ */
28
+ authLoading: boolean;
29
+
24
30
  /**
25
31
  * Sign out
26
32
  */
@@ -46,4 +52,8 @@ export type AuthController<UserType extends User = User> = {
46
52
  */
47
53
  loginSkipped: boolean;
48
54
 
55
+ extra: ExtraData;
56
+
57
+ setExtra: (extra: ExtraData) => void;
58
+
49
59
  };
@@ -8,6 +8,7 @@ import { EnumValues, PropertiesOrBuilders } from "./properties";
8
8
  import { FormContext } from "./fields";
9
9
  import { EntityAction } from "./entity_actions";
10
10
  import { ExportConfig } from "./export_import";
11
+ import { EntityOverrides } from "./entity_overrides";
11
12
 
12
13
  /**
13
14
  * This interface represents a view that includes a collection of entities.
@@ -76,6 +77,13 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
76
77
  */
77
78
  properties: PropertiesOrBuilders<M>;
78
79
 
80
+ /**
81
+ * Title property of the entity. This is the property that will be used
82
+ * as the title in entity related views and references.
83
+ * If not specified, the first property simple text property will be used.
84
+ */
85
+ titleProperty?: keyof M,
86
+
79
87
  /**
80
88
  * Can this collection be edited by the end user.
81
89
  * Defaults to `true`.
@@ -276,6 +284,13 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
276
284
  *
277
285
  */
278
286
  exportable?: boolean | ExportConfig<UserType>;
287
+
288
+ /**
289
+ * User id of the owner of this collection. This is used only by plugins, or if you
290
+ * are writing custom code
291
+ */
292
+ ownerId?: string;
293
+ overrides?: EntityOverrides;
279
294
  }
280
295
 
281
296
  /**
@@ -346,7 +361,7 @@ export type SelectionController<M extends Record<string, any> = any> = {
346
361
 
347
362
  /**
348
363
  * Filter conditions in a `Query.where()` clause are specified using the
349
- * strings '<', '<=', '==', '>=', '>', 'array-contains', 'in', and 'array-contains-any'.
364
+ * strings `<`, `<=`, `==`, `>=`, `>`, `array-contains`, `in`, and `array-contains-any`.
350
365
  * @group Models
351
366
  */
352
367
  export type WhereFilterOp =
@@ -56,6 +56,10 @@ export class EntityReference<M extends Record<string, any> = any> {
56
56
  get pathWithId() {
57
57
  return `${this.path}/${this.id}`;
58
58
  }
59
+
60
+ isEntityReference() {
61
+ return true;
62
+ }
59
63
  }
60
64
 
61
65
  export class GeoPoint {
@@ -4,6 +4,7 @@ import { Entity } from "./entities";
4
4
  import { EntityCollection, SelectionController } from "./collections";
5
5
  import { User } from "./user";
6
6
  import { SideEntityController } from "./side_entity_controller";
7
+ import { EntityOverrides } from "./entity_overrides";
7
8
 
8
9
  export type EntityAction<M extends object = any, UserType extends User = User> = {
9
10
  name: string;
@@ -21,8 +22,11 @@ export type EntityAction<M extends object = any, UserType extends User = User> =
21
22
  * Show this action in the form, defaults to true
22
23
  */
23
24
  includeInForm?: boolean;
25
+
24
26
  }
25
27
 
28
+
29
+
26
30
  export type EntityActionClickProps<M extends object, UserType extends User = User> = {
27
31
  entity: Entity<M>;
28
32
  context: FireCMSContext<UserType>;
@@ -0,0 +1,7 @@
1
+ import { DataSource } from "./datasource";
2
+ import { StorageSource } from "./storage";
3
+
4
+ export type EntityOverrides = {
5
+ dataSource?: DataSource;
6
+ storageSource?: StorageSource;
7
+ };
@@ -67,7 +67,6 @@ export type FireCMSProps<UserType extends User, EC extends EntityCollection> = {
67
67
  loading: boolean;
68
68
  }) => React.ReactNode;
69
69
 
70
-
71
70
  /**
72
71
  * Record of custom form fields to be used in the CMS.
73
72
  * You can use the key to reference the custom field in
@@ -17,6 +17,7 @@ export * from "./side_entity_controller";
17
17
  export * from "./side_dialogs_controller";
18
18
  export * from "./firecms_context";
19
19
  export * from "./entity_callbacks";
20
+ export * from "./entity_overrides";
20
21
  export * from "./local_config_persistence";
21
22
  export * from "./plugins";
22
23
  export * from "./analytics";
@@ -1,3 +1,4 @@
1
+ import React from "react";
1
2
  import { EntityCollection } from "./collections";
2
3
  import { EntityReference } from "./entities";
3
4
 
@@ -22,6 +23,12 @@ export type NavigationController = {
22
23
  */
23
24
  views?: CMSView[];
24
25
 
26
+ /**
27
+ * Custom additional views created by the developer, added to the admin
28
+ * navigation
29
+ */
30
+ adminViews?: CMSView[];
31
+
25
32
  /**
26
33
  * Configuration for the views that should be displayed at the top
27
34
  * level of the navigation (e.g. in the home page or the navigation
@@ -116,13 +123,6 @@ export type NavigationController = {
116
123
  */
117
124
  resolveAliasesFrom: (pathWithAliases: string) => string;
118
125
 
119
- /**
120
- * Location used as the base for routes.
121
- * This is the location that will be used underneath, when the url changes while
122
- * opening a side dialog
123
- */
124
- baseLocation: string;
125
-
126
126
  /**
127
127
  * Call this method to recalculate the navigation
128
128
  */
@@ -192,6 +192,7 @@ export interface CMSView {
192
192
  /**
193
193
  * Optional field used to group top level navigation entries under a
194
194
  * navigation view.
195
+ * This prop is ignored for admin views.
195
196
  */
196
197
  group?: string;
197
198
 
@@ -201,11 +202,11 @@ export interface TopNavigationEntry {
201
202
  url: string;
202
203
  name: string;
203
204
  path: string;
204
- type: "collection" | "view";
205
+ type: "collection" | "view" | "admin";
205
206
  collection?: EntityCollection;
206
- view: CMSView;
207
+ view?: CMSView;
207
208
  description?: string;
208
- group?: string;
209
+ group: string;
209
210
  }
210
211
 
211
212
  export type TopNavigationResult = {
@@ -41,6 +41,11 @@ export interface PermissionsBuilderProps<EC extends EntityCollection = EntityCol
41
41
  */
42
42
  entity: Entity<M> | null;
43
43
 
44
+ /**
45
+ * Path of the collection e.g. 'products/12345/locales'
46
+ */
47
+ path: string;
48
+
44
49
  /**
45
50
  * Path segments of the collection e.g. ['products', 'locales']
46
51
  */
@@ -73,4 +78,4 @@ export type PermissionsBuilder<EC extends EntityCollection = EntityCollection, U
73
78
  user,
74
79
  collection,
75
80
  authController
76
- }: PermissionsBuilderProps<EC, UserType, M>) => Permissions);
81
+ }: PermissionsBuilderProps<EC, UserType, M>) => Permissions | undefined);