@firecms/core 3.3.0-canary.d3242eb → 3.4.0-canary.63041d0

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 (110) hide show
  1. package/dist/app/useApp.d.ts +1 -0
  2. package/dist/components/EntityCollectionTable/column_utils.d.ts +4 -3
  3. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +6 -1
  4. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +7 -0
  5. package/dist/components/EntityCollectionView/FiltersDialog.d.ts +2 -1
  6. package/dist/components/EntityPreview.d.ts +3 -1
  7. package/dist/components/SelectableTable/filters/filter_text_input.d.ts +30 -0
  8. package/dist/components/SelectableTable/filters/filter_text_input.test.d.ts +1 -0
  9. package/dist/components/common/table_url_params.d.ts +24 -0
  10. package/dist/components/common/useDataSourceTableController.d.ts +7 -1
  11. package/dist/components/common/useTableSearchHelper.d.ts +7 -1
  12. package/dist/core/DefaultDrawer.d.ts +10 -3
  13. package/dist/core/EntityEditView.d.ts +7 -1
  14. package/dist/core/field_configs.d.ts +1 -1
  15. package/dist/form/field_bindings/GeopointFieldBinding.d.ts +5 -0
  16. package/dist/form/index.d.ts +1 -0
  17. package/dist/hooks/data/save.d.ts +1 -1
  18. package/dist/hooks/data/useEntityFetch.d.ts +6 -1
  19. package/dist/index.es.js +2960 -1338
  20. package/dist/index.es.js.map +1 -1
  21. package/dist/index.umd.js +2958 -1336
  22. package/dist/index.umd.js.map +1 -1
  23. package/dist/locales/pl.d.ts +2 -0
  24. package/dist/preview/index.d.ts +1 -0
  25. package/dist/preview/property_previews/GeopointPropertyPreview.d.ts +4 -0
  26. package/dist/types/collections.d.ts +24 -0
  27. package/dist/types/datasource.d.ts +42 -0
  28. package/dist/types/properties.d.ts +17 -1
  29. package/dist/types/side_entity_controller.d.ts +6 -0
  30. package/dist/types/translations.d.ts +17 -3
  31. package/dist/util/__tests__/collections.test.d.ts +1 -0
  32. package/dist/util/__tests__/urls.test.d.ts +1 -0
  33. package/dist/util/collections.d.ts +1 -1
  34. package/dist/util/entities.d.ts +1 -0
  35. package/dist/util/geopoint.d.ts +22 -0
  36. package/dist/util/index.d.ts +2 -0
  37. package/dist/util/navigation_blocking.d.ts +22 -0
  38. package/dist/util/navigation_from_path.d.ts +17 -0
  39. package/dist/util/navigation_utils.d.ts +23 -1
  40. package/dist/util/urls.d.ts +22 -0
  41. package/package.json +16 -9
  42. package/src/app/Scaffold.tsx +47 -45
  43. package/src/app/useApp.tsx +1 -0
  44. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +3 -1
  45. package/src/components/EntityCollectionTable/column_utils.tsx +11 -19
  46. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -1
  47. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +7 -0
  48. package/src/components/EntityCollectionView/EntityCollectionView.tsx +24 -3
  49. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +4 -1
  50. package/src/components/EntityCollectionView/FiltersDialog.tsx +39 -28
  51. package/src/components/EntityPreview.tsx +41 -40
  52. package/src/components/HomePage/NavigationCardBinding.tsx +6 -3
  53. package/src/components/ReferenceWidget.tsx +1 -1
  54. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +2 -2
  55. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +33 -7
  56. package/src/components/SelectableTable/filters/filter_text_input.test.ts +184 -0
  57. package/src/components/SelectableTable/filters/filter_text_input.ts +71 -0
  58. package/src/components/VirtualTable/VirtualTable.tsx +19 -8
  59. package/src/components/common/table_url_params.ts +172 -0
  60. package/src/components/common/useDataSourceTableController.tsx +98 -159
  61. package/src/components/common/useTableSearchHelper.ts +21 -2
  62. package/src/contexts/SnackbarProvider.tsx +14 -1
  63. package/src/core/DefaultDrawer.tsx +151 -65
  64. package/src/core/DrawerNavigationGroup.tsx +27 -29
  65. package/src/core/DrawerNavigationItem.tsx +10 -12
  66. package/src/core/EntityEditView.tsx +75 -32
  67. package/src/core/EntitySidePanel.tsx +2 -0
  68. package/src/core/field_configs.tsx +15 -0
  69. package/src/form/EntityForm.tsx +1 -1
  70. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -1
  71. package/src/form/field_bindings/GeopointFieldBinding.tsx +139 -0
  72. package/src/form/index.tsx +1 -0
  73. package/src/hooks/data/save.ts +2 -0
  74. package/src/hooks/data/useEntityFetch.tsx +9 -0
  75. package/src/hooks/useBuildNavigationController.tsx +5 -1
  76. package/src/hooks/useValidateAuthenticator.tsx +4 -0
  77. package/src/i18n/FireCMSi18nProvider.tsx +2 -0
  78. package/src/internal/useBuildDataSource.ts +11 -0
  79. package/src/internal/useBuildSideEntityController.tsx +8 -1
  80. package/src/locales/de.ts +18 -5
  81. package/src/locales/en.ts +18 -5
  82. package/src/locales/es.ts +18 -5
  83. package/src/locales/fr.ts +18 -5
  84. package/src/locales/hi.ts +18 -5
  85. package/src/locales/it.ts +18 -5
  86. package/src/locales/pl.ts +735 -0
  87. package/src/locales/pt.ts +18 -5
  88. package/src/preview/PropertyPreview.tsx +12 -0
  89. package/src/preview/components/StorageThumbnail.tsx +24 -2
  90. package/src/preview/index.ts +1 -0
  91. package/src/preview/property_previews/GeopointPropertyPreview.tsx +23 -0
  92. package/src/routes/FireCMSRoute.tsx +47 -25
  93. package/src/types/collections.ts +26 -0
  94. package/src/types/datasource.ts +42 -0
  95. package/src/types/properties.ts +17 -0
  96. package/src/types/side_entity_controller.tsx +6 -0
  97. package/src/types/translations.ts +17 -3
  98. package/src/util/__tests__/collections.test.ts +32 -0
  99. package/src/util/__tests__/urls.test.ts +131 -0
  100. package/src/util/collections.ts +1 -1
  101. package/src/util/entities.ts +13 -0
  102. package/src/util/geopoint.ts +81 -0
  103. package/src/util/index.ts +2 -0
  104. package/src/util/navigation_blocking.ts +45 -0
  105. package/src/util/navigation_from_path.ts +41 -6
  106. package/src/util/navigation_utils.ts +40 -2
  107. package/src/util/parent_references_from_path.ts +4 -2
  108. package/src/util/previews.ts +8 -1
  109. package/src/util/resolutions.ts +11 -0
  110. package/src/util/urls.ts +52 -0
@@ -0,0 +1,139 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+
3
+ import { CloseIcon, IconButton, TextField } from "@firecms/ui";
4
+ import { FieldProps, GeoPoint } from "../../types";
5
+ import { FieldHelperText, LabelWithIcon } from "../components";
6
+ import { PropertyIdCopyTooltip } from "../../components";
7
+ import { useClearRestoreValue } from "../useClearRestoreValue";
8
+ import { getIconForProperty } from "../../util";
9
+ import { formatGeoPoint, getGeoPointCoordinates, parseGeoPoint } from "../../util/geopoint";
10
+
11
+ type GeopointFieldBindingProps = FieldProps<GeoPoint>;
12
+
13
+ export function GeopointFieldBinding({
14
+ propertyKey,
15
+ value,
16
+ setValue,
17
+ error,
18
+ showError,
19
+ disabled,
20
+ autoFocus,
21
+ property,
22
+ includeDescription,
23
+ size = "large"
24
+ }: GeopointFieldBindingProps) {
25
+
26
+ const coordinates = getGeoPointCoordinates(value);
27
+ const canClear = Boolean((property as any).clearable);
28
+ const [latitude, setLatitude] = useState<string>(coordinates ? coordinates.latitude.toString() : "");
29
+ const [longitude, setLongitude] = useState<string>(coordinates ? coordinates.longitude.toString() : "");
30
+ const [localError, setLocalError] = useState<string | undefined>();
31
+ const skipSyncRef = useRef(false);
32
+
33
+ useClearRestoreValue({
34
+ property,
35
+ value,
36
+ setValue
37
+ });
38
+
39
+ useEffect(() => {
40
+ if (skipSyncRef.current) {
41
+ skipSyncRef.current = false;
42
+ return;
43
+ }
44
+ const nextCoordinates = getGeoPointCoordinates(value);
45
+ setLatitude(nextCoordinates ? nextCoordinates.latitude.toString() : "");
46
+ setLongitude(nextCoordinates ? nextCoordinates.longitude.toString() : "");
47
+ }, [value]);
48
+
49
+ const updateGeoPoint = (nextLatitude: string, nextLongitude: string) => {
50
+ skipSyncRef.current = true;
51
+ setLatitude(nextLatitude);
52
+ setLongitude(nextLongitude);
53
+
54
+ const trimmedLatitude = nextLatitude.trim();
55
+ const trimmedLongitude = nextLongitude.trim();
56
+
57
+ if (!trimmedLatitude && !trimmedLongitude) {
58
+ setLocalError(undefined);
59
+ setValue(null);
60
+ return;
61
+ }
62
+
63
+ const parsed = parseGeoPoint(`${trimmedLatitude}, ${trimmedLongitude}`);
64
+
65
+ if (parsed.error) {
66
+ setLocalError(parsed.error);
67
+ setValue(null);
68
+ return;
69
+ }
70
+
71
+ setLocalError(undefined);
72
+ setValue(parsed.point);
73
+ };
74
+
75
+ const handleClear = (event?: React.MouseEvent) => {
76
+ if (event) {
77
+ event.preventDefault();
78
+ event.stopPropagation();
79
+ }
80
+ updateGeoPoint("", "");
81
+ };
82
+
83
+ const resolvedError = localError ?? error;
84
+ const shouldShowError = Boolean(resolvedError) || Boolean(showError && error);
85
+
86
+ return (
87
+ <>
88
+ <PropertyIdCopyTooltip propertyKey={propertyKey}>
89
+ <div className="flex flex-col gap-2">
90
+ <div className="mt-1">
91
+ <LabelWithIcon
92
+ icon={getIconForProperty(property, "small")}
93
+ required={property.validation?.required}
94
+ title={property.name}
95
+ className={shouldShowError ? "text-red-500 dark:text-red-500" : "text-text-secondary dark:text-text-secondary-dark"}
96
+ />
97
+ </div>
98
+ <div className="grid grid-cols-1 gap-2 md:grid-cols-2">
99
+ <TextField
100
+ size={size}
101
+ value={latitude}
102
+ onChange={(event) => updateGeoPoint(event.target.value, longitude)}
103
+ autoFocus={autoFocus}
104
+ label={"Latitude"}
105
+ type="number"
106
+ disabled={disabled}
107
+ endAdornment={canClear ? (
108
+ <IconButton onClick={handleClear}>
109
+ <CloseIcon />
110
+ </IconButton>
111
+ ) : undefined}
112
+ error={shouldShowError && Boolean(resolvedError)}
113
+ />
114
+ <TextField
115
+ size={size}
116
+ value={longitude}
117
+ onChange={(event) => updateGeoPoint(latitude, event.target.value)}
118
+ label={"Longitude"}
119
+ type="number"
120
+ disabled={disabled}
121
+ error={shouldShowError && Boolean(resolvedError)}
122
+ />
123
+ </div>
124
+ {value && !resolvedError && (
125
+ <div className="text-xs text-text-secondary dark:text-text-secondary-dark font-mono">
126
+ {formatGeoPoint(value)}
127
+ </div>
128
+ )}
129
+ </div>
130
+ </PropertyIdCopyTooltip>
131
+
132
+ <FieldHelperText includeDescription={includeDescription}
133
+ showError={shouldShowError}
134
+ error={resolvedError}
135
+ disabled={disabled}
136
+ property={property}/>
137
+ </>
138
+ );
139
+ }
@@ -11,6 +11,7 @@ export { StorageUploadFieldBinding } from "./field_bindings/StorageUploadFieldBi
11
11
  export { TextFieldBinding } from "./field_bindings/TextFieldBinding";
12
12
  export { SwitchFieldBinding } from "./field_bindings/SwitchFieldBinding";
13
13
  export { DateTimeFieldBinding } from "./field_bindings/DateTimeFieldBinding";
14
+ export { GeopointFieldBinding } from "./field_bindings/GeopointFieldBinding";
14
15
  export { ReferenceFieldBinding } from "./field_bindings/ReferenceFieldBinding";
15
16
  export { ReferenceAsStringFieldBinding } from "./field_bindings/ReferenceAsStringFieldBinding";
16
17
  export { MapFieldBinding } from "./field_bindings/MapFieldBinding";
@@ -43,6 +43,7 @@ export type SaveEntityWithCallbacksProps<M extends Record<string, any>> =
43
43
  export async function saveEntityWithCallbacks<M extends Record<string, any>, USER extends User>({
44
44
  collection,
45
45
  path,
46
+ pathSegments,
46
47
  entityId,
47
48
  values,
48
49
  previousValues,
@@ -103,6 +104,7 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, USE
103
104
  return dataSource.saveEntity({
104
105
  collection,
105
106
  path: resolvedPath,
107
+ pathSegments: pathSegments ?? resolvedPath.split("/"),
106
108
  entityId,
107
109
  values: updatedValues,
108
110
  previousValues,
@@ -9,6 +9,11 @@ import { useFireCMSContext } from "../useFireCMSContext";
9
9
  */
10
10
  export interface EntityFetchProps<M extends Record<string, any>, USER extends User = User> {
11
11
  path: string;
12
+ /**
13
+ * `path` split at its real segment boundaries. Forwarded to the datasource so a parent
14
+ * entity id containing "/" stays unambiguous. Defaults to splitting the resolved path.
15
+ */
16
+ pathSegments?: string[];
12
17
  entityId?: string;
13
18
  databaseId?: string;
14
19
  collection: EntityCollection<M, USER>;
@@ -39,6 +44,7 @@ const CACHE: Record<string, Entity<any> | undefined> = {};
39
44
  export function useEntityFetch<M extends Record<string, any>, USER extends User>(
40
45
  {
41
46
  path: inputPath,
47
+ pathSegments: inputPathSegments,
42
48
  entityId,
43
49
  collection,
44
50
  databaseId,
@@ -49,6 +55,7 @@ export function useEntityFetch<M extends Record<string, any>, USER extends User>
49
55
  const navigationController = useNavigationController();
50
56
 
51
57
  const path = navigationController.resolveIdsFrom(inputPath);
58
+ const pathSegments = inputPathSegments ?? path.split("/");
52
59
 
53
60
  const context: FireCMSContext<USER> = useFireCMSContext();
54
61
 
@@ -97,6 +104,7 @@ export function useEntityFetch<M extends Record<string, any>, USER extends User>
97
104
  if (dataSource.listenEntity) {
98
105
  return dataSource.listenEntity<M>({
99
106
  path,
107
+ pathSegments,
100
108
  entityId,
101
109
  databaseId,
102
110
  collection,
@@ -106,6 +114,7 @@ export function useEntityFetch<M extends Record<string, any>, USER extends User>
106
114
  } else {
107
115
  dataSource.fetchEntity<M>({
108
116
  path,
117
+ pathSegments,
109
118
  entityId,
110
119
  databaseId,
111
120
  collection
@@ -414,7 +414,11 @@ export function useBuildNavigationController<EC extends EntityCollection, USER e
414
414
  const baseCollection = getCollectionByPathOrId(removeInitialAndTrailingSlashes(idOrPath), collections);
415
415
 
416
416
  const userOverride = includeUserOverride ? userConfigPersistence?.getCollectionConfig(idOrPath) : undefined;
417
- const overriddenCollection = baseCollection ? mergeDeep(baseCollection, userOverride ?? {}) : undefined;
417
+ let overriddenCollection = baseCollection;
418
+ if (baseCollection && userOverride) {
419
+ const { properties, ...rest } = userOverride;
420
+ overriddenCollection = mergeDeep(baseCollection, rest);
421
+ }
418
422
 
419
423
  let result: Partial<EntityCollection> | undefined = overriddenCollection;
420
424
 
@@ -74,6 +74,10 @@ export function useValidateAuthenticator<USER extends User = any>
74
74
 
75
75
  if (authenticator instanceof Function && delegateUser && !equal(checkedUserRef.current?.uid, delegateUser.uid)) {
76
76
  setAuthLoading(true);
77
+ // Reset the error of any previous authentication attempt. Otherwise, a
78
+ // rejected user would keep `canAccessMainView` to false for every user
79
+ // logging in afterwards, locking them out of the CMS until a page reload.
80
+ setNotAllowedError(false);
77
81
  try {
78
82
  const allowed = await authenticator({
79
83
  user: delegateUser,
@@ -8,6 +8,7 @@ import { fr } from "../locales/fr";
8
8
  import { it } from "../locales/it";
9
9
  import { hi } from "../locales/hi";
10
10
  import { pt } from "../locales/pt";
11
+ import { pl } from "../locales/pl";
11
12
  import { FireCMSTranslations } from "../types/translations";
12
13
 
13
14
  const FIRECMS_NS = "firecms_core";
@@ -139,6 +140,7 @@ function buildResources(
139
140
  it: { [FIRECMS_NS]: { ...it } },
140
141
  hi: { [FIRECMS_NS]: { ...hi } },
141
142
  pt: { [FIRECMS_NS]: { ...pt } },
143
+ pl: { [FIRECMS_NS]: { ...pl } },
142
144
  };
143
145
 
144
146
  if (!translations) return resources;
@@ -55,6 +55,7 @@ export function useBuildDataSource({
55
55
  */
56
56
  fetchCollection: useCallback(<M extends Record<string, any>>({
57
57
  path,
58
+ pathSegments,
58
59
  collection,
59
60
  filter,
60
61
  limit,
@@ -67,6 +68,7 @@ export function useBuildDataSource({
67
68
  const usedDelegate = collection?.overrides?.dataSourceDelegate ?? delegate;
68
69
  return usedDelegate.fetchCollection<M>({
69
70
  path,
71
+ pathSegments,
70
72
  filter,
71
73
  limit,
72
74
  startAfter,
@@ -97,6 +99,7 @@ export function useBuildDataSource({
97
99
  ? useCallback(<M extends Record<string, any>>(
98
100
  {
99
101
  path,
102
+ pathSegments,
100
103
  collection: collectionProp,
101
104
  filter,
102
105
  limit,
@@ -117,6 +120,7 @@ export function useBuildDataSource({
117
120
 
118
121
  return usedDelegate.listenCollection<M>({
119
122
  path,
123
+ pathSegments,
120
124
  filter,
121
125
  limit,
122
126
  startAfter,
@@ -139,6 +143,7 @@ export function useBuildDataSource({
139
143
  */
140
144
  fetchEntity: useCallback(<M extends Record<string, any>>({
141
145
  path,
146
+ pathSegments,
142
147
  entityId,
143
148
  collection
144
149
  }: FetchEntityProps<M>
@@ -146,6 +151,7 @@ export function useBuildDataSource({
146
151
  const usedDelegate = collection?.overrides?.dataSourceDelegate ?? delegate;
147
152
  return usedDelegate.fetchEntity({
148
153
  path,
154
+ pathSegments,
149
155
  entityId,
150
156
  collection
151
157
  });
@@ -165,6 +171,7 @@ export function useBuildDataSource({
165
171
  ? useCallback(<M extends Record<string, any>>(
166
172
  {
167
173
  path,
174
+ pathSegments,
168
175
  entityId,
169
176
  collection,
170
177
  onUpdate,
@@ -177,6 +184,7 @@ export function useBuildDataSource({
177
184
 
178
185
  return usedDelegate.listenEntity<M>({
179
186
  path,
187
+ pathSegments,
180
188
  entityId,
181
189
  onUpdate,
182
190
  onError,
@@ -198,6 +206,7 @@ export function useBuildDataSource({
198
206
  saveEntity: useCallback(async <M extends Record<string, any>>(
199
207
  {
200
208
  path,
209
+ pathSegments,
201
210
  entityId,
202
211
  values,
203
212
  collection: collectionProp,
@@ -244,6 +253,7 @@ export function useBuildDataSource({
244
253
  try {
245
254
  const entities = await usedDelegate.fetchCollection({
246
255
  path,
256
+ pathSegments,
247
257
  orderBy: orderProperty,
248
258
  order: "asc",
249
259
  limit: 1,
@@ -270,6 +280,7 @@ export function useBuildDataSource({
270
280
 
271
281
  return usedDelegate.saveEntity({
272
282
  path,
283
+ pathSegments,
273
284
  collection,
274
285
  entityId,
275
286
  values: finalValues,
@@ -13,6 +13,7 @@ import {
13
13
  import { getNavigationEntriesFromPath, NavigationViewInternal } from "../util/navigation_from_path";
14
14
  import { useLocation } from "react-router-dom";
15
15
  import {
16
+ encodeEntityId,
16
17
  removeInitialAndTrailingSlashes,
17
18
  resolveCollection,
18
19
  resolveDefaultSelectedView,
@@ -223,12 +224,14 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
223
224
  let sidePanel: EntitySidePanelProps<any> | undefined = undefined;
224
225
  let lastCollectionPath = "";
225
226
  let lastCollectionId: string | undefined = undefined;
227
+ let lastCollectionSegments: string[] | undefined = undefined;
226
228
  for (let i = 0; i < navigationViewsForPath.length; i++) {
227
229
  const navigationEntry = navigationViewsForPath[i];
228
230
 
229
231
  if (navigationEntry.type === "collection") {
230
232
  lastCollectionPath = navigationEntry.path;
231
233
  lastCollectionId = navigationEntry.collection.id;
234
+ lastCollectionSegments = navigationEntry.pathSegments;
232
235
  }
233
236
 
234
237
  const previousEntry = navigationViewsForPath[i - 1];
@@ -236,6 +239,7 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
236
239
  sidePanel = {
237
240
  path: navigationEntry.path,
238
241
  fullIdPath: navigationEntry.fullIdPath,
242
+ pathSegments: navigationEntry.pathSegments,
239
243
  entityId: navigationEntry.entityId,
240
244
  copy: false,
241
245
  width: navigationEntry.parentCollection?.sideDialogWidth
@@ -258,6 +262,9 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
258
262
  sidePanel = {
259
263
  path: lastCollectionPath,
260
264
  fullIdPath: lastCollectionId,
265
+ // A new entity still needs unambiguous segments: it may be created inside a
266
+ // subcollection whose parent id contains "/".
267
+ pathSegments: lastCollectionSegments,
261
268
  copy: false
262
269
  }
263
270
  }
@@ -277,7 +284,7 @@ const propsToSidePanel = (props: EntitySidePanelProps,
277
284
  const collectionPath = removeInitialAndTrailingSlashes(props.path);
278
285
 
279
286
  const urlPath = props.entityId
280
- ? buildUrlCollectionPath(`${collectionPath}/${props.entityId}${props.selectedTab ? "/" + props.selectedTab : ""}${locationSearch}#${SIDE_URL_HASH}`)
287
+ ? buildUrlCollectionPath(`${collectionPath}/${encodeEntityId(props.entityId)}${props.selectedTab ? "/" + props.selectedTab : ""}${locationSearch}#${SIDE_URL_HASH}`)
281
288
  : buildUrlCollectionPath(`${collectionPath}${locationSearch}#${NEW_URL_HASH}`);
282
289
 
283
290
  const resolvedPanelProps: EntitySidePanelProps<any> = {
package/src/locales/de.ts CHANGED
@@ -146,8 +146,8 @@ export const de: FireCMSTranslations = {
146
146
  // ─── Error states ─────────────────────────────────────────────
147
147
  error: "Fehler",
148
148
  error_uploading_file: "Fehler beim Hochladen der Datei",
149
- error_deleting: "Fehler beim Löschen",
150
- error_before_delete: "Fehler vor dem Löschen",
149
+ error_deleting: "Fehler beim Löschen: {{message}}",
150
+ error_before_delete: "Fehler vor dem Löschen: {{message}}",
151
151
  error_updating_asset: "Fehler beim Aktualisieren des Assets",
152
152
  error_deleting_asset: "Fehler beim Löschen des Assets",
153
153
  error_firestore_index: "Für diese Abfrage ist ein Firestore-Index erforderlich.",
@@ -389,6 +389,7 @@ export const de: FireCMSTranslations = {
389
389
  download: "Herunterladen",
390
390
  large_number_of_documents: "Diese Sammlung hat eine große Anzahl von Dokumenten ({{count}}).",
391
391
  include_undefined_values: "Undefinierte Werte einschließen",
392
+ export_apply_filter_sort: "Nur Ergebnisse exportieren, die dem aktuellen Filter/der aktuellen Sortierung entsprechen",
392
393
  submit: "Einreichen",
393
394
 
394
395
  no_filterable_properties: "Keine filterbaren Eigenschaften verfügbar",
@@ -437,8 +438,8 @@ export const de: FireCMSTranslations = {
437
438
  cms_users: "CMS-Benutzer",
438
439
  roles_menu: "Rollen",
439
440
  project_settings: "Projekteinstellungen",
440
- firestore_explorer: "Firestore-Explorer",
441
- explore_your_firestore_data: "Deine Firestore-Daten durchsuchen",
441
+ firestore_manager: "Firestore-Manager",
442
+ manage_your_firestore_data: "Deine Firestore-Daten verwalten",
442
443
 
443
444
  // ─── FireCMS Cloud Login ──────────────────────────────────────
444
445
  build_admin_panel_in_minutes: "Erstellen Sie Ihr Firebase Admin Panel in wenigen Minuten",
@@ -514,10 +515,18 @@ export const de: FireCMSTranslations = {
514
515
  auto_setup_collections_button: "Sammlungen automatisch einrichten",
515
516
  auto_setup_collections_title: "Sammlungen automatisch einrichten?",
516
517
  auto_setup_collections_desc: "Dadurch werden automatisch Sammlungskonfigurationen für Sammlungen erstellt, die noch <b>NICHT</b> zugeordnet sind.",
517
- this_can_take_a_minute: "Dies kann ein bis zwei Minuten dauern",
518
+ setting_up_collections: "Sammlungen werden eingerichtet",
519
+ setting_up_collection: "{{name}} wird eingerichtet",
518
520
  no_collections_found_to_setup: "Keine einzurichtenden Sammlungen gefunden",
519
521
  collections_have_been_setup: "Sammlungen wurden automatisch eingerichtet",
520
522
  error_setting_up_collections: "Fehler beim automatischen Einrichten der Sammlungen",
523
+ setup_collections_title: "Set up collections",
524
+ setup_collections_select_desc: "Select which collections to automatically set up:",
525
+ select_all: "Select all",
526
+ deselect_all: "Deselect all",
527
+ setup_collections_confirm: "Set up ({{count}})",
528
+ collection_setup_success: "{{name}} has been set up",
529
+ go_to_collection: "Go to collection",
521
530
  add_your: "Fügen Sie Ihre",
522
531
  database_collections: "Datenbanksammlungen",
523
532
  to_firecms: "zu FireCMS hinzu",
@@ -578,6 +587,10 @@ export const de: FireCMSTranslations = {
578
587
  order_property_not_found: "Eigenschaft \"{{property}}\" existiert nicht oder ist keine Zahlen-Eigenschaft. Bitte wählen Sie eine gültige Eigenschaft oder löschen Sie die Auswahl.",
579
588
  no_number_properties: "Keine Zahlen-Eigenschaften gefunden. Fügen Sie eine Zahlen-Eigenschaft hinzu, um die Sortierung zu aktivieren.",
580
589
  order_property_description: "Wählen Sie eine Zahlen-Eigenschaft, um die Reihenfolge der Elemente beizubehalten",
590
+ image_property: "Bild-Eigenschaft",
591
+ image_property_not_found: "Eigenschaft \"{{property}}\" existiert nicht oder ist keine Bild-Eigenschaft. Bitte wählen Sie eine gültige Eigenschaft oder löschen Sie die Auswahl.",
592
+ no_image_properties: "Keine Bild-Eigenschaften gefunden. Fügen Sie eine Speicher- oder Bild-URL-Eigenschaft hinzu, um sie als Vorschaubild zu verwenden.",
593
+ image_property_description: "Wählen Sie die Eigenschaft, die als Vorschaubild in den Ansichten Karten und Kanban verwendet wird. Wenn nicht festgelegt, wird automatisch die erste passende Bild-Eigenschaft verwendet.",
581
594
  display_settings: "Anzeigeeinstellungen",
582
595
  default_row_size: "Standard-Zeilengröße",
583
596
  side_dialog_width: "Seitendialog-Breite",
package/src/locales/en.ts CHANGED
@@ -154,8 +154,8 @@ export const en: FireCMSTranslations = {
154
154
  // ─── Error states ─────────────────────────────────────────────
155
155
  error: "Error",
156
156
  error_uploading_file: "Error uploading file",
157
- error_deleting: "Error deleting",
158
- error_before_delete: "Error before delete",
157
+ error_deleting: "Error deleting: {{message}}",
158
+ error_before_delete: "Error before delete: {{message}}",
159
159
  error_updating_asset: "Error updating asset",
160
160
  error_deleting_asset: "Error deleting asset",
161
161
  error_firestore_index: "A Firestore index is required for this query.",
@@ -397,6 +397,7 @@ export const en: FireCMSTranslations = {
397
397
  download: "Download",
398
398
  large_number_of_documents: "This collections has a large number of documents ({{count}}).",
399
399
  include_undefined_values: "Include undefined values",
400
+ export_apply_filter_sort: "Only export results matching the current filter/sort",
400
401
  submit: "Submit",
401
402
 
402
403
  no_filterable_properties: "No filterable properties available",
@@ -445,8 +446,8 @@ export const en: FireCMSTranslations = {
445
446
  cms_users: "CMS Users",
446
447
  roles_menu: "Roles",
447
448
  project_settings: "Project settings",
448
- firestore_explorer: "Firestore Explorer",
449
- explore_your_firestore_data: "Explore your Firestore data",
449
+ firestore_manager: "Firestore Manager",
450
+ manage_your_firestore_data: "Manage your Firestore data",
450
451
 
451
452
  // ─── FireCMS Cloud Login ──────────────────────────────────────
452
453
  build_admin_panel_in_minutes: "Build Your Firebase Admin Panel in Minutes",
@@ -522,10 +523,18 @@ export const en: FireCMSTranslations = {
522
523
  auto_setup_collections_button: "Automatically set up collections",
523
524
  auto_setup_collections_title: "Automatically set up collections?",
524
525
  auto_setup_collections_desc: "This will automatically create collection configs for collections that are <b>NOT</b> already mapped",
525
- this_can_take_a_minute: "This can take a minute or two",
526
+ setting_up_collections: "Setting up collections",
527
+ setting_up_collection: "Setting up {{name}}",
526
528
  no_collections_found_to_setup: "No collections found to setup.",
527
529
  collections_have_been_setup: "Collections have been automatically setup.",
528
530
  error_setting_up_collections: "Error automatically setting up collections",
531
+ setup_collections_title: "Set up collections",
532
+ setup_collections_select_desc: "Select which collections to automatically set up:",
533
+ select_all: "Select all",
534
+ deselect_all: "Deselect all",
535
+ setup_collections_confirm: "Set up ({{count}})",
536
+ collection_setup_success: "{{name}} has been set up",
537
+ go_to_collection: "Go to collection",
529
538
 
530
539
  // --- Home Suggestions ---
531
540
  add_your: "Add your",
@@ -590,6 +599,10 @@ export const en: FireCMSTranslations = {
590
599
  order_property_not_found: "Property \"{{property}}\" does not exist or is not a number property. Please select a valid property or clear the selection.",
591
600
  no_number_properties: "No number properties found. Add a number property to enable ordering.",
592
601
  order_property_description: "Select a number property to persist the order of items",
602
+ image_property: "Image Property",
603
+ image_property_not_found: "Property \"{{property}}\" does not exist or is not an image property. Please select a valid property or clear the selection.",
604
+ no_image_properties: "No image properties found. Add a storage or URL image property to use as a thumbnail.",
605
+ image_property_description: "Select the property used as the thumbnail image in Cards and Kanban view modes. If not set, the first matching image property will be used automatically.",
593
606
  display_settings: "Display settings",
594
607
  default_row_size: "Default row size",
595
608
  side_dialog_width: "Side dialog width",
package/src/locales/es.ts CHANGED
@@ -152,8 +152,8 @@ export const es: FireCMSTranslations = {
152
152
  // ─── Error states ─────────────────────────────────────────────
153
153
  error: "Error",
154
154
  error_uploading_file: "Error al subir archivo",
155
- error_deleting: "Error al eliminar",
156
- error_before_delete: "Error antes de eliminar",
155
+ error_deleting: "Error al eliminar: {{message}}",
156
+ error_before_delete: "Error antes de eliminar: {{message}}",
157
157
  error_updating_asset: "Error al actualizar recurso",
158
158
  error_deleting_asset: "Error al eliminar recurso",
159
159
  error_firestore_index: "Se requiere un índice de Firestore para esta consulta.",
@@ -397,6 +397,7 @@ export const es: FireCMSTranslations = {
397
397
  download: "Descargar",
398
398
  large_number_of_documents: "Esta colección posee un gran número de documentos ({{count}}).",
399
399
  include_undefined_values: "Incluir valores omitidos (undefined)",
400
+ export_apply_filter_sort: "Exportar solo los resultados que coinciden con el filtro/orden actual",
400
401
  submit: "Enviar",
401
402
 
402
403
  no_filterable_properties: "No hay propiedades filtrables disponibles",
@@ -445,8 +446,8 @@ export const es: FireCMSTranslations = {
445
446
  cms_users: "Usuarios del CMS",
446
447
  roles_menu: "Roles",
447
448
  project_settings: "Ajustes del proyecto",
448
- firestore_explorer: "Explorador de Firestore",
449
- explore_your_firestore_data: "Explora tus datos de Firestore",
449
+ firestore_manager: "Gestor de Firestore",
450
+ manage_your_firestore_data: "Gestiona tus datos de Firestore",
450
451
 
451
452
  // ─── FireCMS Cloud Login ──────────────────────────────────────
452
453
  build_admin_panel_in_minutes: "Crea tu panel de administración de Firebase en minutos",
@@ -522,10 +523,18 @@ export const es: FireCMSTranslations = {
522
523
  auto_setup_collections_button: "Configurar colecciones automáticamente",
523
524
  auto_setup_collections_title: "¿Configurar colecciones automáticamente?",
524
525
  auto_setup_collections_desc: "Esto creará automáticamente la configuración de las colecciones que <b>NO</b> estén mapeadas",
525
- this_can_take_a_minute: "Esto puede tardar un minuto o dos",
526
+ setting_up_collections: "Configurando colecciones",
527
+ setting_up_collection: "Configurando {{name}}",
526
528
  no_collections_found_to_setup: "No se encontraron colecciones para configurar",
527
529
  collections_have_been_setup: "¡Tus colecciones han sido configuradas!",
528
530
  error_setting_up_collections: "Error al configurar colecciones",
531
+ setup_collections_title: "Set up collections",
532
+ setup_collections_select_desc: "Select which collections to automatically set up:",
533
+ select_all: "Select all",
534
+ deselect_all: "Deselect all",
535
+ setup_collections_confirm: "Set up ({{count}})",
536
+ collection_setup_success: "{{name}} has been set up",
537
+ go_to_collection: "Go to collection",
529
538
 
530
539
  // --- Home Suggestions ---
531
540
  add_your: "Añade tus",
@@ -590,6 +599,10 @@ export const es: FireCMSTranslations = {
590
599
  order_property_not_found: "La propiedad \"{{property}}\" no existe o no es una propiedad numérica. Selecciona una propiedad válida o borra la selección.",
591
600
  no_number_properties: "No se encontraron propiedades numéricas. Agrega una propiedad numérica para habilitar el ordenamiento.",
592
601
  order_property_description: "Selecciona una propiedad numérica para mantener el orden de los elementos",
602
+ image_property: "Propiedad de imagen",
603
+ image_property_not_found: "La propiedad \"{{property}}\" no existe o no es una propiedad de imagen. Selecciona una propiedad válida o borra la selección.",
604
+ no_image_properties: "No se encontraron propiedades de imagen. Agrega una propiedad de almacenamiento o URL de imagen para usarla como miniatura.",
605
+ image_property_description: "Selecciona la propiedad usada como miniatura en las vistas de Tarjetas y Kanban. Si no se establece, se usará automáticamente la primera propiedad de imagen que coincida.",
593
606
  display_settings: "Configuración de visualización",
594
607
  default_row_size: "Tamaño de fila predeterminado",
595
608
  side_dialog_width: "Ancho del diálogo lateral",
package/src/locales/fr.ts CHANGED
@@ -146,8 +146,8 @@ export const fr: FireCMSTranslations = {
146
146
  // ─── Error states ─────────────────────────────────────────────
147
147
  error: "Erreur",
148
148
  error_uploading_file: "Erreur lors du téléchargement du fichier",
149
- error_deleting: "Erreur lors de la suppression",
150
- error_before_delete: "Erreur avant la suppression",
149
+ error_deleting: "Erreur lors de la suppression: {{message}}",
150
+ error_before_delete: "Erreur avant la suppression: {{message}}",
151
151
  error_updating_asset: "Erreur lors de la mise à jour de l'actif",
152
152
  error_deleting_asset: "Erreur lors de la suppression de l'actif",
153
153
  error_firestore_index: "Un index Firestore est requis pour cette requête.",
@@ -389,6 +389,7 @@ export const fr: FireCMSTranslations = {
389
389
  download: "Télécharger",
390
390
  large_number_of_documents: "Cette collection contient un grand nombre de documents ({{count}}).",
391
391
  include_undefined_values: "Inclure les valeurs non définies",
392
+ export_apply_filter_sort: "N'exporter que les résultats correspondant au filtre/tri actuel",
392
393
  submit: "Soumettre",
393
394
 
394
395
  no_filterable_properties: "Aucune propriété filtrable disponible",
@@ -437,8 +438,8 @@ export const fr: FireCMSTranslations = {
437
438
  cms_users: "Utilisateurs du CMS",
438
439
  roles_menu: "Rôles",
439
440
  project_settings: "Paramètres du projet",
440
- firestore_explorer: "Explorateur Firestore",
441
- explore_your_firestore_data: "Explorez vos données Firestore",
441
+ firestore_manager: "Gestionnaire Firestore",
442
+ manage_your_firestore_data: "Gérez vos données Firestore",
442
443
 
443
444
  // ─── FireCMS Cloud Login ──────────────────────────────────────
444
445
  build_admin_panel_in_minutes: "Créez votre panneau d'administration Firebase en quelques minutes",
@@ -514,10 +515,18 @@ export const fr: FireCMSTranslations = {
514
515
  auto_setup_collections_button: "Configurer les collections automatiquement",
515
516
  auto_setup_collections_title: "Configurer les collections automatiquement ?",
516
517
  auto_setup_collections_desc: "Cela créera automatiquement des configurations de collection pour les collections qui ne sont <b>PAS</b> déjà mappées",
517
- this_can_take_a_minute: "Cela peut prendre une minute",
518
+ setting_up_collections: "Configuration des collections",
519
+ setting_up_collection: "Configuration de {{name}}",
518
520
  no_collections_found_to_setup: "Aucune collection à configurer trouvée",
519
521
  collections_have_been_setup: "Les collections ont été configurées",
520
522
  error_setting_up_collections: "Erreur lors de la configuration des collections",
523
+ setup_collections_title: "Set up collections",
524
+ setup_collections_select_desc: "Select which collections to automatically set up:",
525
+ select_all: "Select all",
526
+ deselect_all: "Deselect all",
527
+ setup_collections_confirm: "Set up ({{count}})",
528
+ collection_setup_success: "{{name}} has been set up",
529
+ go_to_collection: "Go to collection",
521
530
  add_your: "Ajoutez vos",
522
531
  database_collections: "collections de base de données",
523
532
  to_firecms: "à FireCMS",
@@ -578,6 +587,10 @@ export const fr: FireCMSTranslations = {
578
587
  order_property_not_found: "La propriété \"{{property}}\" n'existe pas ou n'est pas une propriété numérique. Veuillez sélectionner une propriété valide ou effacer la sélection.",
579
588
  no_number_properties: "Aucune propriété numérique trouvée. Ajoutez une propriété numérique pour activer le tri.",
580
589
  order_property_description: "Sélectionnez une propriété numérique pour conserver l'ordre des éléments",
590
+ image_property: "Propriété d'image",
591
+ image_property_not_found: "La propriété \"{{property}}\" n'existe pas ou n'est pas une propriété d'image. Veuillez sélectionner une propriété valide ou effacer la sélection.",
592
+ no_image_properties: "Aucune propriété d'image trouvée. Ajoutez une propriété de stockage ou d'URL d'image à utiliser comme miniature.",
593
+ image_property_description: "Sélectionnez la propriété utilisée comme miniature dans les vues Cartes et Kanban. Si elle n'est pas définie, la première propriété d'image correspondante sera utilisée automatiquement.",
581
594
  display_settings: "Paramètres d'affichage",
582
595
  default_row_size: "Taille de ligne par défaut",
583
596
  side_dialog_width: "Largeur du dialogue latéral",