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

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 (38) hide show
  1. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -6
  2. package/dist/components/PropertyIdCopyTooltipContent.d.ts +3 -0
  3. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  4. package/dist/hooks/useProjectLog.d.ts +4 -0
  5. package/dist/index.es.js +2438 -2365
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/index.umd.js +5 -5
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/util/index.d.ts +1 -1
  10. package/dist/util/useDebouncedCallback.d.ts +1 -0
  11. package/package.json +4 -4
  12. package/src/components/ArrayContainer.tsx +3 -9
  13. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +33 -36
  14. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +36 -38
  15. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +17 -14
  16. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +10 -1
  17. package/src/components/EntityCollectionView/EntityCollectionView.tsx +15 -14
  18. package/src/components/PropertyIdCopyTooltipContent.tsx +28 -0
  19. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +0 -1
  20. package/src/components/SelectableTable/SelectableTable.tsx +2 -2
  21. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -2
  22. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -2
  23. package/src/core/Drawer.tsx +17 -15
  24. package/src/core/FireCMS.tsx +4 -1
  25. package/src/core/Scaffold.tsx +5 -5
  26. package/src/core/field_configs.tsx +11 -11
  27. package/src/form/EntityForm.tsx +16 -4
  28. package/src/form/PropertyFieldBinding.tsx +3 -8
  29. package/src/form/field_bindings/MapFieldBinding.tsx +8 -6
  30. package/src/form/field_bindings/RepeatFieldBinding.tsx +4 -2
  31. package/src/hooks/useBuildNavigationController.tsx +26 -6
  32. package/src/hooks/useProjectLog.tsx +31 -0
  33. package/src/internal/EntityView.tsx +2 -2
  34. package/src/util/index.ts +1 -1
  35. package/src/util/{useDebounce.ts → useDebouncedCallback.ts} +1 -1
  36. package/dist/hooks/useVerifyLicense.d.ts +0 -0
  37. package/dist/util/useDebounce.d.ts +0 -1
  38. package/src/hooks/useVerifyLicense.tsx +0 -1
@@ -176,7 +176,7 @@ function StyledDrawer(props: {
176
176
  className={"relative h-full no-scrollbar overflow-y-auto overflow-x-hidden"}
177
177
  style={{
178
178
  width,
179
- transition: "left 150ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, opacity 150ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, width 150ms cubic-bezier(0.4, 0, 0.6, 1) 0ms"
179
+ transition: "left 100ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, opacity 100ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, width 100ms cubic-bezier(0.4, 0, 0.6, 1) 0ms"
180
180
  }}
181
181
  >
182
182
 
@@ -201,8 +201,8 @@ function StyledDrawer(props: {
201
201
  <div className={"flex flex-col h-full"}>
202
202
  <div
203
203
  style={{
204
- transition: "padding 150ms cubic-bezier(0.4, 0, 0.6, 1) 0ms",
205
- padding: props.open ? "32px 96px 0px 24px" : "72px 16px 0px"
204
+ transition: "padding 100ms cubic-bezier(0.4, 0, 0.6, 1) 0ms",
205
+ padding: props.open ? "32px 144px 0px 24px" : "72px 16px 0px"
206
206
  }}
207
207
  className={cn("cursor-pointer")}>
208
208
 
@@ -215,7 +215,7 @@ function StyledDrawer(props: {
215
215
  ? <img src={props.logo}
216
216
  alt="Logo"
217
217
  className={cn("max-w-full max-h-full",
218
- props.open ?? "w-[160px] h-[160px]")}/>
218
+ props.open ?? "w-[112px] h-[112px]")}/>
219
219
  : <FireCMSLogo/>}
220
220
 
221
221
  </Link>
@@ -259,7 +259,7 @@ function StyledDrawer(props: {
259
259
  onMouseLeave={props.onMouseLeave}
260
260
  style={{
261
261
  width,
262
- transition: "left 150ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, opacity 150ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, width 150ms cubic-bezier(0.4, 0, 0.6, 1) 0ms"
262
+ transition: "left 100ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, opacity 100ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, width 100ms cubic-bezier(0.4, 0, 0.6, 1) 0ms"
263
263
  }}>
264
264
 
265
265
  {innerDrawer}
@@ -104,6 +104,17 @@ export const DEFAULT_FIELD_CONFIGS: Record<string, PropertyConfig<any>> = {
104
104
  Field: TextFieldBinding
105
105
  }
106
106
  },
107
+ switch: {
108
+ key: "switch",
109
+ name: "Switch",
110
+ description: "Boolean true or false field (or yes or no, 0 or 1...)",
111
+ Icon: FlagIcon,
112
+ color: "#20d9d2",
113
+ property: {
114
+ dataType: "boolean",
115
+ Field: SwitchFieldBinding
116
+ }
117
+ },
107
118
  select: {
108
119
  key: "select",
109
120
  name: "Select/enum",
@@ -225,17 +236,6 @@ export const DEFAULT_FIELD_CONFIGS: Record<string, PropertyConfig<any>> = {
225
236
  Field: ArrayOfReferencesFieldBinding
226
237
  }
227
238
  },
228
- switch: {
229
- key: "switch",
230
- name: "Switch",
231
- description: "Boolean true or false field (or yes or no, 0 or 1...)",
232
- Icon: FlagIcon,
233
- color: "#20d9d2",
234
- property: {
235
- dataType: "boolean",
236
- Field: SwitchFieldBinding
237
- }
238
- },
239
239
  date_time: {
240
240
  key: "date_time",
241
241
  name: "Date/time",
@@ -34,7 +34,7 @@ import {
34
34
  } from "../hooks";
35
35
  import { ErrorFocus } from "./components/ErrorFocus";
36
36
  import { CustomIdField } from "./components/CustomIdField";
37
- import { Alert, Button, cn, DialogActions, IconButton, Typography } from "@firecms/ui";
37
+ import { Alert, Button, cn, DialogActions, IconButton, Tooltip, Typography } from "@firecms/ui";
38
38
  import { ErrorBoundary } from "../components";
39
39
  import {
40
40
  copyEntityAction,
@@ -42,6 +42,7 @@ import {
42
42
  } from "../components/EntityCollectionTable/internal/default_entity_actions";
43
43
  import { useAnalyticsController } from "../hooks/useAnalyticsController";
44
44
  import { ValidationError } from "yup";
45
+ import { PropertyIdCopyTooltipContent } from "../components/PropertyIdCopyTooltipContent";
45
46
 
46
47
  /**
47
48
  * @group Components
@@ -388,7 +389,10 @@ function EntityFormInternal<M extends Record<string, any>>({
388
389
 
389
390
  const authController = useAuthController();
390
391
 
391
- const getActionsForEntity = useCallback(({ entity, customEntityActions }: { entity?: Entity<M>, customEntityActions?: EntityAction[] }): EntityAction[] => {
392
+ const getActionsForEntity = useCallback(({ entity, customEntityActions }: {
393
+ entity?: Entity<M>,
394
+ customEntityActions?: EntityAction[]
395
+ }): EntityAction[] => {
392
396
  const createEnabled = canCreateEntity(inputCollection, authController, fullPathToCollectionSegments(path), null);
393
397
  const deleteEnabled = entity ? canDeleteEntity(inputCollection, authController, fullPathToCollectionSegments(path), entity) : true;
394
398
  const actions: EntityAction[] = [];
@@ -481,7 +485,10 @@ function EntityFormInternal<M extends Record<string, any>>({
481
485
  savingError={savingError}
482
486
  closeAfterSaveRef={closeAfterSaveRef}
483
487
  autoSave={autoSave}
484
- entityActions={getActionsForEntity({ entity, customEntityActions: inputCollection.entityActions })}/>}
488
+ entityActions={getActionsForEntity({
489
+ entity,
490
+ customEntityActions: inputCollection.entityActions
491
+ })}/>}
485
492
 
486
493
  </div>
487
494
  </div>
@@ -588,7 +595,12 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
588
595
  <div id={`form_field_${key}`}
589
596
  key={`field_${resolvedCollection.name}_${key}`}>
590
597
  <ErrorBoundary>
591
- <PropertyFieldBinding {...cmsFormFieldProps}/>
598
+ <Tooltip title={<PropertyIdCopyTooltipContent propertyId={key}/>}
599
+ delayDuration={800}
600
+ side={"left"}
601
+ sideOffset={16}>
602
+ <PropertyFieldBinding {...cmsFormFieldProps}/>
603
+ </Tooltip>
592
604
  </ErrorBoundary>
593
605
  </div>
594
606
  );
@@ -67,7 +67,7 @@ export const PropertyFieldBinding = React.memo(PropertyFieldBindingInternal, (a:
67
67
  return false;
68
68
  }) as typeof PropertyFieldBindingInternal;
69
69
 
70
- function PropertyFieldBindingInternal<T extends CMSType = CMSType, CustomProps = any, M extends Record<string, any> = Record<string, any>>
70
+ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Record<string, any> = Record<string, any>>
71
71
  ({
72
72
  propertyKey,
73
73
  property,
@@ -83,13 +83,8 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, CustomProps =
83
83
 
84
84
  const customizationController = useCustomizationController();
85
85
 
86
- const shouldAlwaysRerender = shouldPropertyReRender(property, customizationController.plugins);
87
- // we use the standard Field for user defined fields, since it rebuilds
88
- // when there are changes in other values, in contrast to Field
89
- const FieldComponent = Field;
90
-
91
86
  return (
92
- <FieldComponent
87
+ <Field
93
88
  name={propertyKey}
94
89
  >
95
90
  {(fieldProps) => {
@@ -155,7 +150,7 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, CustomProps =
155
150
  componentProps={componentProps}
156
151
  fieldProps={fieldProps}/>;
157
152
  }}
158
- </FieldComponent>
153
+ </Field>
159
154
  );
160
155
 
161
156
  }
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { FieldProps, Properties, ResolvedProperties } from "../../types";
3
3
 
4
- import { LabelWithIcon } from "../../components";
4
+ import { ErrorBoundary, LabelWithIcon } from "../../components";
5
5
  import { getIconForProperty, isHidden, pick } from "../../util";
6
6
  import { FieldHelperText } from "../components";
7
7
  import { PropertyFieldBinding } from "../PropertyFieldBinding";
@@ -70,8 +70,10 @@ export function MapFieldBinding<T extends Record<string, any>>({
70
70
  };
71
71
  return (
72
72
  <div key={`map-${propertyKey}-${index}`}>
73
- <PropertyFieldBinding
74
- {...fieldProps}/>
73
+ <ErrorBoundary>
74
+ <PropertyFieldBinding
75
+ {...fieldProps}/>
76
+ </ErrorBoundary>
75
77
  </div>
76
78
  );
77
79
  }
@@ -90,10 +92,10 @@ export function MapFieldBinding<T extends Record<string, any>>({
90
92
  );
91
93
 
92
94
  return (
93
- <>
95
+ <ErrorBoundary>
94
96
 
95
97
  {!tableMode && !partOfBlock && <ExpandablePanel initiallyExpanded={expanded}
96
- className={"px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2"}
98
+ className={"px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2 bg-slate-50 bg-opacity-50 dark:bg-gray-900"}
97
99
  title={title}>{mapFormView}</ExpandablePanel>}
98
100
 
99
101
  {(tableMode || partOfBlock) && mapFormView}
@@ -104,7 +106,7 @@ export function MapFieldBinding<T extends Record<string, any>>({
104
106
  disabled={disabled}
105
107
  property={property}/>
106
108
 
107
- </>
109
+ </ErrorBoundary>
108
110
  );
109
111
  }
110
112
 
@@ -1,7 +1,7 @@
1
1
  import React, { useState } from "react";
2
2
  import { CMSType, FieldProps, ResolvedProperty } from "../../types";
3
3
  import { FieldHelperText, FormikArrayContainer } from "../components";
4
- import { LabelWithIcon } from "../../components";
4
+ import { ErrorBoundary, LabelWithIcon } from "../../components";
5
5
  import { useClearRestoreValue } from "../../hooks";
6
6
  import { getIconForProperty } from "../../util";
7
7
  import { PropertyFieldBinding } from "../PropertyFieldBinding";
@@ -62,7 +62,9 @@ export function RepeatFieldBinding<T extends Array<any>>({
62
62
  partOfBlock: false,
63
63
  autoFocus: internalId === lastAddedId
64
64
  };
65
- return <PropertyFieldBinding {...fieldProps}/>;
65
+ return <ErrorBoundary>
66
+ <PropertyFieldBinding {...fieldProps}/>
67
+ </ErrorBoundary>;
66
68
  };
67
69
 
68
70
  const arrayContainer = <FormikArrayContainer value={value}
@@ -256,7 +256,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
256
256
  */
257
257
  const baseLocation = state && state.base_location ? state.base_location : location;
258
258
 
259
- const getAllParentCollectionsForPath = useCallback((path: string): EntityReference[] => {
259
+ const getAllParentReferencesForPath = useCallback((path: string): EntityReference[] => {
260
260
  return getParentReferencesFromPath({
261
261
  path,
262
262
  collections
@@ -264,8 +264,28 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
264
264
  }, [collections]);
265
265
 
266
266
  const getParentCollectionIds = useCallback((path: string): string[] => {
267
- return getAllParentCollectionsForPath(path).map(r => r.id);
268
- }, [getAllParentCollectionsForPath])
267
+
268
+ const strings = path.split("/");
269
+ const oddPathSegments = strings.filter((_, i) => i % 2 === 0);
270
+ oddPathSegments.pop();
271
+
272
+ const result: string[][] = [];
273
+
274
+ for (let i = 1; i <= oddPathSegments.length; i++) {
275
+ result.push(oddPathSegments.slice(0, i));
276
+ }
277
+
278
+ // for each odd path segment, get the collection
279
+ const parentCollectionIds = result.map(r => getCollectionFromPaths(r)?.id).filter(Boolean) as string[];
280
+
281
+ getCollectionFromPaths(oddPathSegments);
282
+
283
+ // const allParentCollectionsForPath = getAllParentReferencesForPath(path);
284
+ // console.log("allParentCollectionsForPath", allParentCollectionsForPath);
285
+ // const parentCollectionIds = allParentCollectionsForPath.map(r => r.id);
286
+ console.log("getParentCollectionIds", path, parentCollectionIds);
287
+ return parentCollectionIds;
288
+ }, [getAllParentReferencesForPath])
269
289
 
270
290
  const convertIdsToPaths = useCallback((ids: string[]): string[] => {
271
291
  let currentCollections = collections;
@@ -282,7 +302,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
282
302
  }
283
303
  , [getCollectionFromIds]);
284
304
 
285
- return useMemo(() => ({
305
+ return {
286
306
  collections,
287
307
  views,
288
308
  loading: !initialised || navigationLoading,
@@ -303,10 +323,10 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
303
323
  topLevelNavigation,
304
324
  baseLocation,
305
325
  refreshNavigation,
306
- getParentReferencesFromPath: getAllParentCollectionsForPath,
326
+ getParentReferencesFromPath: getAllParentReferencesForPath,
307
327
  getParentCollectionIds,
308
328
  convertIdsToPaths
309
- }), [baseCollectionPath, baseLocation, basePath, buildCMSUrlPath, buildUrlCollectionPath, buildUrlEditCollectionPath, collections, getAllParentCollectionsForPath, getCollection, getCollectionFromPaths, homeUrl, initialised, isUrlCollectionPath, navigationLoading, navigationLoadingError, refreshNavigation, resolveAliasesFrom, topLevelNavigation, urlPathToDataPath, views]);
329
+ };
310
330
  }
311
331
 
312
332
  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
+ }
@@ -16,7 +16,7 @@ import {
16
16
  removeInitialAndTrailingSlashes,
17
17
  resolveDefaultSelectedView,
18
18
  resolveEntityView,
19
- useDebounce
19
+ useDebouncedCallback
20
20
  } from "../util";
21
21
 
22
22
  import {
@@ -79,7 +79,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
79
79
  * We use this only when autoSave is enabled.
80
80
  */
81
81
  const [valuesToBeSaved, setValuesToBeSaved] = useState<EntityValues<M> | undefined>(undefined);
82
- useDebounce(valuesToBeSaved, () => {
82
+ useDebouncedCallback(valuesToBeSaved, () => {
83
83
  if (valuesToBeSaved)
84
84
  saveEntity({
85
85
  entityId: usedEntity?.id,
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";
@@ -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