@firecms/core 3.0.0-beta.2-pre.5 → 3.0.0-beta.3

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 (83) hide show
  1. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -6
  2. package/dist/components/PropertyIdCopyTooltipContent.d.ts +3 -0
  3. package/dist/components/ReferenceWidget.d.ts +3 -3
  4. package/dist/components/index.d.ts +0 -1
  5. package/dist/core/SideEntityView.d.ts +7 -0
  6. package/dist/core/index.d.ts +0 -2
  7. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  8. package/dist/form/components/index.d.ts +1 -0
  9. package/dist/form/index.d.ts +1 -0
  10. package/dist/hooks/index.d.ts +2 -1
  11. package/dist/{core → hooks}/useBuildModeController.d.ts +1 -1
  12. package/dist/hooks/useBuildNavigationController.d.ts +1 -1
  13. package/dist/hooks/useProjectLog.d.ts +4 -0
  14. package/dist/index.es.js +3377 -3290
  15. package/dist/index.es.js.map +1 -1
  16. package/dist/index.umd.js +5 -5
  17. package/dist/index.umd.js.map +1 -1
  18. package/dist/internal/useBuildDataSource.d.ts +4 -0
  19. package/dist/types/entities.d.ts +1 -0
  20. package/dist/util/index.d.ts +2 -1
  21. package/dist/util/useDebouncedCallback.d.ts +1 -0
  22. package/package.json +12 -4
  23. package/src/components/ArrayContainer.tsx +3 -9
  24. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +33 -37
  25. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +36 -38
  26. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +2 -1
  27. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -1
  28. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +17 -14
  29. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +10 -1
  30. package/src/components/EntityCollectionView/EntityCollectionView.tsx +15 -14
  31. package/src/components/PropertyIdCopyTooltipContent.tsx +28 -0
  32. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +0 -1
  33. package/src/components/ReferenceWidget.tsx +4 -4
  34. package/src/components/SelectableTable/SelectableTable.tsx +2 -2
  35. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +2 -2
  36. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -2
  37. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -2
  38. package/src/components/index.tsx +0 -1
  39. package/src/core/Drawer.tsx +17 -15
  40. package/src/core/EntitySidePanel.tsx +1 -1
  41. package/src/{internal → core}/EntityView.tsx +4 -4
  42. package/src/core/FireCMS.tsx +4 -1
  43. package/src/core/Scaffold.tsx +5 -5
  44. package/src/core/SideEntityView.tsx +38 -0
  45. package/src/core/field_configs.tsx +11 -11
  46. package/src/core/index.tsx +0 -2
  47. package/src/form/EntityForm.tsx +16 -4
  48. package/src/form/PropertyFieldBinding.tsx +3 -8
  49. package/src/form/components/index.tsx +1 -0
  50. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +2 -3
  51. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +4 -3
  52. package/src/form/field_bindings/BlockFieldBinding.tsx +2 -3
  53. package/src/form/field_bindings/DateTimeFieldBinding.tsx +3 -3
  54. package/src/form/field_bindings/KeyValueFieldBinding.tsx +4 -4
  55. package/src/form/field_bindings/MapFieldBinding.tsx +9 -7
  56. package/src/form/field_bindings/MarkdownFieldBinding.tsx +1 -2
  57. package/src/form/field_bindings/MultiSelectBinding.tsx +2 -3
  58. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -2
  59. package/src/form/field_bindings/ReferenceFieldBinding.tsx +5 -4
  60. package/src/form/field_bindings/RepeatFieldBinding.tsx +6 -4
  61. package/src/form/field_bindings/SelectFieldBinding.tsx +2 -3
  62. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +3 -3
  63. package/src/form/field_bindings/SwitchFieldBinding.tsx +2 -3
  64. package/src/form/field_bindings/TextFieldBinding.tsx +3 -4
  65. package/src/form/index.tsx +1 -0
  66. package/src/hooks/index.tsx +3 -1
  67. package/src/{core → hooks}/useBuildModeController.tsx +1 -1
  68. package/src/hooks/useBuildNavigationController.tsx +30 -15
  69. package/src/hooks/useProjectLog.tsx +31 -0
  70. package/src/internal/useBuildDataSource.ts +7 -2
  71. package/src/preview/PropertyPreview.tsx +1 -1
  72. package/src/preview/components/ReferencePreview.tsx +1 -1
  73. package/src/types/entities.ts +4 -0
  74. package/src/util/index.ts +2 -1
  75. package/src/util/{useDebounce.ts → useDebouncedCallback.ts} +1 -1
  76. package/dist/hooks/useVerifyLicense.d.ts +0 -0
  77. package/dist/util/useDebounce.d.ts +0 -1
  78. package/src/hooks/useVerifyLicense.tsx +0 -1
  79. /package/dist/{internal → core}/EntityView.d.ts +0 -0
  80. /package/dist/{components → form/components}/LabelWithIcon.d.ts +0 -0
  81. /package/dist/{core → hooks}/useBuildLocalConfigurationPersistence.d.ts +0 -0
  82. /package/src/{components → form/components}/LabelWithIcon.tsx +0 -0
  83. /package/src/{core → hooks}/useBuildLocalConfigurationPersistence.tsx +0 -0
@@ -1,11 +1,10 @@
1
1
  import React from "react";
2
2
 
3
3
  import { FieldProps } from "../../types";
4
- import { useClearRestoreValue } from "../../hooks";
5
4
  import { getIconForProperty } from "../../util";
6
- import { FieldHelperText } from "../components/FieldHelperText";
5
+ import { FieldHelperText, LabelWithIcon } from "../components";
7
6
  import { BooleanSwitchWithLabel } from "@firecms/ui";
8
- import { LabelWithIcon } from "../../components";
7
+ import { useClearRestoreValue } from "../useClearRestoreValue";
9
8
 
10
9
  type SwitchFieldProps = FieldProps<boolean>;
11
10
 
@@ -1,12 +1,11 @@
1
1
  import React, { useCallback } from "react";
2
2
 
3
+ import { ClearIcon, Collapse, IconButton, TextField } from "@firecms/ui";
3
4
  import { FieldProps, PreviewType } from "../../types";
4
- import { FieldHelperText } from "../components";
5
- import { useClearRestoreValue } from "../../hooks";
5
+ import { FieldHelperText, LabelWithIcon } from "../components";
6
6
  import { getIconForProperty } from "../../util";
7
- import { ClearIcon, Collapse, IconButton, TextField } from "@firecms/ui";
8
7
  import { PropertyPreview } from "../../preview";
9
- import { LabelWithIcon } from "../../components";
8
+ import { useClearRestoreValue } from "../useClearRestoreValue";
10
9
 
11
10
  interface TextFieldProps<T extends string | number> extends FieldProps<T> {
12
11
  allowInfinity?: boolean
@@ -40,3 +40,4 @@ export {
40
40
  } from "./EntityForm";
41
41
 
42
42
  export { PropertyFieldBinding } from "./PropertyFieldBinding";
43
+ export * from "./useClearRestoreValue";
@@ -4,7 +4,6 @@ export * from "./data/useEntityFetch";
4
4
  export * from "./data/save";
5
5
  export * from "./data/delete";
6
6
 
7
- export * from "../form/useClearRestoreValue";
8
7
  export * from "./useNavigationController";
9
8
 
10
9
  export * from "./useResolvedNavigationFrom";
@@ -23,3 +22,6 @@ export * from "./useReferenceDialog";
23
22
  export * from "./useBrowserTitleAndIcon";
24
23
  export * from "./useCustomizationController";
25
24
  export * from "./useBuildNavigationController";
25
+
26
+ export * from "./useBuildLocalConfigurationPersistence";
27
+ export * from "./useBuildModeController";
@@ -1,6 +1,6 @@
1
1
  import { useCallback, useEffect, useState } from "react";
2
2
 
3
- import { ModeController } from "../hooks";
3
+ import { ModeController } from "./index";
4
4
 
5
5
  /**
6
6
  * Use this hook to build a color mode controller that determines
@@ -1,5 +1,6 @@
1
- import { useCallback, useEffect, useMemo, useState } from "react";
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { useLocation } from "react-router-dom";
3
+ import equal from "react-fast-compare"
3
4
 
4
5
  import {
5
6
  AuthController,
@@ -49,7 +50,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
49
50
  basePath = DEFAULT_BASE_PATH,
50
51
  baseCollectionPath = DEFAULT_COLLECTION_PATH,
51
52
  authController,
52
- collections: baseCollections,
53
+ collections: collectionsProp,
53
54
  views: baseViews,
54
55
  userConfigPersistence,
55
56
  dataSourceDelegate,
@@ -58,6 +59,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
58
59
 
59
60
  const location = useLocation();
60
61
 
62
+ const collectionsRef = useRef<EntityCollection[] | null>();
61
63
  const [collections, setCollections] = useState<EntityCollection[] | undefined>();
62
64
  const [views, setViews] = useState<CMSView[] | undefined>();
63
65
  const [initialised, setInitialised] = useState<boolean>(false);
@@ -80,7 +82,6 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
80
82
  [baseCollectionPath]);
81
83
 
82
84
  const computeTopNavigation = useCallback((collections: EntityCollection[], views: CMSView[]): TopNavigationResult => {
83
- // return (collection.editable && resolvePermissions(collection, authController, paths).editCollection) ?? DEFAULT_PERMISSIONS.editCollection;
84
85
  const navigationEntries: TopNavigationEntry[] = [
85
86
  ...(collections ?? []).map(collection => (!collection.hideFromNavigation
86
87
  ? {
@@ -125,14 +126,16 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
125
126
 
126
127
  try {
127
128
  const [resolvedCollections = [], resolvedViews = []] = await Promise.all([
128
- resolveCollections(baseCollections, authController, dataSourceDelegate, injectCollections),
129
+ resolveCollections(collectionsProp, authController, dataSourceDelegate, injectCollections),
129
130
  resolveCMSViews(baseViews, authController, dataSourceDelegate)
130
131
  ]
131
132
  );
132
-
133
- setCollections(resolvedCollections);
134
- setViews(resolvedViews);
135
- setTopLevelNavigation(computeTopNavigation(resolvedCollections ?? [], resolvedViews));
133
+ if (!equal(collectionsRef.current, resolvedCollections) || !equal(views, resolvedViews) || !equal(topLevelNavigation, computeTopNavigation(resolvedCollections, resolvedViews))) {
134
+ collectionsRef.current = resolvedCollections;
135
+ setCollections(resolvedCollections);
136
+ setViews(resolvedViews);
137
+ setTopLevelNavigation(computeTopNavigation(resolvedCollections ?? [], resolvedViews));
138
+ }
136
139
  } catch (e) {
137
140
  console.error(e);
138
141
  setNavigationLoadingError(e as any);
@@ -140,7 +143,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
140
143
 
141
144
  setNavigationLoading(false);
142
145
  setInitialised(true);
143
- }, [baseCollections, authController.user, authController.initialLoading, baseViews, computeTopNavigation, injectCollections]);
146
+ }, [collectionsProp, authController.user, authController.initialLoading, baseViews, computeTopNavigation, injectCollections]);
144
147
 
145
148
  useEffect(() => {
146
149
  refreshNavigation();
@@ -256,7 +259,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
256
259
  */
257
260
  const baseLocation = state && state.base_location ? state.base_location : location;
258
261
 
259
- const getAllParentCollectionsForPath = useCallback((path: string): EntityReference[] => {
262
+ const getAllParentReferencesForPath = useCallback((path: string): EntityReference[] => {
260
263
  return getParentReferencesFromPath({
261
264
  path,
262
265
  collections
@@ -264,8 +267,20 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
264
267
  }, [collections]);
265
268
 
266
269
  const getParentCollectionIds = useCallback((path: string): string[] => {
267
- return getAllParentCollectionsForPath(path).map(r => r.id);
268
- }, [getAllParentCollectionsForPath])
270
+
271
+ const strings = path.split("/");
272
+ const oddPathSegments = strings.filter((_, i) => i % 2 === 0);
273
+ oddPathSegments.pop();
274
+
275
+ const result: string[][] = [];
276
+
277
+ for (let i = 1; i <= oddPathSegments.length; i++) {
278
+ result.push(oddPathSegments.slice(0, i));
279
+ }
280
+
281
+ // for each odd path segment, get the collection
282
+ return result.map(r => getCollectionFromPaths(r)?.id).filter(Boolean) as string[];
283
+ }, [getAllParentReferencesForPath])
269
284
 
270
285
  const convertIdsToPaths = useCallback((ids: string[]): string[] => {
271
286
  let currentCollections = collections;
@@ -282,7 +297,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
282
297
  }
283
298
  , [getCollectionFromIds]);
284
299
 
285
- return useMemo(() => ({
300
+ return {
286
301
  collections,
287
302
  views,
288
303
  loading: !initialised || navigationLoading,
@@ -303,10 +318,10 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
303
318
  topLevelNavigation,
304
319
  baseLocation,
305
320
  refreshNavigation,
306
- getParentReferencesFromPath: getAllParentCollectionsForPath,
321
+ getParentReferencesFromPath: getAllParentReferencesForPath,
307
322
  getParentCollectionIds,
308
323
  convertIdsToPaths
309
- }), [baseCollectionPath, baseLocation, basePath, buildCMSUrlPath, buildUrlCollectionPath, buildUrlEditCollectionPath, collections, getAllParentCollectionsForPath, getCollection, getCollectionFromPaths, homeUrl, initialised, isUrlCollectionPath, navigationLoading, navigationLoadingError, refreshNavigation, resolveAliasesFrom, topLevelNavigation, urlPathToDataPath, views]);
324
+ };
310
325
  }
311
326
 
312
327
  export function getSidePanelKey(path: string, entityId?: string) {
@@ -0,0 +1,31 @@
1
+ import { useEffect, useRef } from "react";
2
+ import { AuthController } from "../types";
3
+
4
+ export const DEFAULT_SERVER_DEV = "https://api-kdoe6pj3qq-ey.a.run.app";
5
+ export const DEFAULT_SERVER = "https://api-drplyi3b6q-ey.a.run.app";
6
+
7
+ async function makeRequest(authController: AuthController) {
8
+ const firebaseToken = await authController.getAuthToken();
9
+ return fetch(DEFAULT_SERVER + "/access_log",
10
+ {
11
+ // mode: "no-cors",
12
+ method: "POST",
13
+ headers: {
14
+ "Content-Type": "application/json",
15
+ Authorization: `Basic ${firebaseToken}`,
16
+ },
17
+ body: JSON.stringify({})
18
+ })
19
+ .then(async (res) => {
20
+ });
21
+ }
22
+
23
+ export function useProjectLog(authController: AuthController) {
24
+ const accessedUserRef = useRef<string | null>(null);
25
+ useEffect(() => {
26
+ if (authController.user && authController.user.uid !== accessedUserRef.current && !authController.initialLoading) {
27
+ makeRequest(authController);
28
+ accessedUserRef.current = authController.user.uid;
29
+ }
30
+ }, [authController]);
31
+ }
@@ -330,6 +330,10 @@ export function useBuildDataSource({
330
330
  * bindings.
331
331
  * Also, Firestore references are replaced with {@link EntityReference}
332
332
  * @param data
333
+ * @param buildReference
334
+ * @param buildGeoPoint
335
+ * @param buildDate
336
+ * @param buildDelete
333
337
  * @group Firestore
334
338
  */
335
339
  export function cmsToDelegateModel(data: any,
@@ -340,9 +344,11 @@ export function cmsToDelegateModel(data: any,
340
344
  ): any {
341
345
  if (data === undefined) {
342
346
  return buildDelete();
347
+ } else if (data === null) {
348
+ return null;
343
349
  } else if (Array.isArray(data)) {
344
350
  return data.map(v => cmsToDelegateModel(v, buildReference, buildGeoPoint, buildDate, buildDelete));
345
- } else if (data instanceof EntityReference) {
351
+ } else if (data.isEntityReference && data.isEntityReference()) {
346
352
  return buildReference(data);
347
353
  } else if (data instanceof GeoPoint) {
348
354
  return buildGeoPoint(data);
@@ -355,4 +361,3 @@ export function cmsToDelegateModel(data: any,
355
361
  }
356
362
  return data;
357
363
  }
358
-
@@ -178,7 +178,7 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
178
178
  }
179
179
  } else if (property.dataType === "reference") {
180
180
  if (typeof property.path === "string") {
181
- if (value instanceof EntityReference) {
181
+ if (typeof value === "object" && "isEntityReference" in value && value.isEntityReference()) {
182
182
  content = <ReferencePreview
183
183
  disabled={!property.path}
184
184
  previewProperties={property.previewProperties}
@@ -32,7 +32,7 @@ export type ReferencePreviewProps = {
32
32
  */
33
33
  export const ReferencePreview = React.memo<ReferencePreviewProps>(function ReferencePreview(props: ReferencePreviewProps) {
34
34
  const reference = props.reference;
35
- if (!((reference as unknown) instanceof EntityReference)) {
35
+ if (!(typeof reference === "object" && "isEntityReference" in reference && reference.isEntityReference())) {
36
36
  console.warn("Reference preview received value of type", typeof reference);
37
37
  return <ReferencePreviewContainer
38
38
  onClick={props.onClick}
@@ -56,6 +56,10 @@ export class EntityReference<M extends Record<string, any> = any> {
56
56
  get pathWithId() {
57
57
  return `${this.path}/${this.id}`;
58
58
  }
59
+
60
+ isEntityReference() {
61
+ return true;
62
+ }
59
63
  }
60
64
 
61
65
  export class GeoPoint {
package/src/util/index.ts CHANGED
@@ -7,7 +7,7 @@ export * from "./objects";
7
7
  export * from "./paths";
8
8
  export * from "./regexp";
9
9
  export * from "./navigation_utils";
10
- export * from "./useDebounce";
10
+ export * from "./useDebouncedCallback";
11
11
  export * from "./property_utils";
12
12
  export * from "./resolutions";
13
13
  export * from "./permissions";
@@ -20,3 +20,4 @@ export * from "./flatten_object";
20
20
  export * from "./make_properties_editable";
21
21
  export * from "./join_collections";
22
22
  export * from "./builders";
23
+ export * from "./useTraceUpdate";
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
 
3
- export function useDebounce<T>(value: T, callback: () => void, immediate: boolean, timeoutMs = 300) {
3
+ export function useDebouncedCallback<T>(value: T, callback: () => void, immediate: boolean, timeoutMs = 300) {
4
4
 
5
5
  const pendingUpdate = React.useRef(false);
6
6
  const performUpdate = () => {
File without changes
@@ -1 +0,0 @@
1
- export declare function useDebounce<T>(value: T, callback: () => void, immediate: boolean, timeoutMs?: number): void;
@@ -1 +0,0 @@
1
- // export
File without changes