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

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 (218) 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/Drawer.d.ts +5 -12
  28. package/dist/core/DrawerNavigationItem.d.ts +9 -0
  29. package/dist/core/{EntityView.d.ts → EntityEditView.d.ts} +2 -2
  30. package/dist/core/NavigationRoutes.d.ts +1 -1
  31. package/dist/core/Scaffold.d.ts +7 -10
  32. package/dist/core/index.d.ts +3 -4
  33. package/dist/form/EntityForm.d.ts +1 -1
  34. package/dist/form/components/ErrorFocus.d.ts +1 -1
  35. package/dist/form/components/StorageItemPreview.d.ts +3 -2
  36. package/dist/form/components/StorageUploadProgress.d.ts +1 -1
  37. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  38. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  39. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +4 -3
  40. package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
  41. package/dist/form/validation.d.ts +1 -1
  42. package/dist/hooks/data/delete.d.ts +2 -2
  43. package/dist/hooks/data/save.d.ts +2 -3
  44. package/dist/hooks/data/useDataSource.d.ts +2 -2
  45. package/dist/hooks/data/useEntityFetch.d.ts +3 -3
  46. package/dist/hooks/index.d.ts +2 -0
  47. package/dist/hooks/useBuildNavigationController.d.ts +6 -4
  48. package/dist/hooks/useProjectLog.d.ts +6 -2
  49. package/dist/hooks/useStorageSource.d.ts +2 -2
  50. package/dist/hooks/useValidateAuthenticator.d.ts +21 -0
  51. package/dist/index.es.js +9644 -9122
  52. package/dist/index.es.js.map +1 -1
  53. package/dist/index.umd.js +5 -5
  54. package/dist/index.umd.js.map +1 -1
  55. package/dist/internal/useBuildDataSource.d.ts +1 -12
  56. package/dist/preview/PropertyPreview.d.ts +1 -1
  57. package/dist/preview/PropertyPreviewProps.d.ts +1 -4
  58. package/dist/preview/components/BooleanPreview.d.ts +5 -1
  59. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  60. package/dist/preview/components/ReferencePreview.d.ts +1 -7
  61. package/dist/types/analytics.d.ts +1 -1
  62. package/dist/types/auth.d.ts +37 -1
  63. package/dist/types/collections.d.ts +29 -5
  64. package/dist/types/datasource.d.ts +3 -6
  65. package/dist/types/entities.d.ts +5 -1
  66. package/dist/types/entity_actions.d.ts +14 -0
  67. package/dist/types/entity_callbacks.d.ts +2 -2
  68. package/dist/types/entity_overrides.d.ts +6 -0
  69. package/dist/types/index.d.ts +2 -1
  70. package/dist/types/navigation.d.ts +14 -13
  71. package/dist/types/permissions.d.ts +5 -1
  72. package/dist/types/plugins.d.ts +20 -20
  73. package/dist/types/properties.d.ts +4 -4
  74. package/dist/types/property_config.d.ts +2 -2
  75. package/dist/types/roles.d.ts +31 -0
  76. package/dist/types/storage.d.ts +11 -3
  77. package/dist/types/user.d.ts +5 -0
  78. package/dist/util/collections.d.ts +9 -1
  79. package/dist/util/entities.d.ts +1 -1
  80. package/dist/util/icon_synonyms.d.ts +2 -4
  81. package/dist/util/icons.d.ts +8 -2
  82. package/dist/util/navigation_utils.d.ts +2 -2
  83. package/dist/util/permissions.d.ts +4 -4
  84. package/dist/util/references.d.ts +4 -2
  85. package/dist/util/resolutions.d.ts +9 -13
  86. package/dist/util/useTraceUpdate.d.ts +1 -0
  87. package/package.json +139 -119
  88. package/src/components/ClearFilterSortButton.tsx +41 -0
  89. package/src/components/DeleteEntityDialog.tsx +4 -4
  90. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +2 -2
  91. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +275 -278
  92. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +9 -5
  93. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +44 -44
  94. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  95. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +9 -16
  96. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +3 -3
  97. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +27 -32
  98. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +11 -6
  99. package/src/components/EntityCollectionTable/internal/default_entity_actions.tsx +9 -5
  100. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -4
  101. package/src/components/EntityCollectionView/EntityCollectionView.tsx +560 -554
  102. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
  103. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  104. package/src/components/EntityCollectionView/useSelectionController.tsx +30 -0
  105. package/src/components/EntityPreview.tsx +207 -70
  106. package/src/components/EntityView.tsx +84 -0
  107. package/src/components/FieldCaption.tsx +14 -0
  108. package/src/components/FireCMSAppBar.tsx +33 -11
  109. package/src/components/HomePage/DefaultHomePage.tsx +15 -11
  110. package/src/components/HomePage/NavigationCard.tsx +69 -0
  111. package/src/components/HomePage/NavigationCardBinding.tsx +116 -0
  112. package/src/components/HomePage/SmallNavigationCard.tsx +45 -0
  113. package/src/components/HomePage/index.tsx +3 -1
  114. package/src/components/PropertyIdCopyTooltipContent.tsx +2 -3
  115. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +4 -4
  116. package/src/components/ReferenceWidget.tsx +5 -5
  117. package/src/components/SearchIconsView.tsx +4 -4
  118. package/src/components/SelectableTable/SelectableTable.tsx +1 -1
  119. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  120. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +23 -8
  121. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +35 -24
  122. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +35 -15
  123. package/src/components/VirtualTable/VirtualTable.tsx +28 -20
  124. package/src/components/VirtualTable/VirtualTableProps.tsx +1 -1
  125. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
  126. package/src/components/common/types.tsx +4 -6
  127. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -1
  128. package/src/components/index.tsx +4 -2
  129. package/src/contexts/AuthControllerContext.tsx +1 -1
  130. package/src/core/Drawer.tsx +78 -103
  131. package/src/core/DrawerNavigationItem.tsx +62 -0
  132. package/src/core/{EntityView.tsx → EntityEditView.tsx} +21 -40
  133. package/src/core/EntitySidePanel.tsx +2 -2
  134. package/src/core/FireCMS.tsx +22 -7
  135. package/src/core/NavigationRoutes.tsx +11 -4
  136. package/src/core/Scaffold.tsx +76 -61
  137. package/src/core/field_configs.tsx +1 -2
  138. package/src/core/index.tsx +3 -4
  139. package/src/form/EntityForm.tsx +42 -22
  140. package/src/form/PropertyFieldBinding.tsx +0 -2
  141. package/src/form/components/StorageItemPreview.tsx +5 -3
  142. package/src/form/components/StorageUploadProgress.tsx +7 -6
  143. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +8 -12
  144. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
  145. package/src/form/field_bindings/KeyValueFieldBinding.tsx +15 -15
  146. package/src/form/field_bindings/MapFieldBinding.tsx +15 -15
  147. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +1 -1
  148. package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -0
  149. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +14 -5
  150. package/src/form/field_bindings/TextFieldBinding.tsx +7 -5
  151. package/src/form/validation.ts +3 -4
  152. package/src/hooks/data/delete.ts +3 -3
  153. package/src/hooks/data/save.ts +2 -2
  154. package/src/hooks/data/useCollectionFetch.tsx +1 -1
  155. package/src/hooks/data/useDataSource.tsx +8 -3
  156. package/src/hooks/data/useEntityFetch.tsx +4 -4
  157. package/src/hooks/index.tsx +3 -0
  158. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +9 -10
  159. package/src/hooks/useBuildModeController.tsx +11 -5
  160. package/src/hooks/useBuildNavigationController.tsx +199 -81
  161. package/src/hooks/useProjectLog.tsx +17 -7
  162. package/src/hooks/useReferenceDialog.tsx +2 -2
  163. package/src/hooks/useStorageSource.tsx +7 -2
  164. package/src/hooks/useValidateAuthenticator.tsx +115 -0
  165. package/src/internal/useBuildDataSource.ts +42 -44
  166. package/src/internal/useBuildSideEntityController.tsx +86 -20
  167. package/src/preview/PropertyPreview.tsx +3 -14
  168. package/src/preview/PropertyPreviewProps.tsx +1 -11
  169. package/src/preview/components/BooleanPreview.tsx +19 -4
  170. package/src/preview/components/EnumValuesChip.tsx +1 -1
  171. package/src/preview/components/ReferencePreview.tsx +55 -147
  172. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -1
  173. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +0 -1
  174. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -1
  175. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -1
  176. package/src/preview/property_previews/ArrayOneOfPreview.tsx +0 -1
  177. package/src/preview/property_previews/ArrayPropertyPreview.tsx +0 -1
  178. package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
  179. package/src/types/analytics.ts +1 -0
  180. package/src/types/auth.tsx +50 -1
  181. package/src/types/collections.ts +33 -5
  182. package/src/types/datasource.ts +8 -5
  183. package/src/types/entities.ts +9 -1
  184. package/src/types/entity_actions.tsx +17 -0
  185. package/src/types/entity_callbacks.ts +2 -2
  186. package/src/types/entity_overrides.tsx +7 -0
  187. package/src/types/firecms.tsx +0 -1
  188. package/src/types/index.ts +2 -1
  189. package/src/types/navigation.ts +17 -16
  190. package/src/types/permissions.ts +6 -1
  191. package/src/types/plugins.tsx +26 -28
  192. package/src/types/properties.ts +8 -6
  193. package/src/types/property_config.tsx +2 -2
  194. package/src/types/roles.ts +41 -0
  195. package/src/types/side_entity_controller.tsx +1 -0
  196. package/src/types/storage.ts +12 -3
  197. package/src/types/user.ts +7 -0
  198. package/src/util/collections.ts +22 -0
  199. package/src/util/entities.ts +1 -1
  200. package/src/util/icon_list.ts +2 -2
  201. package/src/util/icon_synonyms.ts +4 -6
  202. package/src/util/icons.tsx +11 -3
  203. package/src/util/navigation_utils.ts +6 -6
  204. package/src/util/objects.ts +0 -14
  205. package/src/util/permissions.ts +11 -8
  206. package/src/util/references.ts +36 -5
  207. package/src/util/resolutions.ts +6 -24
  208. package/src/util/strings.ts +2 -2
  209. package/src/util/useTraceUpdate.tsx +2 -1
  210. package/dist/core/SideEntityView.d.ts +0 -7
  211. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  212. package/dist/internal/useLocaleConfig.d.ts +0 -1
  213. package/dist/types/appcheck.d.ts +0 -26
  214. package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
  215. package/src/core/SideEntityView.tsx +0 -38
  216. package/src/internal/useBuildCustomizationController.tsx +0 -5
  217. package/src/internal/useLocaleConfig.tsx +0 -18
  218. package/src/types/appcheck.ts +0 -29
@@ -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, cn, 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={cn("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
+ }
@@ -0,0 +1,45 @@
1
+ import { ArrowForwardIcon, cardClickableMixin, cardMixin, cn, focusedMixin, Typography, } from "@firecms/ui";
2
+
3
+ import { Link } from "react-router-dom";
4
+
5
+ export type SmallNavigationCardProps = {
6
+ name: string,
7
+ url: string;
8
+ icon: React.ReactElement;
9
+ };
10
+
11
+ export function SmallNavigationCard({
12
+ name,
13
+ url,
14
+ icon,
15
+ }: SmallNavigationCardProps) {
16
+
17
+ return (
18
+ <>
19
+
20
+ <Link
21
+ tabIndex={0}
22
+ className={cn(cardMixin,
23
+ cardClickableMixin,
24
+ focusedMixin,
25
+ "cursor-pointer flex flex-row items-center px-4 py-2 text-inherit dark:text-inherit visited:text-inherit visited:dark:text-inherit hover:text-inherit hover:dark:text-inherit ")}
26
+ to={url}
27
+ >
28
+
29
+ <div className="flex flex-row items-center flex-grow gap-2 ">
30
+ {icon}
31
+
32
+ <Typography gutterBottom variant="h5"
33
+ component="h2"
34
+ className="mb-0 ml-4">
35
+ {name}
36
+ </Typography>
37
+ </div>
38
+
39
+ <div className={"p-4"}>
40
+ <ArrowForwardIcon color="primary"/>
41
+ </div>
42
+ </Link>
43
+
44
+ </>);
45
+ }
@@ -1,3 +1,5 @@
1
1
  export * from "./DefaultHomePage";
2
- export * from "./NavigationCollectionCard";
2
+ export * from "./NavigationCardBinding";
3
3
  export * from "./NavigationGroup";
4
+ export * from "./NavigationCard";
5
+ export * from "./SmallNavigationCard";
@@ -1,4 +1,4 @@
1
- import { ContentPasteIcon, IconButton, Typography } from "@firecms/ui";
1
+ import { ContentCopyIcon, IconButton, Typography } from "@firecms/ui";
2
2
  import { useCallback, useState } from "react";
3
3
 
4
4
  export function PropertyIdCopyTooltipContent({ propertyId }: { propertyId: string }) {
@@ -12,9 +12,8 @@ export function PropertyIdCopyTooltipContent({ propertyId }: { propertyId: strin
12
12
  color={"disabled"}>{copied ? "Copied" : "Property ID"}</Typography>
13
13
  <Typography variant={"caption"} className={"text-white"}><code>{propertyId}</code></Typography>
14
14
  </div>
15
- {/* Copy to clipboard button*/}
16
15
  <IconButton size={"small"}>
17
- <ContentPasteIcon size={"smallest"}
16
+ <ContentCopyIcon size={"smallest"}
18
17
  className={"text-white"}
19
18
  onClick={useCallback(() => {
20
19
  navigator.clipboard.writeText(propertyId);
@@ -17,7 +17,7 @@ import {
17
17
  import { ErrorView } from "../ErrorView";
18
18
  import { AddIcon, Button, DialogActions, Typography } from "@firecms/ui";
19
19
  import { canCreateEntity, fullPathToCollectionSegments, resolveCollection } from "../../util";
20
- import { useSelectionController } from "../EntityCollectionView/EntityCollectionView";
20
+ import { useSelectionController } from "../EntityCollectionView/useSelectionController";
21
21
  import { useColumnIds, useTableSearchHelper } from "../common";
22
22
  import { useSideDialogContext } from "../../core";
23
23
  import { useAnalyticsController } from "../../hooks/useAnalyticsController";
@@ -109,7 +109,7 @@ export function ReferenceSelectionTable<M extends Record<string, any>>(
109
109
 
110
110
  const fullPath = navigation.resolveAliasesFrom(pathInput);
111
111
 
112
- const dataSource = useDataSource();
112
+ const dataSource = useDataSource(collection);
113
113
 
114
114
  const [entitiesDisplayedFirst, setEntitiesDisplayedFirst] = useState<Entity<any>[]>([]);
115
115
 
@@ -291,6 +291,7 @@ export function ReferenceSelectionTable<M extends Record<string, any>>(
291
291
  displayedColumnIds={displayedColumnIds}
292
292
  onEntityClick={onEntityClick}
293
293
  tableController={tableController}
294
+ enablePopupIcon={false}
294
295
  tableRowActionsBuilder={tableRowActionsBuilder}
295
296
  title={<Typography variant={"subtitle2"}>
296
297
  {collection.singularName ? `Select ${collection.singularName}` : `Select from ${collection.name}`}
@@ -349,7 +350,7 @@ function ReferenceDialogActions({
349
350
  onNewClick();
350
351
  }
351
352
  : undefined;
352
- const addButton = canCreateEntity(collection, authController, fullPathToCollectionSegments(path), null) &&
353
+ const addButton = canCreateEntity(collection, authController, path, null) &&
353
354
  onClick && (largeLayout
354
355
  ? <Button
355
356
  onClick={onClick}
@@ -360,7 +361,6 @@ function ReferenceDialogActions({
360
361
  </Button>
361
362
  : <Button
362
363
  onClick={onClick}
363
- size="medium"
364
364
  variant="outlined"
365
365
  color="primary"
366
366
  >
@@ -50,11 +50,11 @@ export function ReferenceWidget<M extends Record<string, any>>({
50
50
 
51
51
  const collection: EntityCollection | undefined = useMemo(() => {
52
52
  return navigationController.getCollection(path);
53
- }, [path, navigationController]);
53
+ }, [path, navigationController.getCollection]);
54
54
 
55
- if (!collection) {
56
- throw Error(`Couldn't find the corresponding collection for the path: ${path}`);
57
- }
55
+ // if (!collection) {
56
+ // throw Error(`Couldn't find the corresponding collection for the path: ${path}`);
57
+ // }
58
58
 
59
59
  const onSingleEntitySelected = useCallback((entity: Entity<M> | null) => {
60
60
  if (disabled)
@@ -122,7 +122,7 @@ export function ReferenceWidget<M extends Record<string, any>>({
122
122
  size={size}/>
123
123
 
124
124
  }
125
- return <div className={cn("text-sm font-medium text-gray-500",
125
+ return <div className={cn("text-sm font-medium",
126
126
  "min-w-80 flex flex-col gap-4",
127
127
  "relative transition-colors duration-200 ease-in rounded font-medium",
128
128
  disabled ? "bg-opacity-50" : "hover:bg-opacity-75",
@@ -1,14 +1,14 @@
1
1
  import React from "react";
2
2
 
3
3
  import { coolIconKeys, debounce, Icon, IconButton, iconKeys, SearchBar, Tooltip } from "@firecms/ui";
4
- import { icon_synonyms, iconsSearch } from "../util";
4
+ import { iconSynonyms, iconsSearch } from "../util";
5
5
 
6
6
  const UPDATE_SEARCH_INDEX_WAIT_MS = 220;
7
7
 
8
- if (process.env.NODE_ENV !== "production") {
9
- Object.keys(icon_synonyms).forEach((icon: string) => {
8
+ if (iconSynonyms && process.env.NODE_ENV !== "production") {
9
+ Object.keys(iconSynonyms).forEach((icon: string) => {
10
10
  if (!iconKeys.includes(icon)) {
11
- console.warn(`The icon ${icon} no longer exists. Remove it from \`icon_synonyms\``);
11
+ console.warn(`The icon ${icon} no longer exists. Remove it from \`iconSynonyms\``);
12
12
  }
13
13
  });
14
14
  }
@@ -10,7 +10,7 @@ import {
10
10
  } from "../../types";
11
11
  import { CellRendererParams, VirtualTable, VirtualTableColumn } from "../VirtualTable";
12
12
  import { enumToObjectEntries } from "../../util";
13
- import { OnCellValueChange, OnColumnResizeParams } from "../common/types";
13
+ import { OnCellValueChange, OnColumnResizeParams } from "../common";
14
14
  import { FilterFormFieldProps } from "../VirtualTable/VirtualTableHeader";
15
15
  import { ReferenceFilterField } from "./filters/ReferenceFilterField";
16
16
  import { StringNumberFilterField } from "./filters/StringNumberFilterField";
@@ -32,7 +32,7 @@ export function BooleanFilterField({
32
32
  const valueSet = !!value;
33
33
 
34
34
  return (
35
- <div className="w-[200px]">
35
+ <div className="w-[300px]">
36
36
  <BooleanSwitchWithLabel
37
37
  value={valueSetToTrue}
38
38
  allowIndeterminate={true}
@@ -44,6 +44,5 @@ export function BooleanFilterField({
44
44
  : `${title} is false`}
45
45
  />
46
46
  </div>
47
- )
48
- ;
47
+ );
49
48
  }
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from "react";
2
2
  import { VirtualTableWhereFilterOp } from "../../VirtualTable";
3
- import { DateTimeField, Select, SelectItem } from "@firecms/ui";
3
+ import { Checkbox, DateTimeField, Label, Select, SelectItem } from "@firecms/ui";
4
4
  import { useCustomizationController } from "../../../hooks";
5
5
 
6
6
  interface DateTimeFilterFieldProps {
@@ -43,10 +43,10 @@ export function DateTimeFilterField({
43
43
 
44
44
  const [fieldOperation, fieldValue] = value || [possibleOperations[0], undefined];
45
45
  const [operation, setOperation] = useState<VirtualTableWhereFilterOp>(fieldOperation);
46
- const [internalValue, setInternalValue] = useState<Date | undefined>(fieldValue);
46
+ const [internalValue, setInternalValue] = useState<Date | null | undefined>(fieldValue);
47
47
 
48
- function updateFilter(op: VirtualTableWhereFilterOp, val: Date | undefined) {
49
- let newValue: Date | undefined = val;
48
+ function updateFilter(op: VirtualTableWhereFilterOp, val: Date | undefined | null) {
49
+ let newValue: Date | null | undefined = val;
50
50
  const prevOpIsArray = multipleSelectOperations.includes(operation);
51
51
  const newOpIsArray = multipleSelectOperations.includes(op);
52
52
  if (prevOpIsArray !== newOpIsArray) {
@@ -73,7 +73,7 @@ export function DateTimeFilterField({
73
73
 
74
74
  return (
75
75
 
76
- <div className="flex w-[440px] items-center">
76
+ <div className="flex w-[440px]">
77
77
  <div className="w-[80px]">
78
78
  <Select value={operation}
79
79
  onValueChange={(value) => {
@@ -88,19 +88,34 @@ export function DateTimeFilterField({
88
88
  </Select>
89
89
  </div>
90
90
 
91
- <div className="flex-grow ml-2">
91
+ <div className="flex-grow ml-2 flex flex-col gap-2">
92
92
 
93
93
  <DateTimeField
94
94
  mode={mode}
95
95
  size={"medium"}
96
96
  locale={locale}
97
- value={internalValue}
98
- onChange={(dateValue: Date | null) => {
97
+ value={internalValue ?? undefined}
98
+ onChange={(dateValue: Date | undefined) => {
99
99
  updateFilter(operation, dateValue === null ? undefined : dateValue);
100
100
  }}
101
101
  clearable={true}
102
102
  />
103
103
 
104
+ <Label
105
+ className="border cursor-pointer rounded-md p-2 flex items-center gap-2 [&:has(:checked)]:bg-gray-100 dark:[&:has(:checked)]:bg-gray-800"
106
+ htmlFor="null-filter"
107
+ >
108
+ <Checkbox id="null-filter"
109
+ checked={internalValue === null}
110
+ size={"small"}
111
+ onCheckedChange={(checked) => {
112
+ if (internalValue !== null)
113
+ updateFilter(operation, null);
114
+ else updateFilter(operation, undefined);
115
+ }}/>
116
+ Filter for null values
117
+ </Label>
118
+
104
119
  </div>
105
120
 
106
121
  </div>
@@ -4,7 +4,7 @@ import { Entity, EntityCollection, EntityReference } from "../../../types";
4
4
  import { ReferencePreview } from "../../../preview";
5
5
  import { getReferenceFrom } from "../../../util";
6
6
  import { useNavigationController, useReferenceDialog } from "../../../hooks";
7
- import { Button, Select, SelectItem } from "@firecms/ui";
7
+ import { Button, Checkbox, Label, Select, SelectItem } from "@firecms/ui";
8
8
 
9
9
  interface ReferenceFilterFieldProps {
10
10
  name: string,
@@ -48,33 +48,31 @@ export function ReferenceFilterField({
48
48
  ? ["array-contains"]
49
49
  : ["==", "!=", ">", "<", ">=", "<="];
50
50
 
51
- const [onHover, setOnHover] = React.useState(false);
52
-
53
51
  isArray
54
52
  ? possibleOperations.push("array-contains-any")
55
53
  : possibleOperations.push("in", "not-in");
56
54
 
57
55
  const [fieldOperation, fieldValue] = value || [possibleOperations[0], undefined];
58
56
  const [operation, setOperation] = useState<VirtualTableWhereFilterOp>(fieldOperation);
59
- const [internalValue, setInternalValue] = useState<EntityReference | EntityReference[] | undefined>(fieldValue);
57
+ const [internalValue, setInternalValue] = useState<EntityReference | EntityReference[] | undefined | null>(fieldValue);
60
58
 
61
59
  const selectedEntityIds = internalValue
62
60
  ? (Array.isArray(internalValue) ? internalValue.map((ref) => {
63
- if (!(ref.isEntityReference && ref.isEntityReference())) {
61
+ if (!(ref?.isEntityReference && ref?.isEntityReference())) {
64
62
  return null;
65
63
  }
66
64
  return ref.id;
67
65
  }).filter(Boolean) as string[] : [internalValue.id])
68
66
  : [];
69
67
 
70
- function updateFilter(op: VirtualTableWhereFilterOp, val?: EntityReference | EntityReference[]) {
68
+ function updateFilter(op: VirtualTableWhereFilterOp, val?: EntityReference | EntityReference[] | null) {
71
69
 
72
70
  const prevOpIsArray = multipleSelectOperations.includes(operation);
73
71
  const newOpIsArray = multipleSelectOperations.includes(op);
74
72
  let newValue = val;
75
73
  if (prevOpIsArray !== newOpIsArray) {
76
74
  // @ts-ignore
77
- newValue = newOpIsArray ? (newValue.isEntityReference && newValue.isEntityReference() ? [newValue] : []) : undefined
75
+ newValue = newOpIsArray ? (newValue?.isEntityReference && newValue?.isEntityReference() ? [newValue] : []) : undefined
78
76
  }
79
77
 
80
78
  setOperation(op);
@@ -129,28 +127,22 @@ export function ReferenceFilterField({
129
127
 
130
128
  const buildEntry = (reference: EntityReference) => {
131
129
  return (
132
- <div
133
- className="mb-0.5"
134
- onMouseEnter={() => setOnHover(true)}
135
- onMouseMove={() => setOnHover(true)}
136
- onMouseLeave={() => setOnHover(false)}>
137
- <ReferencePreview
138
- disabled={!path}
139
- previewProperties={previewProperties}
140
- size={"medium"}
141
- onClick={doOpenDialog}
142
- reference={reference}
143
- onHover={onHover}
144
- allowEntityNavigation={false}
145
- />
146
- </div>
130
+ <ReferencePreview
131
+ disabled={!path}
132
+ previewProperties={previewProperties}
133
+ size={"medium"}
134
+ onClick={doOpenDialog}
135
+ reference={reference}
136
+ hover={true}
137
+ allowEntityNavigation={false}
138
+ />
147
139
  );
148
140
  };
149
141
 
150
142
  return (
151
143
 
152
144
  <div className="flex w-[440px] flex-row">
153
- <div className="w-[120px]">
145
+ <div className="w-[140px]">
154
146
  <Select value={operation}
155
147
  onValueChange={(value) => {
156
148
  updateFilter(value as VirtualTableWhereFilterOp, internalValue);
@@ -164,21 +156,40 @@ export function ReferenceFilterField({
164
156
  </Select>
165
157
  </div>
166
158
 
167
- <div className="flex-grow ml-2 h-full">
159
+ <div className="flex-grow ml-2 h-full gap-2 flex flex-col">
168
160
 
169
161
  {internalValue && Array.isArray(internalValue) && <div>
170
162
  {internalValue.map((ref, index) => buildEntry(ref))}
171
163
  </div>}
164
+
172
165
  {internalValue && !Array.isArray(internalValue) && <div>
173
166
  {buildEntry(internalValue)}
174
167
  </div>}
168
+
175
169
  {(!internalValue || (Array.isArray(internalValue) && internalValue.length === 0)) &&
176
170
  <Button onClick={doOpenDialog}
177
171
  variant={"outlined"}
172
+ size={"large"}
178
173
  className="h-full w-full">
179
174
  {multiple ? "Select references" : "Select reference"}
180
175
  </Button>
181
176
  }
177
+
178
+ {!isArray && <Label
179
+ className="border cursor-pointer rounded-md p-2 flex items-center gap-2 [&:has(:checked)]:bg-gray-100 dark:[&:has(:checked)]:bg-gray-800"
180
+ htmlFor="null-filter"
181
+ >
182
+ <Checkbox id="null-filter"
183
+ checked={internalValue === null}
184
+ size={"small"}
185
+ onCheckedChange={(checked) => {
186
+ if (internalValue !== null)
187
+ updateFilter(operation, null);
188
+ else updateFilter(operation, undefined);
189
+ }}/>
190
+ Filter for null values
191
+ </Label>}
192
+
182
193
  </div>
183
194
 
184
195
  </div>