@firecms/core 3.0.0-canary.5 → 3.0.0-canary.50

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 (210) hide show
  1. package/README.md +2 -2
  2. package/dist/components/ClearFilterSortButton.d.ts +5 -0
  3. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +11 -11
  4. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  5. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +5 -3
  6. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +3 -2
  7. package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
  8. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
  9. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
  10. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +12 -3
  11. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  12. package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
  13. package/dist/components/EntityPreview.d.ts +25 -7
  14. package/dist/components/EntityView.d.ts +11 -0
  15. package/dist/components/FieldCaption.d.ts +5 -0
  16. package/dist/components/FireCMSAppBar.d.ts +3 -2
  17. package/dist/components/HomePage/NavigationCard.d.ts +8 -0
  18. package/dist/components/HomePage/{NavigationCollectionCard.d.ts → NavigationCardBinding.d.ts} +2 -2
  19. package/dist/components/HomePage/SmallNavigationCard.d.ts +6 -0
  20. package/dist/components/HomePage/index.d.ts +3 -1
  21. package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
  22. package/dist/components/VirtualTable/VirtualTableProps.d.ts +1 -1
  23. package/dist/components/common/types.d.ts +4 -6
  24. package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +3 -0
  25. package/dist/components/index.d.ts +4 -2
  26. package/dist/contexts/AuthControllerContext.d.ts +1 -1
  27. package/dist/core/{EntityView.d.ts → EntityEditView.d.ts} +2 -2
  28. package/dist/core/NavigationRoutes.d.ts +1 -1
  29. package/dist/core/Scaffold.d.ts +1 -1
  30. package/dist/form/EntityForm.d.ts +1 -1
  31. package/dist/form/components/ErrorFocus.d.ts +1 -1
  32. package/dist/form/components/StorageItemPreview.d.ts +3 -2
  33. package/dist/form/components/StorageUploadProgress.d.ts +1 -1
  34. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  35. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  36. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +4 -3
  37. package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
  38. package/dist/form/validation.d.ts +1 -1
  39. package/dist/hooks/data/delete.d.ts +2 -2
  40. package/dist/hooks/data/save.d.ts +2 -3
  41. package/dist/hooks/data/useDataSource.d.ts +2 -2
  42. package/dist/hooks/data/useEntityFetch.d.ts +3 -3
  43. package/dist/hooks/index.d.ts +1 -0
  44. package/dist/hooks/useBuildNavigationController.d.ts +6 -4
  45. package/dist/hooks/useProjectLog.d.ts +6 -2
  46. package/dist/hooks/useStorageSource.d.ts +2 -2
  47. package/dist/hooks/useValidateAuthenticator.d.ts +21 -0
  48. package/dist/index.es.js +10402 -9898
  49. package/dist/index.es.js.map +1 -1
  50. package/dist/index.umd.js +5 -5
  51. package/dist/index.umd.js.map +1 -1
  52. package/dist/internal/useBuildDataSource.d.ts +1 -12
  53. package/dist/preview/PropertyPreview.d.ts +1 -1
  54. package/dist/preview/PropertyPreviewProps.d.ts +1 -4
  55. package/dist/preview/components/BooleanPreview.d.ts +5 -1
  56. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  57. package/dist/preview/components/ReferencePreview.d.ts +1 -7
  58. package/dist/types/analytics.d.ts +1 -1
  59. package/dist/types/auth.d.ts +37 -1
  60. package/dist/types/collections.d.ts +29 -5
  61. package/dist/types/datasource.d.ts +3 -6
  62. package/dist/types/entities.d.ts +5 -1
  63. package/dist/types/entity_actions.d.ts +14 -0
  64. package/dist/types/entity_callbacks.d.ts +2 -2
  65. package/dist/types/entity_overrides.d.ts +6 -0
  66. package/dist/types/index.d.ts +2 -1
  67. package/dist/types/navigation.d.ts +14 -13
  68. package/dist/types/permissions.d.ts +5 -1
  69. package/dist/types/plugins.d.ts +20 -20
  70. package/dist/types/properties.d.ts +4 -4
  71. package/dist/types/property_config.d.ts +2 -2
  72. package/dist/types/roles.d.ts +31 -0
  73. package/dist/types/storage.d.ts +11 -3
  74. package/dist/types/user.d.ts +5 -0
  75. package/dist/util/collections.d.ts +9 -1
  76. package/dist/util/entities.d.ts +1 -1
  77. package/dist/util/icon_synonyms.d.ts +1 -4
  78. package/dist/util/icons.d.ts +8 -2
  79. package/dist/util/navigation_utils.d.ts +2 -2
  80. package/dist/util/permissions.d.ts +4 -4
  81. package/dist/util/references.d.ts +4 -2
  82. package/dist/util/resolutions.d.ts +9 -13
  83. package/dist/util/useTraceUpdate.d.ts +1 -0
  84. package/package.json +139 -119
  85. package/src/components/ClearFilterSortButton.tsx +41 -0
  86. package/src/components/DeleteEntityDialog.tsx +4 -4
  87. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +2 -2
  88. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +275 -278
  89. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +9 -5
  90. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +44 -44
  91. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  92. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +9 -16
  93. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +3 -3
  94. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +27 -32
  95. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +11 -6
  96. package/src/components/EntityCollectionTable/internal/default_entity_actions.tsx +9 -5
  97. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -4
  98. package/src/components/EntityCollectionView/EntityCollectionView.tsx +69 -64
  99. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
  100. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  101. package/src/components/EntityCollectionView/useSelectionController.tsx +30 -0
  102. package/src/components/EntityPreview.tsx +207 -70
  103. package/src/components/EntityView.tsx +84 -0
  104. package/src/components/FieldCaption.tsx +14 -0
  105. package/src/components/FireCMSAppBar.tsx +33 -11
  106. package/src/components/HomePage/DefaultHomePage.tsx +15 -11
  107. package/src/components/HomePage/NavigationCard.tsx +69 -0
  108. package/src/components/HomePage/NavigationCardBinding.tsx +116 -0
  109. package/src/components/HomePage/SmallNavigationCard.tsx +45 -0
  110. package/src/components/HomePage/index.tsx +3 -1
  111. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +4 -4
  112. package/src/components/ReferenceWidget.tsx +4 -4
  113. package/src/components/SearchIconsView.tsx +4 -4
  114. package/src/components/SelectableTable/SelectableTable.tsx +1 -1
  115. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  116. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +23 -8
  117. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +35 -24
  118. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +35 -15
  119. package/src/components/VirtualTable/VirtualTable.tsx +28 -20
  120. package/src/components/VirtualTable/VirtualTableProps.tsx +1 -1
  121. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
  122. package/src/components/common/types.tsx +4 -6
  123. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -1
  124. package/src/components/index.tsx +4 -2
  125. package/src/contexts/AuthControllerContext.tsx +1 -1
  126. package/src/core/Drawer.tsx +66 -39
  127. package/src/core/{EntityView.tsx → EntityEditView.tsx} +21 -40
  128. package/src/core/EntitySidePanel.tsx +2 -2
  129. package/src/core/FireCMS.tsx +18 -3
  130. package/src/core/NavigationRoutes.tsx +11 -4
  131. package/src/core/Scaffold.tsx +5 -4
  132. package/src/core/field_configs.tsx +1 -2
  133. package/src/form/EntityForm.tsx +40 -21
  134. package/src/form/PropertyFieldBinding.tsx +0 -2
  135. package/src/form/components/StorageItemPreview.tsx +5 -3
  136. package/src/form/components/StorageUploadProgress.tsx +7 -6
  137. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +8 -12
  138. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
  139. package/src/form/field_bindings/KeyValueFieldBinding.tsx +15 -15
  140. package/src/form/field_bindings/MapFieldBinding.tsx +15 -15
  141. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +1 -1
  142. package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -0
  143. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +14 -5
  144. package/src/form/field_bindings/TextFieldBinding.tsx +7 -5
  145. package/src/form/validation.ts +3 -4
  146. package/src/hooks/data/delete.ts +3 -3
  147. package/src/hooks/data/save.ts +2 -2
  148. package/src/hooks/data/useCollectionFetch.tsx +1 -1
  149. package/src/hooks/data/useDataSource.tsx +8 -3
  150. package/src/hooks/data/useEntityFetch.tsx +4 -4
  151. package/src/hooks/index.tsx +2 -0
  152. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +9 -10
  153. package/src/hooks/useBuildModeController.tsx +11 -5
  154. package/src/hooks/useBuildNavigationController.tsx +199 -81
  155. package/src/hooks/useProjectLog.tsx +17 -7
  156. package/src/hooks/useReferenceDialog.tsx +2 -2
  157. package/src/hooks/useStorageSource.tsx +7 -2
  158. package/src/hooks/useValidateAuthenticator.tsx +115 -0
  159. package/src/internal/useBuildDataSource.ts +42 -44
  160. package/src/internal/useBuildSideEntityController.tsx +86 -20
  161. package/src/preview/PropertyPreview.tsx +3 -14
  162. package/src/preview/PropertyPreviewProps.tsx +1 -11
  163. package/src/preview/components/BooleanPreview.tsx +19 -4
  164. package/src/preview/components/EnumValuesChip.tsx +1 -1
  165. package/src/preview/components/ReferencePreview.tsx +55 -147
  166. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -1
  167. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +0 -1
  168. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -1
  169. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -1
  170. package/src/preview/property_previews/ArrayOneOfPreview.tsx +0 -1
  171. package/src/preview/property_previews/ArrayPropertyPreview.tsx +0 -1
  172. package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
  173. package/src/types/analytics.ts +1 -0
  174. package/src/types/auth.tsx +50 -1
  175. package/src/types/collections.ts +33 -5
  176. package/src/types/datasource.ts +8 -5
  177. package/src/types/entities.ts +9 -1
  178. package/src/types/entity_actions.tsx +17 -0
  179. package/src/types/entity_callbacks.ts +2 -2
  180. package/src/types/entity_overrides.tsx +7 -0
  181. package/src/types/firecms.tsx +0 -1
  182. package/src/types/index.ts +2 -1
  183. package/src/types/navigation.ts +17 -16
  184. package/src/types/permissions.ts +6 -1
  185. package/src/types/plugins.tsx +26 -28
  186. package/src/types/properties.ts +8 -6
  187. package/src/types/property_config.tsx +2 -2
  188. package/src/types/roles.ts +41 -0
  189. package/src/types/side_entity_controller.tsx +1 -0
  190. package/src/types/storage.ts +12 -3
  191. package/src/types/user.ts +7 -0
  192. package/src/util/collections.ts +22 -0
  193. package/src/util/entities.ts +1 -1
  194. package/src/util/icon_list.ts +2 -2
  195. package/src/util/icon_synonyms.ts +1 -4
  196. package/src/util/icons.tsx +11 -3
  197. package/src/util/navigation_utils.ts +6 -6
  198. package/src/util/objects.ts +0 -14
  199. package/src/util/permissions.ts +11 -8
  200. package/src/util/references.ts +36 -5
  201. package/src/util/resolutions.ts +6 -24
  202. package/src/util/strings.ts +2 -2
  203. package/src/util/useTraceUpdate.tsx +2 -1
  204. package/dist/core/SideEntityView.d.ts +0 -7
  205. package/dist/internal/useLocaleConfig.d.ts +0 -1
  206. package/dist/types/appcheck.d.ts +0 -26
  207. package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
  208. package/src/core/SideEntityView.tsx +0 -38
  209. package/src/internal/useLocaleConfig.tsx +0 -18
  210. package/src/types/appcheck.ts +0 -29
@@ -252,7 +252,7 @@ export type VirtualTableFilterValues<Key extends string> = Partial<Record<Key, [
252
252
 
253
253
  /**
254
254
  * Filter conditions in a `Query.where()` clause are specified using the
255
- * strings '<', '<=', '==', '>=', '>', 'array-contains', 'in', 'not-in', and 'array-contains-any'.
255
+ * strings `<`, `<=`, `==`, `>=`, `>`, `array-contains`, `in`, and `array-contains-any`.
256
256
  * @see Table
257
257
  * @group Models
258
258
  */
@@ -25,7 +25,7 @@ export function VirtualTableDateField(props: {
25
25
  return (
26
26
  <DateTimeField
27
27
  value={internalValue ?? undefined}
28
- onChange={(dateValue) => updateValue(dateValue)}
28
+ onChange={(dateValue) => updateValue(dateValue ?? null)}
29
29
  size={"medium"}
30
30
  invisible={true}
31
31
  className={"w-full h-full"}
@@ -1,4 +1,4 @@
1
- import { CollectionSize, Entity, FireCMSContext, ResolvedProperty, SelectedCellProps } from "../../types";
1
+ import { CollectionSize, FireCMSContext, ResolvedProperty, SelectedCellProps } from "../../types";
2
2
 
3
3
  export type EntityCollectionTableController<M extends Record<string, any>> = {
4
4
 
@@ -31,14 +31,12 @@ export type EntityCollectionTableController<M extends Record<string, any>> = {
31
31
  * Props passed in a callback when the content of a cell in a table has been edited
32
32
  * @group Collection components
33
33
  */
34
- export interface OnCellValueChangeParams<T = any, M extends Record<string, any> = any> {
34
+ export interface OnCellValueChangeParams<T = any, D = any> {
35
35
  value: T,
36
36
  propertyKey: string,
37
- entity: Entity<M>,
37
+ data?: D,
38
38
  onValueUpdated: () => void
39
- setError: (e: Error) => void
40
- fullPath: string
41
- context: FireCMSContext
39
+ setError: (e: Error | undefined) => void
42
40
  }
43
41
 
44
42
  /**
@@ -12,6 +12,7 @@ import {
12
12
  User
13
13
  } from "../../types";
14
14
  import { useDebouncedData } from "./useDebouncedData";
15
+ import equal from "react-fast-compare"
15
16
 
16
17
  const DEFAULT_PAGE_SIZE = 50;
17
18
 
@@ -31,6 +32,10 @@ export type DataSourceEntityCollectionTableControllerProps<M extends Record<stri
31
32
  entitiesDisplayedFirst?: Entity<M>[];
32
33
 
33
34
  lastDeleteTimestamp?: number;
35
+
36
+ /**
37
+ * Force filter to be applied to the table.
38
+ */
34
39
  forceFilter?: FilterValues<string>;
35
40
  }
36
41
 
@@ -65,7 +70,7 @@ export function useDataSourceEntityCollectionTableController<M extends Record<st
65
70
 
66
71
  const [popupCell, setPopupCell] = React.useState<SelectedCellProps<M> | undefined>(undefined);
67
72
  const navigation = useNavigationController();
68
- const dataSource = useDataSource();
73
+ const dataSource = useDataSource(collection);
69
74
  const resolvedPath = useMemo(() => navigation.resolveAliasesFrom(fullPath), [fullPath, navigation.resolveAliasesFrom]);
70
75
 
71
76
  const forceFilter = forceFilterFromProps ?? forceFilterFromCollection;
@@ -83,6 +88,12 @@ export function useDataSourceEntityCollectionTableController<M extends Record<st
83
88
  return initialSort;
84
89
  }, [initialSort, forceFilter]);
85
90
 
91
+ useEffect(() => {
92
+ if (!equal(forceFilter, filterValues)) {
93
+ setFilterValues(forceFilter)
94
+ }
95
+ }, [forceFilter]);
96
+
86
97
  const [filterValues, setFilterValues] = React.useState<FilterValues<Extract<keyof M, string>> | undefined>(forceFilter ?? initialFilter ?? undefined);
87
98
  const [sortBy, setSortBy] = React.useState<[Extract<keyof M, string>, "asc" | "desc"] | undefined>(initialSortInternal);
88
99
 
@@ -1,8 +1,8 @@
1
1
  export type { ErrorViewProps } from "./ErrorView";
2
2
  export { ErrorView } from "./ErrorView";
3
3
 
4
- export type { EntityPreviewProps } from "./EntityPreview";
5
- export { EntityPreview } from "./EntityPreview";
4
+ export type { EntityViewProps } from "./EntityView";
5
+ export { EntityView } from "./EntityView";
6
6
 
7
7
  export type { ReferenceSelectionInnerProps } from "./ReferenceTable/ReferenceSelectionTable";
8
8
  export { ReferenceSelectionTable } from "./ReferenceTable/ReferenceSelectionTable";
@@ -15,6 +15,7 @@ export * from "./HomePage";
15
15
  export * from "./SelectableTable/SelectableTable";
16
16
  export * from "./EntityCollectionView/EntityCollectionView";
17
17
  export * from "./EntityCollectionView/EntityCollectionViewActions";
18
+ export * from "./EntityCollectionView/useSelectionController";
18
19
 
19
20
  export * from "./PropertyConfigBadge";
20
21
 
@@ -32,3 +33,4 @@ export * from "./FireCMSAppBar";
32
33
  export * from "./ArrayContainer";
33
34
  export * from "./ReferenceWidget";
34
35
  export * from "./SearchIconsView";
36
+ export * from "./FieldCaption";
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
2
  import { AuthController } from "../types";
3
3
 
4
- export const AuthControllerContext = React.createContext<AuthController>({} as AuthController);
4
+ export const AuthControllerContext = React.createContext<AuthController<any, any>>({} as AuthController<any, any>);
@@ -2,10 +2,10 @@ import React, { useCallback } from "react";
2
2
 
3
3
  import { useLargeLayout, useNavigationController } from "../hooks";
4
4
 
5
- import { NavLink } from "react-router-dom";
5
+ import { NavLink, useNavigate } from "react-router-dom";
6
6
  import { CMSAnalyticsEvent, TopNavigationEntry, TopNavigationResult } from "../types";
7
7
  import { IconForView } from "../util";
8
- import { cn, Tooltip, Typography } from "@firecms/ui";
8
+ import { cn, IconButton, Menu, MenuItem, MoreVertIcon, Tooltip, Typography } from "@firecms/ui";
9
9
  import { useAnalyticsController } from "../hooks/useAnalyticsController";
10
10
 
11
11
  /**
@@ -33,6 +33,9 @@ export function Drawer({
33
33
 
34
34
  const tooltipsOpen = hovered && !drawerOpen;
35
35
  const largeLayout = useLargeLayout();
36
+ const navigate = useNavigate();
37
+
38
+ const [adminMenuOpen, setAdminMenuOpen] = React.useState(false);
36
39
 
37
40
  if (!navigation.topLevelNavigation)
38
41
  throw Error("Navigation not ready in Drawer");
@@ -42,7 +45,8 @@ export function Drawer({
42
45
  groups
43
46
  }: TopNavigationResult = navigation.topLevelNavigation;
44
47
 
45
- const ungroupedNavigationViews = Object.values(navigationEntries).filter(e => !e.group);
48
+ const adminViews = navigationEntries.filter(e => e.type === "admin") ?? [];
49
+ const groupsWithoutAdmin = groups.filter(g => g !== "Admin");
46
50
 
47
51
  const buildGroupHeader = useCallback((group?: string) => {
48
52
  if (!drawerOpen) return <div className="h-12 w-full"/>;
@@ -67,41 +71,64 @@ export function Drawer({
67
71
  };
68
72
 
69
73
  return (
70
- <div className={"flex-grow overflow-scroll no-scrollbar"}>
71
-
72
- {groups.map((group) => (
73
- <React.Fragment
74
- key={`drawer_group_${group}`}>
75
- {buildGroupHeader(group)}
76
- {Object.values(navigationEntries)
77
- .filter(e => e.group === group)
78
- .map((view, index) =>
79
- <DrawerNavigationItem
80
- key={`navigation_${index}`}
81
- icon={<IconForView collectionOrView={view.collection ?? view.view}/>}
82
- tooltipsOpen={tooltipsOpen}
83
- drawerOpen={drawerOpen}
84
- onClick={() => onClick(view)}
85
- url={view.url}
86
- name={view.name}/>)}
87
- </React.Fragment>
88
- ))}
89
-
90
- {ungroupedNavigationViews.length > 0 && buildGroupHeader()}
91
-
92
- {ungroupedNavigationViews.map((view, index) => {
93
-
94
- return <DrawerNavigationItem
95
- key={`navigation_${index}`}
96
- icon={<IconForView collectionOrView={view.collection ?? view.view}/>}
97
- tooltipsOpen={tooltipsOpen}
98
- onClick={() => onClick(view)}
99
- drawerOpen={drawerOpen}
100
- url={view.url}
101
- name={view.name}/>;
102
- })}
103
-
104
- </div>
74
+ <>
75
+
76
+ <div className={"flex-grow overflow-scroll no-scrollbar"}>
77
+
78
+ {groupsWithoutAdmin.map((group) => (
79
+ <React.Fragment
80
+ key={`drawer_group_${group}`}>
81
+ {buildGroupHeader(group)}
82
+ {Object.values(navigationEntries)
83
+ .filter(e => e.group === group)
84
+ .map((view, index) =>
85
+ <DrawerNavigationItem
86
+ key={`navigation_${index}`}
87
+ icon={<IconForView collectionOrView={view.collection ?? view.view}/>}
88
+ tooltipsOpen={tooltipsOpen}
89
+ drawerOpen={drawerOpen}
90
+ onClick={() => onClick(view)}
91
+ url={view.url}
92
+ name={view.name}/>)}
93
+ </React.Fragment>
94
+ ))}
95
+
96
+ </div>
97
+
98
+ {adminViews.length > 0 && <Menu
99
+ open={adminMenuOpen}
100
+ onOpenChange={setAdminMenuOpen}
101
+ trigger={
102
+ <IconButton
103
+ shape={"square"}
104
+ className={"m-4 text-gray-900 dark:text-white w-fit"}>
105
+ <Tooltip title={"Admin"}
106
+ open={tooltipsOpen}
107
+ side={"right"} sideOffset={28}>
108
+ <MoreVertIcon/>
109
+ </Tooltip>
110
+ {drawerOpen && <div
111
+ className={cn(
112
+ drawerOpen ? "opacity-100" : "opacity-0 hidden",
113
+ "mx-4 font-inherit text-inherit"
114
+ )}>
115
+ ADMIN
116
+ </div>}
117
+ </IconButton>}
118
+ >
119
+ {adminViews.map((entry, index) =>
120
+ <MenuItem
121
+ onClick={(event) => {
122
+ event.preventDefault();
123
+ navigate(entry.path);
124
+ }}
125
+ key={`navigation_${index}`}>
126
+ {<IconForView collectionOrView={entry.view}/>}
127
+ {entry.name}
128
+ </MenuItem>)}
129
+
130
+ </Menu>}
131
+ </>
105
132
  );
106
133
  }
107
134
 
@@ -133,7 +160,7 @@ export function DrawerNavigationItem({
133
160
  transition: drawerOpen ? "width 150ms ease-in" : undefined
134
161
  }}
135
162
  className={({ isActive }: any) => cn("rounded-r-xl truncate",
136
- "hover:bg-slate-300 hover:bg-opacity-75 dark:hover:bg-gray-700 dark:hover:bg-opacity-75 text-gray-800 dark:text-gray-200 hover:text-gray-900 hover:dark:text-gray-100",
163
+ "hover:bg-slate-300 hover:bg-opacity-75 dark:hover:bg-gray-700 dark:hover:bg-opacity-75 text-gray-800 dark:text-gray-200 hover:text-gray-900 hover:dark:text-white",
137
164
  "flex flex-row items-center mr-8",
138
165
  // "transition-all ease-in-out delay-100 duration-300",
139
166
  // drawerOpen ? "w-full" : "w-18",
@@ -9,10 +9,9 @@ import {
9
9
  FormContext,
10
10
  User
11
11
  } from "../types";
12
- import { CircularProgressCenter, EntityCollectionView, EntityPreview, ErrorBoundary, } from "../components";
12
+ import { CircularProgressCenter, EntityCollectionView, EntityView, ErrorBoundary, } from "../components";
13
13
  import {
14
14
  canEditEntity,
15
- fullPathToCollectionSegments,
16
15
  removeInitialAndTrailingSlashes,
17
16
  resolveDefaultSelectedView,
18
17
  resolveEntityView,
@@ -32,12 +31,11 @@ import {
32
31
  import { EntityForm } from "../form";
33
32
  import { CircularProgress, CloseIcon, cn, defaultBorderMixin, IconButton, Tab, Tabs, Typography } from "@firecms/ui";
34
33
  import { EntityFormSaveParams } from "../form/EntityForm";
35
- import { FORM_CONTAINER_WIDTH } from "../internal/common";
36
34
  import { useSideDialogContext } from "./index";
37
35
 
38
36
  const MAIN_TAB_VALUE = "main_##Q$SC^#S6";
39
37
 
40
- export interface EntityViewProps<M extends Record<string, any>> {
38
+ export interface EntityEditViewProps<M extends Record<string, any>> {
41
39
  path: string;
42
40
  collection: EntityCollection<M>;
43
41
  entityId?: string;
@@ -56,18 +54,18 @@ export interface EntityViewProps<M extends Record<string, any>> {
56
54
  * You probably don't want to use this view directly since it is bound to the
57
55
  * side panel. Instead, you might want to use {@link EntityForm} or {@link EntityCollectionView}
58
56
  */
59
- export function EntityView<M extends Record<string, any>, UserType extends User>({
60
- path,
61
- entityId,
62
- selectedSubPath,
63
- copy,
64
- collection,
65
- parentCollectionIds,
66
- onValuesAreModified,
67
- formWidth,
68
- onUpdate,
69
- onClose
70
- }: EntityViewProps<M>) {
57
+ export function EntityEditView<M extends Record<string, any>, UserType extends User>({
58
+ path,
59
+ entityId,
60
+ selectedSubPath,
61
+ copy,
62
+ collection,
63
+ parentCollectionIds,
64
+ onValuesAreModified,
65
+ formWidth,
66
+ onUpdate,
67
+ onClose,
68
+ }: EntityEditViewProps<M>) {
71
69
 
72
70
  if (collection.customId && collection.formAutoSave) {
73
71
  console.warn(`The collection ${collection.path} has customId and formAutoSave enabled. This is not supported and formAutoSave will be ignored`);
@@ -92,10 +90,9 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
92
90
 
93
91
  // const largeLayout = useLargeLayout();
94
92
  // const largeLayoutTabSelected = useRef(!largeLayout);
93
+ // const resolvedFormWidth: string = typeof formWidth === "number" ? `${formWidth}px` : formWidth ?? FORM_CONTAINER_WIDTH;
95
94
 
96
- const resolvedFormWidth: string = typeof formWidth === "number" ? `${formWidth}px` : formWidth ?? FORM_CONTAINER_WIDTH;
97
-
98
- const dataSource = useDataSource();
95
+ const dataSource = useDataSource(collection);
99
96
  const sideDialogContext = useSideDialogContext();
100
97
  const sideEntityController = useSideEntityController();
101
98
  const snackbarController = useSnackbarController();
@@ -154,29 +151,12 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
154
151
  if (status === "new") {
155
152
  setReadOnly(false);
156
153
  } else {
157
- const editEnabled = usedEntity ? canEditEntity(collection, authController, fullPathToCollectionSegments(path), usedEntity ?? null) : false;
154
+ const editEnabled = usedEntity ? canEditEntity(collection, authController, path, usedEntity ?? null) : false;
158
155
  if (usedEntity)
159
156
  setReadOnly(!editEnabled);
160
157
  }
161
158
  }, [authController, usedEntity, status]);
162
159
 
163
- // useEffect(() => {
164
- // if (largeLayoutTabSelected.current === largeLayout)
165
- // return;
166
- // // open first tab by default in large layouts
167
- // if (selectedSubPath !== defaultSelectedView) {
168
- // console.log("Replacing url 1", defaultSelectedView);
169
- // sideEntityController.replace({
170
- // path,
171
- // entityId,
172
- // selectedSubPath: defaultSelectedView,
173
- // updateUrl: true,
174
- // collection
175
- // });
176
- // }
177
- // largeLayoutTabSelected.current = largeLayout;
178
- // }, [defaultSelectedView, largeLayout, selectedSubPath]);
179
-
180
160
  const onPreSaveHookError = useCallback((e: Error) => {
181
161
  setSaving(false);
182
162
  snackbarController.open({
@@ -222,7 +202,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
222
202
  entityId: updatedEntity.id,
223
203
  selectedSubPath: selectedTabRef.current,
224
204
  updateUrl: true,
225
- collection
205
+ collection,
226
206
  });
227
207
  }
228
208
 
@@ -302,6 +282,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
302
282
  .map(e => resolveEntityView(e, customizationController.entityViews))
303
283
  .filter(Boolean) as EntityCustomView[]
304
284
  : [];
285
+
305
286
  const customViewsView: React.ReactNode[] | undefined = customViews && resolvedEntityViews
306
287
  .map(
307
288
  (customView, colIndex) => {
@@ -382,7 +363,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
382
363
  entityId,
383
364
  selectedSubPath: value === MAIN_TAB_VALUE ? undefined : value,
384
365
  updateUrl: true,
385
- collection
366
+ collection,
386
367
  });
387
368
  };
388
369
 
@@ -463,7 +444,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
463
444
  className={"mt-16 mb-8 mx-8"}
464
445
  variant={"h4"}>{collection.singularName ?? collection.name}
465
446
  </Typography>
466
- <EntityPreview
447
+ <EntityView
467
448
  className={"px-12"}
468
449
  entity={usedEntity as Entity<M>}
469
450
  path={path}
@@ -4,7 +4,7 @@ import { EntitySidePanelProps } from "../types";
4
4
  import { useNavigationController } from "../hooks";
5
5
 
6
6
  import { ErrorBoundary } from "../components";
7
- import { EntityView } from "./EntityView";
7
+ import { EntityEditView } from "./EntityEditView";
8
8
  import { useSideDialogContext } from "./SideDialogs";
9
9
 
10
10
  /**
@@ -77,7 +77,7 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
77
77
  return (
78
78
  <>
79
79
  <ErrorBoundary>
80
- <EntityView
80
+ <EntityEditView
81
81
  {...props}
82
82
  formWidth={props.width}
83
83
  collection={collection}
@@ -12,8 +12,7 @@ import { DataSourceContext } from "../contexts/DataSourceContext";
12
12
  import { SideEntityControllerContext } from "../contexts/SideEntityControllerContext";
13
13
  import { NavigationContext } from "../contexts/NavigationContext";
14
14
  import { SideDialogsControllerContext } from "../contexts/SideDialogsControllerContext";
15
- import { useLocaleConfig } from "../internal/useLocaleConfig";
16
- import { CenteredView } from "@firecms/ui";
15
+ import { CenteredView, Typography, useLocaleConfig } from "@firecms/ui";
17
16
  import { DialogsProvider } from "../contexts/DialogsProvider";
18
17
  import { useBuildDataSource } from "../internal/useBuildDataSource";
19
18
  import { useBuildCustomizationController } from "../internal/useBuildCustomizationController";
@@ -85,7 +84,7 @@ export function FireCMS<UserType extends User, EC extends EntityCollection>(prop
85
84
  onAnalyticsEvent
86
85
  }), []);
87
86
 
88
- useProjectLog(authController);
87
+ const accessResponse = useProjectLog(authController, plugins);
89
88
 
90
89
  if (navigationController.navigationLoadingError) {
91
90
  return (
@@ -107,6 +106,22 @@ export function FireCMS<UserType extends User, EC extends EntityCollection>(prop
107
106
  );
108
107
  }
109
108
 
109
+ if (accessResponse?.blocked) {
110
+ return (
111
+ <CenteredView maxWidth={"md"} fullScreen={true}>
112
+ <Typography variant={"h4"}>
113
+ Access blocked
114
+ </Typography>
115
+ <Typography>
116
+ This app has been blocked. Please reach out at <a
117
+ href={"mailto:hello@firecms.co"}>hello@firecms.co</a> for more information.
118
+ </Typography>
119
+ {accessResponse?.message &&
120
+ <Typography>Response from the server: {accessResponse?.message}</Typography>}
121
+ </CenteredView>
122
+ );
123
+ }
124
+
110
125
  return (
111
126
  <ModeControllerContext.Provider value={modeController}>
112
127
  <AnalyticsContext.Provider value={analyticsController}>
@@ -13,7 +13,7 @@ export type NavigationRoutesProps = {
13
13
  /**
14
14
  * In case you need to override the home page
15
15
  */
16
- HomePage?: React.ComponentType;
16
+ homePage?: React.ReactNode;
17
17
 
18
18
  customRoutes?: React.ReactNode[]
19
19
 
@@ -28,10 +28,9 @@ export type NavigationRoutesProps = {
28
28
  * @constructor
29
29
  * @group Components
30
30
  */
31
-
32
31
  export const NavigationRoutes = React.memo<NavigationRoutesProps>(
33
32
  function NavigationRoutes({
34
- HomePage = DefaultHomePage,
33
+ homePage = <DefaultHomePage/>,
35
34
  customRoutes
36
35
  }: NavigationRoutesProps) {
37
36
 
@@ -59,6 +58,14 @@ export const NavigationRoutes = React.memo<NavigationRoutesProps>(
59
58
  cmsViews.push(buildCMSViewRoute(cmsView.path, cmsView));
60
59
  });
61
60
  }
61
+ if (navigation.adminViews) {
62
+ navigation.adminViews.forEach((cmsView) => {
63
+ if (Array.isArray(cmsView.path))
64
+ cmsViews.push(...cmsView.path.map(path => buildCMSViewRoute(path, cmsView)));
65
+ else
66
+ cmsViews.push(buildCMSViewRoute(cmsView.path, cmsView));
67
+ });
68
+ }
62
69
 
63
70
  // we reorder collections so that nested paths are included first
64
71
  const sortedCollections = [...(navigation.collections ?? [])]
@@ -85,7 +92,7 @@ export const NavigationRoutes = React.memo<NavigationRoutesProps>(
85
92
 
86
93
  const homeRoute = (
87
94
  <Route path={"/"}
88
- element={<HomePage/>}/>
95
+ element={homePage}/>
89
96
  );
90
97
 
91
98
  const notFoundRoute = <Route path={"*"}
@@ -17,7 +17,7 @@ export interface ScaffoldProps<ExtraDrawerProps = object, ExtraAppbarProps = obj
17
17
  /**
18
18
  * Name of the app, displayed as the main title and in the tab title
19
19
  */
20
- name: string;
20
+ name: React.ReactNode;
21
21
 
22
22
  /**
23
23
  * Logo to be displayed in the drawer of the CMS
@@ -112,9 +112,10 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
112
112
  }}>
113
113
 
114
114
  <FireCMSAppBar title={name}
115
- includeDrawer={includeDrawer}
116
- drawerOpen={computedDrawerOpen}
117
- {...fireCMSAppBarProps}/>
115
+ includeDrawer={includeDrawer}
116
+ logo={logo}
117
+ drawerOpen={computedDrawerOpen}
118
+ {...fireCMSAppBarProps}/>
118
119
 
119
120
  <StyledDrawer
120
121
  displayed={includeDrawer}
@@ -359,8 +359,7 @@ export function getDefaultFieldId(property: Property | ResolvedProperty) {
359
359
  } else if (property.dataType === "map") {
360
360
  if (property.keyValue)
361
361
  return "key_value";
362
- if (property.properties)
363
- return "group";
362
+ return "group";
364
363
  } else if (property.dataType === "array") {
365
364
  const of = (property as ArrayProperty).of;
366
365
  const oneOf = (property as ArrayProperty).oneOf;