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

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 (34) hide show
  1. package/dist/components/PropertyIdCopyTooltipContent.d.ts +3 -0
  2. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  3. package/dist/hooks/useProjectLog.d.ts +4 -0
  4. package/dist/index.es.js +2307 -2239
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/index.umd.js +5 -5
  7. package/dist/index.umd.js.map +1 -1
  8. package/dist/util/index.d.ts +1 -1
  9. package/dist/util/useDebouncedCallback.d.ts +1 -0
  10. package/package.json +4 -4
  11. package/src/components/ArrayContainer.tsx +3 -9
  12. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +17 -14
  13. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +10 -1
  14. package/src/components/EntityCollectionView/EntityCollectionView.tsx +6 -5
  15. package/src/components/PropertyIdCopyTooltipContent.tsx +28 -0
  16. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +0 -1
  17. package/src/components/SelectableTable/SelectableTable.tsx +2 -2
  18. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -2
  19. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -2
  20. package/src/core/Drawer.tsx +17 -15
  21. package/src/core/FireCMS.tsx +4 -1
  22. package/src/core/Scaffold.tsx +5 -5
  23. package/src/core/field_configs.tsx +11 -11
  24. package/src/form/EntityForm.tsx +16 -4
  25. package/src/form/PropertyFieldBinding.tsx +3 -8
  26. package/src/form/field_bindings/MapFieldBinding.tsx +8 -6
  27. package/src/form/field_bindings/RepeatFieldBinding.tsx +4 -2
  28. package/src/hooks/useProjectLog.tsx +31 -0
  29. package/src/internal/EntityView.tsx +2 -2
  30. package/src/util/index.ts +1 -1
  31. package/src/util/{useDebounce.ts → useDebouncedCallback.ts} +1 -1
  32. package/dist/hooks/useVerifyLicense.d.ts +0 -0
  33. package/dist/util/useDebounce.d.ts +0 -1
  34. package/src/hooks/useVerifyLicense.tsx +0 -1
@@ -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";
@@ -0,0 +1 @@
1
+ export declare function useDebouncedCallback<T>(value: T, callback: () => void, immediate: boolean, timeoutMs?: number): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@firecms/core",
3
3
  "type": "module",
4
- "version": "3.0.0-beta.2-pre.5",
4
+ "version": "3.0.0-beta.2",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/firecmsco"
@@ -38,8 +38,8 @@
38
38
  "generateIcons": "ts-node --esm src/icons/generateIcons.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@firecms/formex": "^3.0.0-beta.2-pre.5",
42
- "@firecms/ui": "^3.0.0-beta.2-pre.5",
41
+ "@firecms/formex": "^3.0.0-beta.2",
42
+ "@firecms/ui": "^3.0.0-beta.2",
43
43
  "@fontsource/ibm-plex-mono": "^5.0.8",
44
44
  "@fontsource/roboto": "^5.0.8",
45
45
  "@hello-pangea/dnd": "^16.5.0",
@@ -107,7 +107,7 @@
107
107
  "dist",
108
108
  "src"
109
109
  ],
110
- "gitHead": "5159646cfdb35e11cc510080bd3cff17104d0cb4",
110
+ "gitHead": "9c3561bc09311f2339bb6fa224c88a62d3b19617",
111
111
  "publishConfig": {
112
112
  "access": "public"
113
113
  }
@@ -7,7 +7,7 @@ import {
7
7
  AddIcon,
8
8
  Button,
9
9
  ContentCopyIcon,
10
- fieldBackgroundHoverMixin,
10
+ fieldBackgroundHoverMixin, HandleIcon,
11
11
  IconButton,
12
12
  Menu,
13
13
  MenuItem,
@@ -253,6 +253,7 @@ export function ArrayContainerItem({
253
253
  </div>;
254
254
  }
255
255
 
256
+
256
257
  export function ArrayItemOptions({
257
258
  direction,
258
259
  disabled,
@@ -291,14 +292,7 @@ export function ArrayItemOptions({
291
292
  setMenuOpen(false);
292
293
  }}
293
294
  className={`cursor-${disabled ? "inherit" : "grab"}`}>
294
- <svg width="24" height="24" viewBox="0 0 100 100" fill="none">
295
- <circle cx="28" cy="50" r="9" fill={"currentColor"}/>
296
- <circle cx="28" cy="21" r="9" fill={"currentColor"}/>
297
- <circle cx="71" cy="21" r="9" fill={"currentColor"}/>
298
- <circle cx="71" cy="50" r="9" fill={"currentColor"}/>
299
- <circle cx="71" cy="78" r="9" fill={"currentColor"}/>
300
- <circle cx="28" cy="78" r="9" fill={"currentColor"}/>
301
- </svg>
295
+ <HandleIcon/>
302
296
  </IconButton>
303
297
 
304
298
  <Menu
@@ -8,7 +8,8 @@ import {
8
8
  FilterListOffIcon,
9
9
  SearchBar,
10
10
  Select,
11
- SelectItem
11
+ SelectItem,
12
+ Tooltip
12
13
  } from "@firecms/ui";
13
14
  import { CollectionSize } from "../../../types";
14
15
  import { useLargeLayout } from "../../../hooks";
@@ -54,19 +55,21 @@ export function CollectionTableToolbar(props: CollectionTableToolbarProps) {
54
55
  </Button>;
55
56
 
56
57
  const sizeSelect = (
57
- <Select
58
- value={props.size as string}
59
- className="w-16 h-10"
60
- size={"small"}
61
- onValueChange={(v) => props.onSizeChanged(v as CollectionSize)}
62
- renderValue={(v) => <div className={"font-medium"}>{v.toUpperCase()}</div>}
63
- >
64
- {["xs", "s", "m", "l", "xl"].map((size) => (
65
- <SelectItem key={size} value={size} className={"w-12 font-medium text-center"}>
66
- {size.toUpperCase()}
67
- </SelectItem>
68
- ))}
69
- </Select>
58
+ <Tooltip title={"Table row size"} side={"right"} sideOffset={4}>
59
+ <Select
60
+ value={props.size as string}
61
+ className="w-16 h-10"
62
+ size={"small"}
63
+ onValueChange={(v) => props.onSizeChanged(v as CollectionSize)}
64
+ renderValue={(v) => <div className={"font-medium"}>{v.toUpperCase()}</div>}
65
+ >
66
+ {["xs", "s", "m", "l", "xl"].map((size) => (
67
+ <SelectItem key={size} value={size} className={"w-12 font-medium text-center"}>
68
+ {size.toUpperCase()}
69
+ </SelectItem>
70
+ ))}
71
+ </Select>
72
+ </Tooltip>
70
73
  );
71
74
 
72
75
  return (
@@ -224,7 +224,15 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
224
224
  const formex = useCreateFormex<M>({
225
225
  initialValues: (entity?.values ?? {}) as EntityValues<M>,
226
226
  validation: (values) => {
227
- return validationSchema?.validate(values)
227
+ return validationSchema?.validate(values, { abortEarly: false })
228
+ .then(() => ({}))
229
+ .catch((e) => {
230
+ const errors: Record<string, string> = {};
231
+ e.inner.forEach((error: any) => {
232
+ errors[error.path] = error.message;
233
+ });
234
+ return errors;
235
+ });
228
236
  },
229
237
  validateOnInitialRender: true,
230
238
  onSubmit: (values, actions) => {
@@ -339,6 +347,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
339
347
  }
340
348
  const form = <div
341
349
  className={`text-gray-900 dark:text-white overflow-auto rounded rounded-md bg-white dark:bg-gray-950 ${!open ? "hidden" : ""} cursor-grab max-w-[100vw]`}>
350
+
342
351
  {internalForm}
343
352
 
344
353
  {savingError &&
@@ -53,7 +53,6 @@ import {
53
53
  Popover,
54
54
  SearchIcon,
55
55
  Skeleton,
56
- TextField,
57
56
  Tooltip,
58
57
  Typography
59
58
  } from "@firecms/ui";
@@ -670,6 +669,7 @@ export const EntityCollectionView = React.memo(
670
669
  equal(a.isSubCollection, b.isSubCollection) &&
671
670
  equal(a.className, b.className) &&
672
671
  equal(a.properties, b.properties) &&
672
+ equal(a.propertiesOrder, b.propertiesOrder) &&
673
673
  equal(a.hideIdFromCollection, b.hideIdFromCollection) &&
674
674
  equal(a.inlineEditing, b.inlineEditing) &&
675
675
  equal(a.selectionEnabled, b.selectionEnabled) &&
@@ -804,13 +804,14 @@ function EntityIdHeaderWidget({
804
804
  }}
805
805
  className={"text-gray-900 dark:text-white w-96 max-w-full"}>
806
806
 
807
- <div className="flex p-4 w-full gap-4">
808
- <TextField
807
+ <div className="flex p-2 w-full gap-4">
808
+ <input
809
+ autoFocus={openPopup}
809
810
  placeholder={"Find entity by ID"}
810
- size={"small"}
811
+ // size={"small"}
811
812
  onChange={(e) => setSearchString(e.target.value)}
812
813
  value={searchString}
813
- className={"flex-grow"}/>
814
+ className={"flex-grow bg-transparent outline-none p-1"}/>
814
815
  <Button variant={"outlined"}
815
816
  disabled={!searchString}
816
817
  type={"submit"}
@@ -0,0 +1,28 @@
1
+ import { ContentPasteIcon, IconButton, Typography } from "@firecms/ui";
2
+ import { useCallback, useState } from "react";
3
+
4
+ export function PropertyIdCopyTooltipContent({ propertyId }: { propertyId: string }) {
5
+
6
+ const [copied, setCopied] = useState(false);
7
+
8
+ return (
9
+ <div className={"flex flex-row gap-2 items-center justify-center text-white"}>
10
+ <div>
11
+ <Typography variant={"caption"} className={"min-w-20 text-slate-400"}
12
+ color={"disabled"}>{copied ? "Copied" : "Property ID"}</Typography>
13
+ <Typography variant={"caption"} className={"text-white"}><code>{propertyId}</code></Typography>
14
+ </div>
15
+ {/* Copy to clipboard button*/}
16
+ <IconButton size={"small"}>
17
+ <ContentPasteIcon size={"smallest"}
18
+ className={"text-white"}
19
+ onClick={useCallback(() => {
20
+ navigator.clipboard.writeText(propertyId);
21
+ setCopied(true);
22
+ setTimeout(() => setCopied(false), 2000);
23
+ }, [propertyId])}
24
+ />
25
+ </IconButton>
26
+ </div>
27
+ );
28
+ }
@@ -266,7 +266,6 @@ export function ReferenceSelectionTable<M extends Record<string, any>>(
266
266
  forceFilter
267
267
  });
268
268
 
269
-
270
269
  const {
271
270
  textSearchLoading,
272
271
  textSearchInitialised,
@@ -115,6 +115,7 @@ export const SelectableTable = React.memo<SelectableTableProps<any>>(
115
115
  onEntityClick,
116
116
  onColumnResize,
117
117
  hoverRow = true,
118
+ size,
118
119
  inlineEditing = false,
119
120
  tableController:
120
121
  {
@@ -145,7 +146,6 @@ export const SelectableTable = React.memo<SelectableTableProps<any>>(
145
146
  }: SelectableTableProps<M>) {
146
147
 
147
148
  const ref = useRef<HTMLDivElement>(null);
148
- const [size, setSize] = React.useState<CollectionSize>("m");
149
149
 
150
150
  const [selectedCell, setSelectedCell] = React.useState<SelectedCellProps<M> | undefined>(undefined);
151
151
 
@@ -207,7 +207,7 @@ export const SelectableTable = React.memo<SelectableTableProps<any>>(
207
207
  setPopupCell: setPopupCell as ((cell?: SelectedCellProps<M>) => void),
208
208
  select,
209
209
  onValueChange,
210
- size,
210
+ size: size ?? "m",
211
211
  selectedCell,
212
212
  }}
213
213
  >
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useRef, useState } from "react";
2
2
 
3
- import { useDebounce } from "../../../util";
3
+ import { useDebouncedCallback } from "../../../util";
4
4
  import { TextareaAutosize } from "@firecms/ui";
5
5
 
6
6
  export function VirtualTableInput(props: {
@@ -43,7 +43,7 @@ export function VirtualTableInput(props: {
43
43
  }
44
44
  }, [internalValue, updateValue, value]);
45
45
 
46
- useDebounce(internalValue, doUpdate, !focused, 2000);
46
+ useDebouncedCallback(internalValue, doUpdate, !focused, 2000);
47
47
 
48
48
  useEffect(() => {
49
49
  if (ref.current && focused && !focusedState.current) {
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect, useRef, useState } from "react";
2
- import { useDebounce } from "../../../util";
2
+ import { useDebouncedCallback } from "../../../util";
3
3
 
4
4
  export function VirtualTableNumberInput(props: {
5
5
  error: Error | undefined;
@@ -42,7 +42,7 @@ export function VirtualTableNumberInput(props: {
42
42
 
43
43
  }, [internalValue, value]);
44
44
 
45
- useDebounce(internalValue, doUpdate, !focused, 2000);
45
+ useDebouncedCallback(internalValue, doUpdate, !focused, 2000);
46
46
 
47
47
  useEffect(
48
48
  () => {
@@ -45,12 +45,12 @@ export function Drawer({
45
45
  const ungroupedNavigationViews = Object.values(navigationEntries).filter(e => !e.group);
46
46
 
47
47
  const buildGroupHeader = useCallback((group?: string) => {
48
- if (!drawerOpen) return <div className="h-4"/>;
48
+ if (!drawerOpen) return <div className="h-12 w-full"/>;
49
49
  return <div
50
50
  className="pt-8 pl-6 pr-8 pb-2 flex flex-row items-center">
51
51
  <Typography variant={"caption"}
52
52
  color={"secondary"}
53
- className="font-medium flex-grow">
53
+ className="font-medium flex-grow line-clamp-1">
54
54
  {group ? group.toUpperCase() : "Views".toUpperCase()}
55
55
  </Typography>
56
56
 
@@ -128,12 +128,18 @@ export function DrawerNavigationItem({
128
128
 
129
129
  const listItem = <NavLink
130
130
  onClick={onClick}
131
+ style={{
132
+ width: !drawerOpen ? "72px" : "280px",
133
+ transition: drawerOpen ? "width 150ms ease-in" : undefined
134
+ }}
131
135
  className={({ isActive }: any) => cn("rounded-r-xl truncate",
132
- "hover:bg-gray-200 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",
133
- "flex flex-row items-center w-full mr-8",
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",
137
+ "flex flex-row items-center mr-8",
138
+ // "transition-all ease-in-out delay-100 duration-300",
139
+ // drawerOpen ? "w-full" : "w-18",
134
140
  drawerOpen ? "pl-8 h-12" : "pl-6 h-11",
135
141
  "font-medium text-sm",
136
- isActive ? "bg-gray-100 dark:bg-gray-800" : ""
142
+ isActive ? "bg-slate-200 bg-opacity-75 dark:bg-gray-800" : ""
137
143
  )}
138
144
  to={url}
139
145
  >
@@ -149,14 +155,10 @@ export function DrawerNavigationItem({
149
155
  </div>
150
156
  </NavLink>;
151
157
 
152
- // return listItem;
153
- if (drawerOpen)
154
- return listItem;
155
- else
156
- return <Tooltip
157
- open={tooltipsOpen}
158
- side="right"
159
- title={name}>
160
- {listItem}
161
- </Tooltip>;
158
+ return <Tooltip
159
+ open={drawerOpen ? false : tooltipsOpen}
160
+ side="right"
161
+ title={name}>
162
+ {listItem}
163
+ </Tooltip>;
162
164
  }
@@ -19,6 +19,7 @@ import { useBuildDataSource } from "../internal/useBuildDataSource";
19
19
  import { useBuildCustomizationController } from "../internal/useBuildCustomizationController";
20
20
  import { CustomizationControllerContext } from "../contexts/CustomizationControllerContext";
21
21
  import { AnalyticsContext } from "../contexts/AnalyticsContext";
22
+ import { useProjectLog } from "../hooks/useProjectLog";
22
23
 
23
24
  /**
24
25
  * If you are using independent components of the CMS
@@ -78,12 +79,14 @@ export function FireCMS<UserType extends User, EC extends EntityCollection>(prop
78
79
  entityViews: entityViews ?? [],
79
80
  propertyConfigs: propertyConfigs ?? {},
80
81
  components
81
- })
82
+ });
82
83
 
83
84
  const analyticsController = useMemo(() => ({
84
85
  onAnalyticsEvent
85
86
  }), []);
86
87
 
88
+ useProjectLog(authController);
89
+
87
90
  if (navigationController.navigationLoadingError) {
88
91
  return (
89
92
  <CenteredView maxWidth={"md"}>
@@ -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}
@@ -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";