@firecms/core 3.0.0-canary.7 → 3.0.0-canary.70

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 (271) hide show
  1. package/README.md +2 -2
  2. package/dist/app/AppBar.d.ts +12 -0
  3. package/dist/app/Drawer.d.ts +17 -0
  4. package/dist/app/Scaffold.d.ts +30 -0
  5. package/dist/app/index.d.ts +4 -0
  6. package/dist/app/useApp.d.ts +16 -0
  7. package/dist/components/ClearFilterSortButton.d.ts +5 -0
  8. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +11 -11
  9. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  10. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +5 -3
  11. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +3 -2
  12. package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
  13. package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +2 -0
  14. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
  15. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
  16. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
  17. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +12 -3
  18. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  19. package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
  20. package/dist/components/EntityPreview.d.ts +26 -7
  21. package/dist/components/EntityView.d.ts +11 -0
  22. package/dist/components/FieldCaption.d.ts +5 -0
  23. package/dist/components/HomePage/NavigationCard.d.ts +8 -0
  24. package/dist/components/HomePage/{NavigationCollectionCard.d.ts → NavigationCardBinding.d.ts} +2 -2
  25. package/dist/components/HomePage/SmallNavigationCard.d.ts +6 -0
  26. package/dist/components/HomePage/index.d.ts +3 -1
  27. package/dist/components/ReferenceWidget.d.ts +3 -1
  28. package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
  29. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
  30. package/dist/components/VirtualTable/VirtualTableProps.d.ts +6 -7
  31. package/dist/components/VirtualTable/types.d.ts +3 -3
  32. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -1
  33. package/dist/components/common/index.d.ts +1 -0
  34. package/dist/components/common/table_height.d.ts +5 -0
  35. package/dist/components/common/types.d.ts +4 -6
  36. package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +3 -0
  37. package/dist/components/index.d.ts +6 -3
  38. package/dist/contexts/AuthControllerContext.d.ts +1 -1
  39. package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +5 -8
  40. package/dist/core/DefaultDrawer.d.ts +19 -0
  41. package/dist/core/DrawerNavigationItem.d.ts +9 -0
  42. package/dist/core/EntityEditView.d.ts +36 -0
  43. package/dist/core/NavigationRoutes.d.ts +2 -2
  44. package/dist/core/index.d.ts +3 -4
  45. package/dist/form/PropertiesForm.d.ts +8 -0
  46. package/dist/form/components/ErrorFocus.d.ts +1 -1
  47. package/dist/form/components/FieldHelperText.d.ts +3 -3
  48. package/dist/form/components/StorageItemPreview.d.ts +2 -3
  49. package/dist/form/components/StorageUploadProgress.d.ts +1 -1
  50. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  51. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  52. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -4
  53. package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
  54. package/dist/form/index.d.ts +0 -2
  55. package/dist/form/validation.d.ts +1 -1
  56. package/dist/hooks/data/delete.d.ts +2 -2
  57. package/dist/hooks/data/save.d.ts +2 -3
  58. package/dist/hooks/data/useDataSource.d.ts +2 -2
  59. package/dist/hooks/data/useEntityFetch.d.ts +3 -3
  60. package/dist/hooks/index.d.ts +2 -0
  61. package/dist/hooks/useBuildNavigationController.d.ts +6 -4
  62. package/dist/hooks/useProjectLog.d.ts +6 -2
  63. package/dist/hooks/useStorageSource.d.ts +2 -2
  64. package/dist/hooks/useValidateAuthenticator.d.ts +21 -0
  65. package/dist/index.d.ts +1 -0
  66. package/dist/index.es.js +10512 -9997
  67. package/dist/index.es.js.map +1 -1
  68. package/dist/index.umd.js +5 -5
  69. package/dist/index.umd.js.map +1 -1
  70. package/dist/internal/useBuildDataSource.d.ts +1 -16
  71. package/dist/preview/PropertyPreview.d.ts +1 -1
  72. package/dist/preview/PropertyPreviewProps.d.ts +1 -4
  73. package/dist/preview/components/BooleanPreview.d.ts +5 -1
  74. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  75. package/dist/preview/components/ReferencePreview.d.ts +3 -8
  76. package/dist/types/analytics.d.ts +1 -1
  77. package/dist/types/auth.d.ts +37 -1
  78. package/dist/types/collections.d.ts +44 -6
  79. package/dist/types/datasource.d.ts +21 -14
  80. package/dist/types/entities.d.ts +5 -1
  81. package/dist/types/entity_actions.d.ts +14 -0
  82. package/dist/types/entity_callbacks.d.ts +2 -2
  83. package/dist/types/entity_overrides.d.ts +6 -0
  84. package/dist/types/fields.d.ts +31 -30
  85. package/dist/types/index.d.ts +2 -1
  86. package/dist/types/navigation.d.ts +15 -14
  87. package/dist/types/permissions.d.ts +5 -1
  88. package/dist/types/plugins.d.ts +22 -22
  89. package/dist/types/properties.d.ts +13 -5
  90. package/dist/types/property_config.d.ts +2 -2
  91. package/dist/types/roles.d.ts +31 -0
  92. package/dist/types/storage.d.ts +11 -3
  93. package/dist/types/user.d.ts +5 -0
  94. package/dist/util/collections.d.ts +9 -1
  95. package/dist/util/entities.d.ts +1 -1
  96. package/dist/util/icon_synonyms.d.ts +1 -97
  97. package/dist/util/icons.d.ts +8 -2
  98. package/dist/util/navigation_utils.d.ts +2 -2
  99. package/dist/util/objects.d.ts +1 -1
  100. package/dist/util/permissions.d.ts +4 -4
  101. package/dist/util/references.d.ts +4 -2
  102. package/dist/util/resolutions.d.ts +14 -14
  103. package/dist/util/storage.d.ts +23 -2
  104. package/dist/util/useStorageUploadController.d.ts +1 -1
  105. package/dist/util/useTraceUpdate.d.ts +1 -0
  106. package/package.json +139 -119
  107. package/src/app/AppBar.tsx +18 -0
  108. package/src/app/Drawer.tsx +25 -0
  109. package/src/app/Scaffold.tsx +249 -0
  110. package/src/app/index.ts +4 -0
  111. package/src/app/useApp.tsx +32 -0
  112. package/src/components/ClearFilterSortButton.tsx +41 -0
  113. package/src/components/DeleteEntityDialog.tsx +4 -4
  114. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +4 -4
  115. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +276 -279
  116. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +9 -5
  117. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +48 -45
  118. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  119. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +18 -17
  120. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +5 -5
  121. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +29 -34
  122. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +16 -12
  123. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +4 -5
  124. package/src/components/EntityCollectionView/EntityCollectionView.tsx +73 -72
  125. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
  126. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  127. package/src/components/EntityCollectionView/useSelectionController.tsx +30 -0
  128. package/src/components/EntityPreview.tsx +209 -70
  129. package/src/components/EntityView.tsx +84 -0
  130. package/src/components/FieldCaption.tsx +14 -0
  131. package/src/components/HomePage/DefaultHomePage.tsx +15 -11
  132. package/src/components/HomePage/NavigationCard.tsx +69 -0
  133. package/src/components/HomePage/NavigationCardBinding.tsx +116 -0
  134. package/src/components/HomePage/SmallNavigationCard.tsx +45 -0
  135. package/src/components/HomePage/index.tsx +3 -1
  136. package/src/components/PropertyIdCopyTooltipContent.tsx +2 -3
  137. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +4 -4
  138. package/src/components/ReferenceWidget.tsx +22 -12
  139. package/src/components/SearchIconsView.tsx +5 -5
  140. package/src/components/SelectableTable/SelectableTable.tsx +5 -3
  141. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  142. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +23 -8
  143. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +38 -24
  144. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +35 -15
  145. package/src/components/VirtualTable/VirtualTable.tsx +38 -29
  146. package/src/components/VirtualTable/VirtualTableHeader.tsx +4 -4
  147. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  148. package/src/components/VirtualTable/VirtualTableProps.tsx +7 -7
  149. package/src/components/VirtualTable/VirtualTableRow.tsx +4 -5
  150. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
  151. package/src/components/VirtualTable/types.tsx +2 -3
  152. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +11 -7
  153. package/src/components/common/index.ts +1 -0
  154. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  155. package/src/components/common/types.tsx +4 -6
  156. package/src/components/common/useColumnsIds.tsx +10 -2
  157. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -1
  158. package/src/components/common/useTableSearchHelper.ts +39 -9
  159. package/src/components/index.tsx +6 -3
  160. package/src/contexts/AuthControllerContext.tsx +1 -1
  161. package/src/{components/FireCMSAppBar.tsx → core/DefaultAppBar.tsx} +51 -34
  162. package/src/core/DefaultDrawer.tsx +177 -0
  163. package/src/core/DrawerNavigationItem.tsx +62 -0
  164. package/src/core/EntityEditView.tsx +1101 -0
  165. package/src/core/EntitySidePanel.tsx +3 -4
  166. package/src/core/FireCMS.tsx +54 -43
  167. package/src/core/NavigationRoutes.tsx +14 -7
  168. package/src/core/field_configs.tsx +2 -3
  169. package/src/core/index.tsx +3 -4
  170. package/src/form/PropertiesForm.tsx +81 -0
  171. package/src/form/PropertyFieldBinding.tsx +29 -7
  172. package/src/form/components/FieldHelperText.tsx +3 -3
  173. package/src/form/components/StorageItemPreview.tsx +5 -7
  174. package/src/form/components/StorageUploadProgress.tsx +9 -8
  175. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +10 -12
  176. package/src/form/field_bindings/BlockFieldBinding.tsx +2 -2
  177. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
  178. package/src/form/field_bindings/KeyValueFieldBinding.tsx +19 -19
  179. package/src/form/field_bindings/MapFieldBinding.tsx +25 -17
  180. package/src/form/field_bindings/MarkdownFieldBinding.tsx +2 -2
  181. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -9
  182. package/src/form/field_bindings/ReferenceFieldBinding.tsx +16 -13
  183. package/src/form/field_bindings/SelectFieldBinding.tsx +3 -3
  184. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +14 -35
  185. package/src/form/field_bindings/TextFieldBinding.tsx +7 -5
  186. package/src/form/index.tsx +4 -4
  187. package/src/form/validation.ts +4 -21
  188. package/src/hooks/data/delete.ts +3 -3
  189. package/src/hooks/data/save.ts +4 -2
  190. package/src/hooks/data/useCollectionFetch.tsx +1 -1
  191. package/src/hooks/data/useDataSource.tsx +8 -3
  192. package/src/hooks/data/useEntityFetch.tsx +4 -4
  193. package/src/hooks/index.tsx +3 -0
  194. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
  195. package/src/hooks/useBuildModeController.tsx +11 -5
  196. package/src/hooks/useBuildNavigationController.tsx +200 -83
  197. package/src/hooks/useProjectLog.tsx +17 -7
  198. package/src/hooks/useReferenceDialog.tsx +2 -2
  199. package/src/hooks/useResolvedNavigationFrom.tsx +1 -1
  200. package/src/hooks/useStorageSource.tsx +7 -2
  201. package/src/hooks/useValidateAuthenticator.tsx +115 -0
  202. package/src/index.ts +1 -0
  203. package/src/internal/useBuildDataSource.ts +54 -47
  204. package/src/internal/useBuildSideEntityController.tsx +88 -21
  205. package/src/preview/PropertyPreview.tsx +5 -15
  206. package/src/preview/PropertyPreviewProps.tsx +1 -11
  207. package/src/preview/components/BooleanPreview.tsx +19 -4
  208. package/src/preview/components/EnumValuesChip.tsx +2 -2
  209. package/src/preview/components/ReferencePreview.tsx +72 -165
  210. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -1
  211. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +2 -1
  212. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -1
  213. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -1
  214. package/src/preview/property_previews/ArrayOneOfPreview.tsx +2 -3
  215. package/src/preview/property_previews/ArrayPropertyPreview.tsx +2 -3
  216. package/src/preview/property_previews/MapPropertyPreview.tsx +5 -5
  217. package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
  218. package/src/types/analytics.ts +1 -0
  219. package/src/types/auth.tsx +50 -1
  220. package/src/types/collections.ts +51 -6
  221. package/src/types/customization_controller.tsx +0 -1
  222. package/src/types/datasource.ts +24 -17
  223. package/src/types/entities.ts +9 -1
  224. package/src/types/entity_actions.tsx +17 -0
  225. package/src/types/entity_callbacks.ts +2 -2
  226. package/src/types/entity_overrides.tsx +7 -0
  227. package/src/types/fields.tsx +33 -33
  228. package/src/types/firecms.tsx +0 -1
  229. package/src/types/index.ts +2 -1
  230. package/src/types/navigation.ts +17 -17
  231. package/src/types/permissions.ts +6 -1
  232. package/src/types/plugins.tsx +28 -30
  233. package/src/types/properties.ts +19 -7
  234. package/src/types/property_config.tsx +2 -2
  235. package/src/types/roles.ts +41 -0
  236. package/src/types/side_entity_controller.tsx +1 -0
  237. package/src/types/storage.ts +12 -3
  238. package/src/types/user.ts +7 -0
  239. package/src/util/collections.ts +22 -0
  240. package/src/util/entities.ts +2 -1
  241. package/src/util/enums.ts +1 -1
  242. package/src/util/icon_list.ts +2 -2
  243. package/src/util/icon_synonyms.ts +3 -99
  244. package/src/util/icons.tsx +11 -3
  245. package/src/util/navigation_utils.ts +6 -6
  246. package/src/util/objects.ts +8 -21
  247. package/src/util/permissions.ts +12 -8
  248. package/src/util/references.ts +36 -5
  249. package/src/util/resolutions.ts +32 -31
  250. package/src/util/storage.ts +75 -21
  251. package/src/util/strings.ts +2 -2
  252. package/src/util/useStorageUploadController.tsx +21 -3
  253. package/src/util/useTraceUpdate.tsx +2 -1
  254. package/dist/components/VirtualTable/common.d.ts +0 -2
  255. package/dist/core/Drawer.d.ts +0 -23
  256. package/dist/core/EntityView.d.ts +0 -22
  257. package/dist/core/Scaffold.d.ts +0 -55
  258. package/dist/core/SideEntityView.d.ts +0 -7
  259. package/dist/form/EntityForm.d.ts +0 -77
  260. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  261. package/dist/internal/useLocaleConfig.d.ts +0 -1
  262. package/dist/types/appcheck.d.ts +0 -26
  263. package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
  264. package/src/core/Drawer.tsx +0 -164
  265. package/src/core/EntityView.tsx +0 -578
  266. package/src/core/Scaffold.tsx +0 -281
  267. package/src/core/SideEntityView.tsx +0 -38
  268. package/src/form/EntityForm.tsx +0 -720
  269. package/src/internal/useBuildCustomizationController.tsx +0 -5
  270. package/src/internal/useLocaleConfig.tsx +0 -18
  271. package/src/types/appcheck.ts +0 -29
@@ -1,84 +1,223 @@
1
- import React, { useMemo } from "react";
2
- import { PropertyPreview } from "../preview";
3
- import { Entity, EntityCollection, ResolvedEntityCollection, ResolvedProperties } from "../types";
4
- import { resolveCollection } from "../util";
5
- import { cn, defaultBorderMixin, IconButton, OpenInNewIcon } from "@firecms/ui";
6
- import { CustomizationController } from "../types/customization_controller";
7
- import { useCustomizationController } from "../hooks/useCustomizationController";
1
+ import * as React from "react";
2
+ import { useMemo } from "react";
3
+
4
+ import { Entity, EntityCollection, ResolvedProperty } from "../types";
5
+
6
+ import {
7
+ getEntityImagePreviewPropertyKey,
8
+ getEntityPreviewKeys,
9
+ getEntityTitlePropertyKey,
10
+ getValueInPath,
11
+ resolveCollection
12
+ } from "../util";
13
+ import { cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Skeleton, Tooltip, Typography } from "@firecms/ui";
14
+ import { PreviewSize, PropertyPreview, SkeletonPropertyComponent } from "../preview";
15
+ import { useCustomizationController, useNavigationController, useSideEntityController } from "../hooks";
16
+ import { useAnalyticsController } from "../hooks/useAnalyticsController";
17
+
18
+ export type EntityPreviewProps = {
19
+ size: PreviewSize,
20
+ actions?: React.ReactNode,
21
+ collection?: EntityCollection,
22
+ hover?: boolean;
23
+ previewProperties?: string[],
24
+ disabled: undefined | boolean,
25
+ entity: Entity<any>,
26
+ includeId?: boolean,
27
+ includeEntityLink?: boolean,
28
+ onClick?: (e: React.SyntheticEvent) => void;
29
+ };
8
30
 
9
31
  /**
10
- * @group Components
32
+ * This view is used to display a preview of an entity.
33
+ * It is used by default in reference fields and whenever a reference is displayed.
11
34
  */
12
- export interface EntityPreviewProps<M extends Record<string, any>> {
13
- entity: Entity<M>;
14
- collection: EntityCollection<M>;
15
- path: string;
16
- className?: string;
17
- }
35
+ export function EntityPreview({
36
+ actions,
37
+ disabled,
38
+ hover,
39
+ collection: collectionProp,
40
+ previewProperties,
41
+ onClick,
42
+ size,
43
+ includeId = true,
44
+ includeEntityLink = true,
45
+ entity
46
+ }: EntityPreviewProps) {
18
47
 
19
- export function EntityPreview<M extends Record<string, any>>(
20
- {
21
- entity,
22
- collection,
23
- path,
24
- className
25
- }: EntityPreviewProps<M>) {
48
+ const analyticsController = useAnalyticsController();
49
+ const sideEntityController = useSideEntityController();
50
+ const customizationController = useCustomizationController();
51
+
52
+ const navigationController = useNavigationController();
53
+
54
+ const collection = collectionProp ?? navigationController.getCollection(entity.path);
26
55
 
27
- const customizationController: CustomizationController = useCustomizationController();
28
- const resolvedCollection: ResolvedEntityCollection<M> = useMemo(() => resolveCollection<M>({
56
+ if (!collection) {
57
+ throw Error(`Couldn't find the corresponding collection view for the path: ${entity.path}`);
58
+ }
59
+
60
+ const resolvedCollection = React.useMemo(() => resolveCollection({
29
61
  collection,
30
- path,
31
- entityId: entity.id,
62
+ path: entity.path,
32
63
  values: entity.values,
33
64
  fields: customizationController.propertyConfigs
34
- }), [collection, path, entity]);
65
+ }), [collection]);
35
66
 
36
- const properties: ResolvedProperties = resolvedCollection.properties;
67
+ const listProperties = useMemo(() => getEntityPreviewKeys(resolvedCollection, customizationController.propertyConfigs, previewProperties, size === "small" || size === "medium" ? 3 : 1),
68
+ [previewProperties, resolvedCollection, size]);
37
69
 
38
- return (
39
- <div className={"w-full " + className}>
40
- <div className={"w-full mb-4"}>
41
- <div className={cn(defaultBorderMixin, "flex justify-between py-2 border-b last:border-b-0")}>
42
- <div className="flex items-center w-1/4">
43
- <span className="pl-2 text-sm text-gray-600">Id</span>
44
- </div>
45
- <div
46
- className="flex-grow p-2 ml-2 w-3/4 text-gray-900 dark:text-white min-h-[56px] flex items-center">
47
- <span className="flex-grow mr-2">{entity.id}</span>
48
- {customizationController?.entityLinkBuilder &&
49
- <a href={customizationController.entityLinkBuilder({ entity })}
50
- rel="noopener noreferrer"
51
- target="_blank">
52
- <IconButton>
53
- <OpenInNewIcon
54
- size={"small"}/>
55
- </IconButton>
56
- </a>}
70
+ const titleProperty = getEntityTitlePropertyKey(resolvedCollection, customizationController.propertyConfigs);
71
+ const imagePropertyKey = getEntityImagePreviewPropertyKey(resolvedCollection);
72
+ const imageProperty = imagePropertyKey ? resolvedCollection.properties[imagePropertyKey] : undefined;
73
+
74
+ const restProperties = listProperties.filter(p => p !== titleProperty && p !== imagePropertyKey);
75
+
76
+ return <EntityPreviewContainer onClick={disabled ? undefined : onClick}
77
+ hover={disabled ? undefined : hover}
78
+ size={size}>
79
+ {imageProperty && (
80
+ <div className={cls("w-10 h-10 mr-2 shrink-0 grow-0", size === "tiny" ? "my-0.5" : "m-2 self-start")}>
81
+ <PropertyPreview property={imageProperty}
82
+ propertyKey={imagePropertyKey as string}
83
+ size={"tiny"}
84
+ value={getValueInPath(entity.values, imagePropertyKey as string)}/>
85
+ </div>
86
+ )}
87
+
88
+ <div className={"flex flex-col flex-grow w-full m-1"}>
89
+
90
+ {size !== "tiny" && includeId && (
91
+ entity
92
+ ? <div className={`${
93
+ size !== "medium"
94
+ ? "block whitespace-nowrap overflow-hidden truncate"
95
+ : ""
96
+ }`}>
97
+ <Typography variant={"caption"}
98
+ color={"disabled"}
99
+ className={"font-mono"}>
100
+ {entity.id}
101
+ </Typography>
57
102
  </div>
103
+ : <Skeleton/>)}
104
+
105
+ {titleProperty && (
106
+ <div className={"my-0.5 text-sm font-medium"}>
107
+ {
108
+ entity
109
+ ? <PropertyPreview
110
+ propertyKey={titleProperty as string}
111
+ value={getValueInPath(entity.values, titleProperty)}
112
+ property={resolvedCollection.properties[titleProperty as string] as ResolvedProperty}
113
+ size={"medium"}/>
114
+ : <SkeletonPropertyComponent
115
+ property={resolvedCollection.properties[titleProperty as string] as ResolvedProperty}
116
+ size={"medium"}/>
117
+ }
58
118
  </div>
59
- {Object.entries(properties)
60
- .map(([key, property]) => {
61
- const value = (entity.values)[key];
62
- return (
63
- <div
64
- key={`reference_previews_${key}`}
65
- className={cn(defaultBorderMixin, "flex justify-between py-2 border-b last:border-b-0")}>
66
- <div className="flex items-center w-1/4">
67
- <span className="pl-2 text-sm text-gray-600">{property.name}</span>
68
- </div>
69
- <div
70
- className="flex-grow p-2 ml-2 w-3/4 text-gray-900 dark:text-white min-h-[56px] flex items-center">
71
- <PropertyPreview
72
- propertyKey={key}
73
- value={value}
74
- // entity={entity}
75
- property={property}
76
- size={"medium"}/>
77
- </div>
78
- </div>
79
- )
80
- })}
81
- </div>
119
+ )}
120
+
121
+ {restProperties && restProperties.map((key) => {
122
+ const childProperty = resolvedCollection.properties[key as string];
123
+ if (!childProperty) return null;
124
+
125
+ return (
126
+ <div key={"ref_prev_" + key}
127
+ className={restProperties.length > 1 ? "my-0.5" : "my-0"}>
128
+ {
129
+ entity
130
+ ? <PropertyPreview
131
+ propertyKey={key as string}
132
+ value={getValueInPath(entity.values, key)}
133
+ property={childProperty as ResolvedProperty}
134
+ size={"tiny"}/>
135
+ : <SkeletonPropertyComponent
136
+ property={childProperty as ResolvedProperty}
137
+ size={"tiny"}/>
138
+ }
139
+ </div>
140
+ );
141
+ })}
142
+
82
143
  </div>
83
- );
144
+
145
+ {entity && includeEntityLink &&
146
+ <Tooltip title={`See details for ${entity.id}`}
147
+ className={size !== "tiny" ? "self-start" : ""}>
148
+ <IconButton
149
+ color={"inherit"}
150
+ size={"small"}
151
+ onClick={(e) => {
152
+ e.stopPropagation();
153
+ analyticsController.onAnalyticsEvent?.("entity_click_from_reference", {
154
+ path: entity.path,
155
+ entityId: entity.id
156
+ });
157
+ sideEntityController.open({
158
+ entityId: entity.id,
159
+ path: entity.path,
160
+ collection,
161
+ updateUrl: true
162
+ });
163
+ }}>
164
+ <KeyboardTabIcon size={"small"}/>
165
+ </IconButton>
166
+ </Tooltip>}
167
+
168
+ {actions}
169
+
170
+ </EntityPreviewContainer>;
84
171
  }
172
+
173
+ export type EntityPreviewContainerProps = {
174
+ children: React.ReactNode;
175
+ hover?: boolean;
176
+ fullwidth?: boolean;
177
+ size: PreviewSize;
178
+ className?: string;
179
+ style?: React.CSSProperties;
180
+ onClick?: (e: React.SyntheticEvent) => void;
181
+ };
182
+
183
+ const EntityPreviewContainerInner = React.forwardRef<HTMLDivElement, EntityPreviewContainerProps>(({
184
+ children,
185
+ hover,
186
+ onClick,
187
+ size,
188
+ style,
189
+ className,
190
+ fullwidth = true,
191
+ ...props
192
+ }, ref) => {
193
+ return <div
194
+ ref={ref}
195
+ style={{
196
+ ...style,
197
+ // @ts-ignore
198
+ tabindex: 0
199
+ }}
200
+ className={cls(
201
+ "bg-white dark:bg-gray-900",
202
+ fullwidth ? "w-full" : "",
203
+ "items-center",
204
+ hover ? "hover:bg-slate-50 dark:hover:bg-gray-800 group-hover:bg-slate-50 dark:group-hover:bg-gray-800" : "",
205
+ size === "tiny" ? "p-1" : "p-2",
206
+ "flex border rounded-lg",
207
+ onClick ? "cursor-pointer" : "",
208
+ defaultBorderMixin,
209
+ className)}
210
+ onClick={(event) => {
211
+ if (onClick) {
212
+ event.preventDefault();
213
+ onClick(event);
214
+ }
215
+ }}
216
+ {...props}>
217
+ {children}
218
+ </div>;
219
+ });
220
+
221
+ EntityPreviewContainerInner.displayName = "EntityPreviewContainer";
222
+
223
+ export const EntityPreviewContainer = React.memo(EntityPreviewContainerInner) as React.FC<EntityPreviewContainerProps>;
@@ -0,0 +1,84 @@
1
+ import React, { useMemo } from "react";
2
+ import { PropertyPreview } from "../preview";
3
+ import { Entity, EntityCollection, ResolvedEntityCollection, ResolvedProperties } from "../types";
4
+ import { resolveCollection } from "../util";
5
+ import { cls, defaultBorderMixin, IconButton, OpenInNewIcon } from "@firecms/ui";
6
+ import { CustomizationController } from "../types/customization_controller";
7
+ import { useCustomizationController } from "../hooks/useCustomizationController";
8
+
9
+ /**
10
+ * @group Components
11
+ */
12
+ export interface EntityViewProps<M extends Record<string, any>> {
13
+ entity: Entity<M>;
14
+ collection: EntityCollection<M>;
15
+ path: string;
16
+ className?: string;
17
+ }
18
+
19
+ export function EntityView<M extends Record<string, any>>(
20
+ {
21
+ entity,
22
+ collection,
23
+ path,
24
+ className
25
+ }: EntityViewProps<M>) {
26
+
27
+ const customizationController: CustomizationController = useCustomizationController();
28
+ const resolvedCollection: ResolvedEntityCollection<M> = useMemo(() => resolveCollection<M>({
29
+ collection,
30
+ path,
31
+ entityId: entity.id,
32
+ values: entity.values,
33
+ fields: customizationController.propertyConfigs
34
+ }), [collection, path, entity, customizationController.propertyConfigs]);
35
+
36
+ const properties: ResolvedProperties = resolvedCollection.properties;
37
+
38
+ return (
39
+ <div className={"w-full " + className}>
40
+ <div className={"w-full mb-4"}>
41
+ <div className={cls(defaultBorderMixin, "flex justify-between py-2 border-b last:border-b-0")}>
42
+ <div className="flex items-center w-1/4">
43
+ <span className="pl-2 text-sm text-gray-600">Id</span>
44
+ </div>
45
+ <div
46
+ className="flex-grow p-2 ml-2 w-3/4 text-gray-900 dark:text-white min-h-[56px] flex items-center">
47
+ <span className="flex-grow mr-2">{entity.id}</span>
48
+ {customizationController?.entityLinkBuilder &&
49
+ <a href={customizationController.entityLinkBuilder({ entity })}
50
+ rel="noopener noreferrer"
51
+ target="_blank">
52
+ <IconButton>
53
+ <OpenInNewIcon
54
+ size={"small"}/>
55
+ </IconButton>
56
+ </a>}
57
+ </div>
58
+ </div>
59
+ {Object.entries(properties)
60
+ .map(([key, property]) => {
61
+ const value = entity.values?.[key];
62
+ return (
63
+ <div
64
+ key={`reference_previews_${key}`}
65
+ className={cls(defaultBorderMixin, "flex justify-between py-2 border-b last:border-b-0")}>
66
+ <div className="flex items-center w-1/4">
67
+ <span className="pl-2 text-sm text-gray-600">{property.name}</span>
68
+ </div>
69
+ <div
70
+ className="flex-grow p-2 ml-2 w-3/4 text-gray-900 dark:text-white min-h-[56px] flex items-center">
71
+ <PropertyPreview
72
+ propertyKey={key}
73
+ value={value}
74
+ // entity={entity}
75
+ property={property}
76
+ size={"medium"}/>
77
+ </div>
78
+ </div>
79
+ )
80
+ })}
81
+ </div>
82
+ </div>
83
+ );
84
+ }
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+ import { Typography } from "@firecms/ui";
3
+
4
+ export function FieldCaption({
5
+ error,
6
+ children
7
+ }: { error?: boolean, children?: React.ReactNode }) {
8
+ if (!children) return null;
9
+ return (
10
+ <Typography variant={"caption"} color={error ? "error" : "secondary"} className={"ml-3.5 mt-0.5"}>
11
+ {children}
12
+ </Typography>
13
+ );
14
+ }
@@ -1,11 +1,11 @@
1
1
  import React, { useCallback, useEffect, useState } from "react";
2
2
 
3
3
  import { useCustomizationController, useFireCMSContext, useNavigationController } from "../../hooks";
4
- import { PluginGenericProps, PluginHomePageAdditionalCardsProps } from "../../types";
4
+ import { CMSAnalyticsEvent, PluginGenericProps, PluginHomePageAdditionalCardsProps } from "../../types";
5
5
 
6
6
  import { toArray } from "../../util/arrays";
7
7
  import { NavigationGroup } from "./NavigationGroup";
8
- import { NavigationCollectionCard } from "./NavigationCollectionCard";
8
+ import { NavigationCardBinding } from "./NavigationCardBinding";
9
9
 
10
10
  // @ts-ignore
11
11
  import * as JsSearch from "js-search";
@@ -102,7 +102,7 @@ export function DefaultHomePage({
102
102
  return (
103
103
  <NavigationGroup
104
104
  group={section.title}
105
- key={`plugin_section_${plugin.name}`}>
105
+ key={`plugin_section_${plugin.key}`}>
106
106
  {section.children}
107
107
  </NavigationGroup>
108
108
  );
@@ -173,21 +173,25 @@ export function DefaultHomePage({
173
173
  <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
174
174
  {thisGroupCollections.map((entry) => (
175
175
  <div key={`nav_${entry.group}_${entry.name}`} className="col-span-1">
176
- <NavigationCollectionCard
176
+ <NavigationCardBinding
177
177
  {...entry}
178
178
  onClick={() => {
179
- const event =
180
- entry.type === "collection"
181
- ? "home_navigate_to_collection"
182
- : entry.type === "view"
183
- ? "home_navigate_to_view"
184
- : "unmapped_event";
179
+ let event: CMSAnalyticsEvent;
180
+ if (entry.type === "collection") {
181
+ event = "home_navigate_to_collection";
182
+ } else if (entry.type === "view") {
183
+ event = "home_navigate_to_view";
184
+ } else if (entry.type === "admin") {
185
+ event = "home_navigate_to_admin_view";
186
+ } else {
187
+ event = "unmapped_event";
188
+ }
185
189
  context.analyticsController?.onAnalyticsEvent?.(event, { path: entry.path });
186
190
  }}
187
191
  />
188
192
  </div>
189
193
  ))}
190
- {AdditionalCards &&
194
+ {group?.toLowerCase() !== "admin" && AdditionalCards &&
191
195
  AdditionalCards.map((AdditionalCard, i) => (
192
196
  <div key={`nav_${group}_add_${i}`}>
193
197
  <AdditionalCard {...actionProps} />
@@ -0,0 +1,69 @@
1
+ import { ArrowForwardIcon, Card, cls, Markdown, Typography, } from "@firecms/ui";
2
+
3
+ export type NavigationCardProps = {
4
+ name: string,
5
+ description?: string;
6
+ actions: React.ReactNode;
7
+ icon: React.ReactNode;
8
+ onClick?: () => void,
9
+ };
10
+
11
+ export function NavigationCard({
12
+ name,
13
+ description,
14
+ icon,
15
+ actions,
16
+ onClick,
17
+ }: NavigationCardProps) {
18
+
19
+ return (<Card
20
+ className={cls("h-full p-4 cursor-pointer min-h-[230px]")}
21
+ onClick={() => {
22
+ onClick?.();
23
+ }}>
24
+
25
+ <div className="flex flex-col items-start h-full">
26
+ <div
27
+ className="flex-grow w-full">
28
+
29
+ <div
30
+ className="h-10 flex items-center w-full justify-between text-gray-300 dark:text-gray-600">
31
+
32
+ {icon}
33
+
34
+ <div
35
+ className="flex items-center gap-1"
36
+ onClick={(event: React.MouseEvent) => {
37
+ event.preventDefault();
38
+ event.stopPropagation();
39
+ }}>
40
+
41
+ {actions}
42
+
43
+ </div>
44
+
45
+ </div>
46
+
47
+ <Typography gutterBottom variant="h5"
48
+ component="h2">
49
+ {name}
50
+ </Typography>
51
+
52
+ {description && <Typography variant="body2"
53
+ color="secondary"
54
+ component="div">
55
+ <Markdown source={description} size={"small"}/>
56
+ </Typography>}
57
+ </div>
58
+
59
+ <div style={{ alignSelf: "flex-end" }}>
60
+
61
+ <div className={"p-4"}>
62
+ <ArrowForwardIcon className="text-primary"/>
63
+ </div>
64
+ </div>
65
+
66
+ </div>
67
+
68
+ </Card>)
69
+ }
@@ -0,0 +1,116 @@
1
+ import { useNavigate } from "react-router-dom";
2
+
3
+ import { useCustomizationController, useFireCMSContext } from "../../hooks";
4
+ import { PluginHomePageActionsProps, TopNavigationEntry } from "../../types";
5
+ import { IconForView } from "../../util";
6
+ import { useUserConfigurationPersistence } from "../../hooks/useUserConfigurationPersistence";
7
+ import { IconButton, StarBorderIcon, StarIcon } from "@firecms/ui";
8
+ import { NavigationCard } from "./NavigationCard";
9
+ import { SmallNavigationCard } from "./SmallNavigationCard";
10
+
11
+ /**
12
+ * This is the component used in the home page to render a card for each
13
+ * collection or view.
14
+ * @group Components
15
+ * @param view
16
+ * @param path
17
+ * @param collection
18
+ * @param url
19
+ * @param name
20
+ * @param description
21
+ * @param onClick
22
+ * @constructor
23
+ */
24
+ export function NavigationCardBinding({
25
+ path,
26
+ collection,
27
+ view,
28
+ url,
29
+ name,
30
+ description,
31
+ onClick,
32
+ type
33
+ }: TopNavigationEntry & {
34
+ onClick?: () => void
35
+ }) {
36
+
37
+ const userConfigurationPersistence = useUserConfigurationPersistence();
38
+ const collectionIcon = <IconForView collectionOrView={collection ?? view}/>;
39
+
40
+ const navigate = useNavigate();
41
+ const context = useFireCMSContext();
42
+ const customizationController = useCustomizationController();
43
+
44
+ const favourite = (userConfigurationPersistence?.favouritePaths ?? []).includes(path);
45
+
46
+ const actionsArray: React.ReactNode[] = userConfigurationPersistence
47
+ ? [
48
+ <IconButton
49
+ key={"favourite"}
50
+ onClick={(e) => {
51
+ e.preventDefault();
52
+ e.stopPropagation();
53
+ if (favourite) {
54
+ userConfigurationPersistence.setFavouritePaths(
55
+ userConfigurationPersistence.favouritePaths.filter(p => p !== path)
56
+ );
57
+ } else {
58
+ userConfigurationPersistence.setFavouritePaths(
59
+ [...userConfigurationPersistence.favouritePaths, path]
60
+ );
61
+ }
62
+ }}>
63
+ {
64
+ favourite
65
+ ? <StarIcon
66
+ size={18}
67
+ className={"text-secondary"}/>
68
+ : <StarBorderIcon
69
+ size={18}
70
+ className={"text-gray-400 dark:text-gray-500"}/>}
71
+ </IconButton>
72
+ ]
73
+ : [];
74
+
75
+ if (customizationController.plugins && collection) {
76
+ const actionProps: PluginHomePageActionsProps = {
77
+ path,
78
+ collection,
79
+ context
80
+ };
81
+ customizationController.plugins.forEach((plugin, i) => (
82
+ actionsArray.push(plugin.homePage?.CollectionActions
83
+ ? <plugin.homePage.CollectionActions
84
+ key={`actions_${i}`}
85
+ {...actionProps}
86
+ extraProps={plugin.homePage.extraProps}
87
+ />
88
+ : null
89
+ )))
90
+ }
91
+
92
+ const actions: React.ReactNode | undefined = <>
93
+ {actionsArray}
94
+ </>
95
+
96
+ if (type === "admin") {
97
+ return <SmallNavigationCard icon={collectionIcon}
98
+ name={name}
99
+ url={url}/>
100
+ }
101
+
102
+ return <NavigationCard
103
+ icon={collectionIcon}
104
+ name={name}
105
+ description={description}
106
+ actions={actions}
107
+ onClick={() => {
108
+ onClick?.();
109
+ navigate(url);
110
+ if (userConfigurationPersistence) {
111
+ userConfigurationPersistence.setRecentlyVisitedPaths(
112
+ [path, ...(userConfigurationPersistence.recentlyVisitedPaths ?? []).filter(p => p !== path)]
113
+ );
114
+ }
115
+ }}/>;
116
+ }