@firecms/core 3.2.0-canary.9c3d298 → 3.3.0-canary.451aa49

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 (67) hide show
  1. package/dist/components/VirtualTable/VirtualTableHeader.d.ts +1 -0
  2. package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  3. package/dist/components/VirtualTable/VirtualTableProps.d.ts +6 -1
  4. package/dist/components/VirtualTable/types.d.ts +1 -0
  5. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  6. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.es.js +20186 -19539
  9. package/dist/index.es.js.map +1 -1
  10. package/dist/index.umd.js +24292 -23645
  11. package/dist/index.umd.js.map +1 -1
  12. package/dist/types/collections.d.ts +38 -0
  13. package/dist/types/properties.d.ts +9 -8
  14. package/dist/types/translations.d.ts +23 -0
  15. package/dist/util/index.d.ts +1 -0
  16. package/dist/util/lazy_eager.d.ts +7 -0
  17. package/dist/util/objects.d.ts +1 -0
  18. package/package.json +4 -4
  19. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +9 -3
  20. package/src/components/EntityCollectionView/EntityCollectionView.tsx +3 -5
  21. package/src/components/EntityJsonPreview.tsx +2 -1
  22. package/src/components/ErrorBoundary.tsx +3 -3
  23. package/src/components/VirtualTable/VirtualTable.tsx +5 -3
  24. package/src/components/VirtualTable/VirtualTableHeader.tsx +9 -8
  25. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +8 -3
  26. package/src/components/VirtualTable/VirtualTableProps.tsx +7 -1
  27. package/src/components/VirtualTable/types.tsx +1 -0
  28. package/src/core/DrawerNavigationGroup.tsx +1 -1
  29. package/src/core/EntityEditView.tsx +50 -5
  30. package/src/core/EntitySidePanel.tsx +2 -1
  31. package/src/core/field_configs.tsx +4 -2
  32. package/src/form/EntityForm.tsx +64 -4
  33. package/src/form/PropertyFieldBinding.tsx +4 -3
  34. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +18 -5
  35. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +18 -5
  36. package/src/form/field_bindings/BlockFieldBinding.tsx +21 -7
  37. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
  38. package/src/form/field_bindings/KeyValueFieldBinding.tsx +23 -6
  39. package/src/form/field_bindings/MapFieldBinding.tsx +23 -8
  40. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +43 -20
  41. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +15 -1
  42. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +25 -11
  43. package/src/form/field_bindings/ReferenceFieldBinding.tsx +25 -11
  44. package/src/form/field_bindings/RepeatFieldBinding.tsx +18 -5
  45. package/src/form/field_bindings/SelectFieldBinding.tsx +7 -5
  46. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +24 -7
  47. package/src/form/field_bindings/SwitchFieldBinding.tsx +31 -14
  48. package/src/form/field_bindings/TextFieldBinding.tsx +10 -7
  49. package/src/form/field_bindings/UserSelectFieldBinding.tsx +7 -5
  50. package/src/index.ts +1 -0
  51. package/src/locales/de.ts +28 -1
  52. package/src/locales/en.ts +27 -0
  53. package/src/locales/es.ts +28 -1
  54. package/src/locales/fr.ts +28 -1
  55. package/src/locales/hi.ts +28 -1
  56. package/src/locales/it.ts +28 -1
  57. package/src/locales/pt.ts +28 -1
  58. package/src/preview/PropertyPreview.tsx +3 -2
  59. package/src/preview/components/ReferencePreview.tsx +2 -1
  60. package/src/preview/property_previews/MapPropertyPreview.tsx +49 -27
  61. package/src/routes/FireCMSRoute.tsx +63 -54
  62. package/src/types/collections.ts +40 -0
  63. package/src/types/properties.ts +11 -10
  64. package/src/types/translations.ts +27 -0
  65. package/src/util/index.ts +1 -0
  66. package/src/util/lazy_eager.tsx +33 -0
  67. package/src/util/objects.ts +15 -0
@@ -38,7 +38,9 @@ import {
38
38
  fieldBackgroundDisabledMixin,
39
39
  fieldBackgroundHoverMixin,
40
40
  fieldBackgroundMixin,
41
- Typography
41
+ Typography,
42
+ IconButton,
43
+ CloseIcon
42
44
  } from "@firecms/ui";
43
45
  import { useClearRestoreValue } from "../useClearRestoreValue";
44
46
  import { useTranslation } from "../../hooks/useTranslation";
@@ -110,12 +112,27 @@ export function StorageUploadFieldBinding({
110
112
  <>
111
113
 
112
114
  {!minimalistView &&
113
- <LabelWithIconAndTooltip
114
- propertyKey={propertyKey}
115
- icon={getIconForProperty(property, "small")}
116
- required={property.validation?.required}
117
- title={property.name}
118
- className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"} />}
115
+ <div className="flex items-center w-full">
116
+ <LabelWithIconAndTooltip
117
+ propertyKey={propertyKey}
118
+ icon={getIconForProperty(property, "small")}
119
+ required={property.validation?.required}
120
+ title={property.name}
121
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"} />
122
+ <div className="flex-grow"/>
123
+ {(property.nullable || property.clearable) && !disabled && (
124
+ <IconButton
125
+ size="small"
126
+ onClick={(e) => {
127
+ e.stopPropagation();
128
+ e.preventDefault();
129
+ setValue(null);
130
+ }}
131
+ >
132
+ <CloseIcon size={"small"}/>
133
+ </IconButton>
134
+ )}
135
+ </div>}
119
136
 
120
137
  <StorageUpload
121
138
  value={internalValue}
@@ -3,7 +3,7 @@ import React from "react";
3
3
  import { FieldProps } from "../../types";
4
4
  import { getIconForProperty } from "../../util";
5
5
  import { FieldHelperText, LabelWithIcon } from "../components";
6
- import { BooleanSwitchWithLabel } from "@firecms/ui";
6
+ import { BooleanSwitchWithLabel, IconButton, CloseIcon } from "@firecms/ui";
7
7
  import { useClearRestoreValue } from "../useClearRestoreValue";
8
8
  import { PropertyIdCopyTooltip } from "../../components";
9
9
 
@@ -39,19 +39,36 @@ export const SwitchFieldBinding = function SwitchFieldBinding({
39
39
  <>
40
40
 
41
41
  <PropertyIdCopyTooltip propertyKey={propertyKey}>
42
- <BooleanSwitchWithLabel
43
- value={value}
44
- onValueChange={(v) => setValue(v)}
45
- error={showError}
46
- className={property.widthPercentage !== undefined ? "mt-8" : undefined}
47
- label={<LabelWithIcon
48
- icon={getIconForProperty(property, "small")}
49
- required={property.validation?.required}
50
- title={property.name}/>}
51
- disabled={disabled}
52
- autoFocus={autoFocus}
53
- size={size}
54
- />
42
+ <div className="flex items-center">
43
+ <BooleanSwitchWithLabel
44
+ value={value}
45
+ onValueChange={(v) => setValue(v)}
46
+ error={showError}
47
+ className={property.widthPercentage !== undefined ? "mt-8" : undefined}
48
+ label={<LabelWithIcon
49
+ icon={getIconForProperty(property, "small")}
50
+ required={property.validation?.required}
51
+ title={property.name}/>}
52
+ disabled={disabled}
53
+ autoFocus={autoFocus}
54
+ size={size}
55
+ switchAdornment={
56
+ (property.nullable || property.clearable) && !disabled && value !== null && (
57
+ <IconButton
58
+ size="small"
59
+ onClick={(e) => {
60
+ e.stopPropagation();
61
+ e.preventDefault();
62
+ setValue(null);
63
+ }}
64
+ className="mr-2"
65
+ >
66
+ <CloseIcon size={"small"}/>
67
+ </IconButton>
68
+ )
69
+ }
70
+ />
71
+ </div>
55
72
  </PropertyIdCopyTooltip>
56
73
 
57
74
  <FieldHelperText includeDescription={includeDescription}
@@ -100,10 +100,10 @@ export function TextFieldBinding<T extends string | number>({
100
100
  showError && error ? "text-red-500 dark:text-red-600" : ""
101
101
  )}
102
102
  />
103
- {property.clearable && (
103
+ {(property.nullable || property.clearable) && value !== null && value !== undefined && (
104
104
  <div className="flex flex-row justify-center items-center absolute h-full right-0 top-0 mr-4">
105
- <IconButton onClick={handleClearClick}>
106
- <CloseIcon />
105
+ <IconButton size="small" onClick={handleClearClick}>
106
+ <CloseIcon size="small" />
107
107
  </IconButton>
108
108
  </div>
109
109
  )}
@@ -119,10 +119,13 @@ export function TextFieldBinding<T extends string | number>({
119
119
  type={inputType}
120
120
  disabled={disabled}
121
121
  endAdornment={
122
- property.clearable && <IconButton
123
- onClick={handleClearClick}>
124
- <CloseIcon />
125
- </IconButton>
122
+ (property.nullable || property.clearable) && value !== null && value !== undefined ? (
123
+ <IconButton
124
+ size="small"
125
+ onClick={handleClearClick}>
126
+ <CloseIcon size="small" />
127
+ </IconButton>
128
+ ) : undefined
126
129
  }
127
130
  error={showError ? error : undefined}
128
131
  inputClassName={error ? "text-red-500 dark:text-red-600" : ""} />
@@ -59,11 +59,13 @@ export function UserSelectFieldBinding({
59
59
  />
60
60
  </PropertyIdCopyTooltip>}
61
61
  endAdornment={
62
- property.clearable && !disabled && value && <IconButton
63
- size="small"
64
- onClick={handleClearClick}>
65
- <CloseIcon size={"small"}/>
66
- </IconButton>
62
+ (property.nullable || property.clearable) && !disabled && value !== null && value !== undefined ? (
63
+ <IconButton
64
+ size="small"
65
+ onClick={handleClearClick}>
66
+ <CloseIcon size={"small"}/>
67
+ </IconButton>
68
+ ) : undefined
67
69
  }
68
70
  onValueChange={(updatedValue: string) => {
69
71
  const newValue = updatedValue || null;
package/src/index.ts CHANGED
@@ -11,3 +11,4 @@ export * from "./i18n/FireCMSi18nProvider";
11
11
  export * from "./locales/en";
12
12
  export * from "./locales/es";
13
13
  export * from "./editor";
14
+ export * from "./util/objects";
package/src/locales/de.ts CHANGED
@@ -437,6 +437,8 @@ export const de: FireCMSTranslations = {
437
437
  cms_users: "CMS-Benutzer",
438
438
  roles_menu: "Rollen",
439
439
  project_settings: "Projekteinstellungen",
440
+ firestore_explorer: "Firestore-Explorer",
441
+ explore_your_firestore_data: "Deine Firestore-Daten durchsuchen",
440
442
 
441
443
  // ─── FireCMS Cloud Login ──────────────────────────────────────
442
444
  build_admin_panel_in_minutes: "Erstellen Sie Ihr Firebase Admin Panel in wenigen Minuten",
@@ -678,6 +680,17 @@ export const de: FireCMSTranslations = {
678
680
  settings_appcheck_updated: "AppCheck aktualisiert",
679
681
  settings_appcheck_error: "Fehler beim Aktualisieren von AppCheck",
680
682
 
683
+ // --- Permission Error View ---
684
+ missing_firestore_security_rules: "Fehlende Firestore-Sicherheitsregeln",
685
+ firecms_cloud_requires_security_rule: "FireCMS Cloud erfordert eine spezifische Sicherheitsregel in Ihrem Firestore, um authentifizierten Benutzern Zugriff zu gewähren. Auf die Sammlung",
686
+ cannot_be_accessed_without_it: "kann ohne sie nicht zugegriffen werden.",
687
+ required_security_rule: "Erforderliche Sicherheitsregel",
688
+ fix_automatically: "Automatisch beheben",
689
+ open_firebase_rules: "Firebase-Regeln öffnen",
690
+ security_rules_updated_successfully: "Sicherheitsregeln erfolgreich aktualisiert! Bitte laden Sie die Seite neu, um Ihre Daten zu laden.",
691
+ sec_rules_fixing: "Beheben...",
692
+ sec_rules_fixed: "Behoben!",
693
+
681
694
  // ─── Text Search Dialog ─────────────────────────────────────
682
695
  text_search_dialog_title: "Textsuche aktivieren",
683
696
  text_search_local_not_recommended: "Die lokale Textsuche wird für große Sammlungen nicht empfohlen.",
@@ -687,5 +700,19 @@ export const de: FireCMSTranslations = {
687
700
  text_search_own_implementation: "Sie haben Ihren eigenen Textsuch-Controller implementiert. Sie können die Textsuche für Ihre Sammlung aktivieren.",
688
701
  text_search_enable_for_collection: "Für diese Sammlung aktivieren",
689
702
  text_search_enable_for_project: "Für das Projekt aktivieren",
690
- text_search_enabled_snackbar: "Lokale Textsuche aktiviert"
703
+ text_search_enabled_snackbar: "Lokale Textsuche aktiviert",
704
+
705
+ // ─── GCP Marketplace ─────────────────────────────────────────
706
+ marketplace_managed_by_gcp: "Verwaltet über GCP Marketplace",
707
+ marketplace_billing_note: "Ihr Abonnement wird über den Google Cloud Marketplace verwaltet. Planänderungen, Abrechnung und Kündigung werden in der GCP-Konsole durchgeführt.",
708
+ marketplace_manage_in_gcp_console: "In der GCP-Konsole verwalten",
709
+ marketplace_plan_changes_note: "Um Ihren Plan zu ändern oder zu kündigen, besuchen Sie Ihre GCP Marketplace-Bestellungen.",
710
+ marketplace_welcome_title: "Willkommen vom GCP Marketplace!",
711
+ marketplace_welcome_subtitle: "Ihr Google Cloud Marketplace-Abonnement ist aktiv. Wählen Sie ein vorhandenes Projekt aus oder erstellen Sie ein neues, um es zu verknüpfen.",
712
+ marketplace_select_or_create_project: "Projekt auswählen oder erstellen",
713
+ marketplace_link_project: "Projekt verknüpfen",
714
+ marketplace_linking: "Projekt wird verknüpft…",
715
+ marketplace_link_success: "Projekt erfolgreich verknüpft! Weiterleitung…",
716
+ marketplace_link_error: "Fehler beim Verknüpfen des Projekts. Bitte versuchen Sie es erneut.",
717
+ marketplace_no_account_id: "Keine GCP Marketplace-Konto-ID gefunden. Bitte starten Sie vom GCP Marketplace.",
691
718
  };
package/src/locales/en.ts CHANGED
@@ -445,6 +445,8 @@ export const en: FireCMSTranslations = {
445
445
  cms_users: "CMS Users",
446
446
  roles_menu: "Roles",
447
447
  project_settings: "Project settings",
448
+ firestore_explorer: "Firestore Explorer",
449
+ explore_your_firestore_data: "Explore your Firestore data",
448
450
 
449
451
  // ─── FireCMS Cloud Login ──────────────────────────────────────
450
452
  build_admin_panel_in_minutes: "Build Your Firebase Admin Panel in Minutes",
@@ -700,4 +702,29 @@ export const en: FireCMSTranslations = {
700
702
  settings_appcheck_refresh_note: "You might need to refresh the page to see the changes, after saving.",
701
703
  settings_appcheck_updated: "AppCheck updated",
702
704
  settings_appcheck_error: "Error updating AppCheck",
705
+
706
+ // --- Permission Error View ---
707
+ missing_firestore_security_rules: "Missing Firestore Security Rules",
708
+ firecms_cloud_requires_security_rule: "FireCMS Cloud requires a specific security rule in your Firestore to grant access to authenticated users. The collection",
709
+ cannot_be_accessed_without_it: "cannot be accessed without it.",
710
+ required_security_rule: "Required security rule",
711
+ fix_automatically: "Fix automatically",
712
+ open_firebase_rules: "Open Firebase Rules",
713
+ security_rules_updated_successfully: "Security rules updated successfully! Please refresh the page to load your data.",
714
+ sec_rules_fixing: "Fixing...",
715
+ sec_rules_fixed: "Fixed!",
716
+
717
+ // ─── GCP Marketplace ─────────────────────────────────────────
718
+ marketplace_managed_by_gcp: "Managed via GCP Marketplace",
719
+ marketplace_billing_note: "Your subscription is managed through Google Cloud Marketplace. Plan changes, billing, and cancellation are handled in the GCP Console.",
720
+ marketplace_manage_in_gcp_console: "Manage in GCP Console",
721
+ marketplace_plan_changes_note: "To change your plan or cancel, visit your GCP Marketplace orders.",
722
+ marketplace_welcome_title: "Welcome from GCP Marketplace!",
723
+ marketplace_welcome_subtitle: "Your Google Cloud Marketplace subscription is active. Select an existing project or create a new one to link it.",
724
+ marketplace_select_or_create_project: "Select or create a project",
725
+ marketplace_link_project: "Link project",
726
+ marketplace_linking: "Linking project…",
727
+ marketplace_link_success: "Project linked successfully! Redirecting…",
728
+ marketplace_link_error: "Error linking project. Please try again.",
729
+ marketplace_no_account_id: "No GCP Marketplace account ID found. Please start from the GCP Marketplace.",
703
730
  };
package/src/locales/es.ts CHANGED
@@ -445,6 +445,8 @@ export const es: FireCMSTranslations = {
445
445
  cms_users: "Usuarios del CMS",
446
446
  roles_menu: "Roles",
447
447
  project_settings: "Ajustes del proyecto",
448
+ firestore_explorer: "Explorador de Firestore",
449
+ explore_your_firestore_data: "Explora tus datos de Firestore",
448
450
 
449
451
  // ─── FireCMS Cloud Login ──────────────────────────────────────
450
452
  build_admin_panel_in_minutes: "Crea tu panel de administración de Firebase en minutos",
@@ -690,6 +692,17 @@ export const es: FireCMSTranslations = {
690
692
  settings_appcheck_updated: "AppCheck actualizado",
691
693
  settings_appcheck_error: "Error al actualizar AppCheck",
692
694
 
695
+ // --- Permission Error View ---
696
+ missing_firestore_security_rules: "Faltan Reglas de Seguridad de Firestore",
697
+ firecms_cloud_requires_security_rule: "FireCMS Cloud requiere una regla de seguridad específica en tu Firestore para conceder acceso a los usuarios autenticados. La colección",
698
+ cannot_be_accessed_without_it: "no puede ser accedida sin ella.",
699
+ required_security_rule: "Regla de seguridad requerida",
700
+ fix_automatically: "Corregir automáticamente",
701
+ open_firebase_rules: "Abrir Reglas de Firebase",
702
+ security_rules_updated_successfully: "¡Reglas de seguridad actualizadas con éxito! Por favor recarga la página para cargar tus datos.",
703
+ sec_rules_fixing: "Corrigiendo...",
704
+ sec_rules_fixed: "¡Corregido!",
705
+
693
706
  // ─── Text Search Dialog ─────────────────────────────────────
694
707
  text_search_dialog_title: "Activar búsqueda de texto",
695
708
  text_search_local_not_recommended: "La búsqueda de texto local no es recomendable para colecciones grandes.",
@@ -699,5 +712,19 @@ export const es: FireCMSTranslations = {
699
712
  text_search_own_implementation: "Has implementado tu propio controlador de búsqueda de texto. Puedes activar la búsqueda de texto para tu colección.",
700
713
  text_search_enable_for_collection: "Activar para esta colección",
701
714
  text_search_enable_for_project: "Activar para el proyecto",
702
- text_search_enabled_snackbar: "Búsqueda de texto local activada"
715
+ text_search_enabled_snackbar: "Búsqueda de texto local activada",
716
+
717
+ // ─── GCP Marketplace ─────────────────────────────────────────
718
+ marketplace_managed_by_gcp: "Gestionado a través de GCP Marketplace",
719
+ marketplace_billing_note: "Tu suscripción se gestiona a través de Google Cloud Marketplace. Los cambios de plan, la facturación y la cancelación se realizan en la consola de GCP.",
720
+ marketplace_manage_in_gcp_console: "Gestionar en la consola de GCP",
721
+ marketplace_plan_changes_note: "Para cambiar tu plan o cancelar, visita tus pedidos de GCP Marketplace.",
722
+ marketplace_welcome_title: "¡Bienvenido desde GCP Marketplace!",
723
+ marketplace_welcome_subtitle: "Tu suscripción de Google Cloud Marketplace está activa. Selecciona un proyecto existente o crea uno nuevo para vincularlo.",
724
+ marketplace_select_or_create_project: "Seleccionar o crear un proyecto",
725
+ marketplace_link_project: "Vincular proyecto",
726
+ marketplace_linking: "Vinculando proyecto…",
727
+ marketplace_link_success: "¡Proyecto vinculado con éxito! Redirigiendo…",
728
+ marketplace_link_error: "Error al vincular el proyecto. Por favor, inténtalo de nuevo.",
729
+ marketplace_no_account_id: "No se encontró un ID de cuenta de GCP Marketplace. Por favor, comienza desde GCP Marketplace.",
703
730
  };
package/src/locales/fr.ts CHANGED
@@ -437,6 +437,8 @@ export const fr: FireCMSTranslations = {
437
437
  cms_users: "Utilisateurs du CMS",
438
438
  roles_menu: "Rôles",
439
439
  project_settings: "Paramètres du projet",
440
+ firestore_explorer: "Explorateur Firestore",
441
+ explore_your_firestore_data: "Explorez vos données Firestore",
440
442
 
441
443
  // ─── FireCMS Cloud Login ──────────────────────────────────────
442
444
  build_admin_panel_in_minutes: "Créez votre panneau d'administration Firebase en quelques minutes",
@@ -678,6 +680,17 @@ export const fr: FireCMSTranslations = {
678
680
  settings_appcheck_updated: "AppCheck mis à jour",
679
681
  settings_appcheck_error: "Erreur lors de la mise à jour d'AppCheck",
680
682
 
683
+ // --- Permission Error View ---
684
+ missing_firestore_security_rules: "Règles de sécurité Firestore manquantes",
685
+ firecms_cloud_requires_security_rule: "FireCMS Cloud nécessite une règle de sécurité spécifique dans votre Firestore pour accorder l'accès aux utilisateurs authentifiés. La collection",
686
+ cannot_be_accessed_without_it: "ne peut pas être consultée sans elle.",
687
+ required_security_rule: "Règle de sécurité requise",
688
+ fix_automatically: "Corriger automatiquement",
689
+ open_firebase_rules: "Ouvrir les règles Firebase",
690
+ security_rules_updated_successfully: "Règles de sécurité mises à jour avec succès! Veuillez rafraîchir la page pour charger vos données.",
691
+ sec_rules_fixing: "Correction...",
692
+ sec_rules_fixed: "Corrigé!",
693
+
681
694
  // ─── Text Search Dialog ─────────────────────────────────────
682
695
  text_search_dialog_title: "Activer la recherche de texte",
683
696
  text_search_local_not_recommended: "La recherche de texte locale n'est pas recommandée pour les grandes collections.",
@@ -687,5 +700,19 @@ export const fr: FireCMSTranslations = {
687
700
  text_search_own_implementation: "Vous avez implémenté votre propre contrôleur de recherche de texte. Vous pouvez activer la recherche de texte pour votre collection.",
688
701
  text_search_enable_for_collection: "Activer pour cette collection",
689
702
  text_search_enable_for_project: "Activer pour le projet",
690
- text_search_enabled_snackbar: "Recherche de texte locale activée"
703
+ text_search_enabled_snackbar: "Recherche de texte locale activée",
704
+
705
+ // ─── GCP Marketplace ─────────────────────────────────────────
706
+ marketplace_managed_by_gcp: "Géré via GCP Marketplace",
707
+ marketplace_billing_note: "Votre abonnement est géré via Google Cloud Marketplace. Les modifications de plan, la facturation et l'annulation sont gérées dans la console GCP.",
708
+ marketplace_manage_in_gcp_console: "Gérer dans la console GCP",
709
+ marketplace_plan_changes_note: "Pour modifier votre plan ou annuler, visitez vos commandes GCP Marketplace.",
710
+ marketplace_welcome_title: "Bienvenue depuis GCP Marketplace !",
711
+ marketplace_welcome_subtitle: "Votre abonnement Google Cloud Marketplace est actif. Sélectionnez un projet existant ou créez-en un nouveau pour le lier.",
712
+ marketplace_select_or_create_project: "Sélectionner ou créer un projet",
713
+ marketplace_link_project: "Lier le projet",
714
+ marketplace_linking: "Liaison du projet en cours…",
715
+ marketplace_link_success: "Projet lié avec succès ! Redirection…",
716
+ marketplace_link_error: "Erreur lors de la liaison du projet. Veuillez réessayer.",
717
+ marketplace_no_account_id: "Aucun identifiant de compte GCP Marketplace trouvé. Veuillez commencer depuis GCP Marketplace.",
691
718
  };
package/src/locales/hi.ts CHANGED
@@ -437,6 +437,8 @@ export const hi: FireCMSTranslations = {
437
437
  cms_users: "CMS उपयोगकर्ता",
438
438
  roles_menu: "भूमिकाएँ",
439
439
  project_settings: "परियोजना सेटिंग",
440
+ firestore_explorer: "Firestore एक्सप्लोरर",
441
+ explore_your_firestore_data: "अपने Firestore डेटा का अन्वेषण करें",
440
442
 
441
443
  // ─── FireCMS Cloud Login ──────────────────────────────────────
442
444
  build_admin_panel_in_minutes: "मिनटों में अपना Firebase एडमिन पैनल बनाएं",
@@ -678,6 +680,17 @@ export const hi: FireCMSTranslations = {
678
680
  settings_appcheck_updated: "AppCheck अपडेट किया गया",
679
681
  settings_appcheck_error: "AppCheck अपडेट करने में त्रुटि",
680
682
 
683
+ // --- Permission Error View ---
684
+ missing_firestore_security_rules: "Firestore सुरक्षा नियम गायब हैं",
685
+ firecms_cloud_requires_security_rule: "FireCMS Cloud को आपके Firestore में प्रमाणित उपयोगकर्ताओं को एक्सेस देने के लिए एक विशिष्ट सुरक्षा नियम की आवश्यकता है। संग्रह",
686
+ cannot_be_accessed_without_it: "पर इसके बिना नहीं पहुंचा जा सकता।",
687
+ required_security_rule: "आवश्यक सुरक्षा नियम",
688
+ fix_automatically: "स्वचालित रूप से ठीक करें",
689
+ open_firebase_rules: "Firebase नियम खोलें",
690
+ security_rules_updated_successfully: "सुरक्षा नियम सफलतापूर्वक अपडेट किए गए! कृपया अपना डेटा लोड करने के लिए पेज को रीफ्रेश करें।",
691
+ sec_rules_fixing: "ठीक किया जा रहा है...",
692
+ sec_rules_fixed: "ठीक हो गया!",
693
+
681
694
  // ─── Text Search Dialog ─────────────────────────────────────
682
695
  text_search_dialog_title: "पाठ खोज सक्षम करें",
683
696
  text_search_local_not_recommended: "बड़ी संग्रहों के लिए स्थानीय पाठ खोज की अनुशंसा नहीं की जाती है।",
@@ -687,5 +700,19 @@ export const hi: FireCMSTranslations = {
687
700
  text_search_own_implementation: "आपने अपना स्वयं का पाठ खोज नियंत्रक लागू किया है। आप अपने संग्रह के लिए पाठ खोज सक्षम कर सकते हैं।",
688
701
  text_search_enable_for_collection: "इस संग्रह के लिए सक्षम करें",
689
702
  text_search_enable_for_project: "प्रोजेक्ट के लिए सक्षम करें",
690
- text_search_enabled_snackbar: "स्थानीय पाठ खोज सक्षम की गई"
703
+ text_search_enabled_snackbar: "स्थानीय पाठ खोज सक्षम की गई",
704
+
705
+ // ─── GCP Marketplace ─────────────────────────────────────────
706
+ marketplace_managed_by_gcp: "GCP Marketplace के माध्यम से प्रबंधित",
707
+ marketplace_billing_note: "आपकी सदस्यता Google Cloud Marketplace के माध्यम से प्रबंधित है। योजना परिवर्तन, बिलिंग और रद्दीकरण GCP कंसोल में संभाले जाते हैं।",
708
+ marketplace_manage_in_gcp_console: "GCP कंसोल में प्रबंधित करें",
709
+ marketplace_plan_changes_note: "अपनी योजना बदलने या रद्द करने के लिए, अपने GCP Marketplace ऑर्डर पर जाएं।",
710
+ marketplace_welcome_title: "GCP Marketplace से स्वागत है!",
711
+ marketplace_welcome_subtitle: "आपकी Google Cloud Marketplace सदस्यता सक्रिय है। इसे लिंक करने के लिए एक मौजूदा प्रोजेक्ट चुनें या एक नया बनाएं।",
712
+ marketplace_select_or_create_project: "प्रोजेक्ट चुनें या बनाएं",
713
+ marketplace_link_project: "प्रोजेक्ट लिंक करें",
714
+ marketplace_linking: "प्रोजेक्ट लिंक हो रहा है…",
715
+ marketplace_link_success: "प्रोजेक्ट सफलतापूर्वक लिंक हो गया! रीडायरेक्ट हो रहा है…",
716
+ marketplace_link_error: "प्रोजेक्ट लिंक करने में त्रुटि। कृपया पुनः प्रयास करें।",
717
+ marketplace_no_account_id: "कोई GCP Marketplace खाता ID नहीं मिली। कृपया GCP Marketplace से शुरू करें।",
691
718
  };
package/src/locales/it.ts CHANGED
@@ -437,6 +437,8 @@ export const it: FireCMSTranslations = {
437
437
  cms_users: "Utenti CMS",
438
438
  roles_menu: "Ruoli",
439
439
  project_settings: "Impostazioni del progetto",
440
+ firestore_explorer: "Esplora Firestore",
441
+ explore_your_firestore_data: "Esplora i tuoi dati Firestore",
440
442
 
441
443
  // ─── FireCMS Cloud Login ──────────────────────────────────────
442
444
  build_admin_panel_in_minutes: "Crea il tuo pannello di amministrazione Firebase in pochi minuti",
@@ -678,6 +680,17 @@ export const it: FireCMSTranslations = {
678
680
  settings_appcheck_updated: "AppCheck aggiornato",
679
681
  settings_appcheck_error: "Errore nell'aggiornamento di AppCheck",
680
682
 
683
+ // --- Permission Error View ---
684
+ missing_firestore_security_rules: "Regole di sicurezza Firestore mancanti",
685
+ firecms_cloud_requires_security_rule: "FireCMS Cloud richiede una regola di sicurezza specifica nel tuo Firestore per concedere l'accesso agli utenti autenticati. La collezione",
686
+ cannot_be_accessed_without_it: "non può essere visitata senza di essa.",
687
+ required_security_rule: "Regola di sicurezza richiesta",
688
+ fix_automatically: "Correggi automaticamente",
689
+ open_firebase_rules: "Apri le regole Firebase",
690
+ security_rules_updated_successfully: "Regole di sicurezza aggiornate con successo! Per favore aggiorna la pagina per caricare i tuoi dati.",
691
+ sec_rules_fixing: "Correzione...",
692
+ sec_rules_fixed: "Corretto!",
693
+
681
694
  // ─── Text Search Dialog ─────────────────────────────────────
682
695
  text_search_dialog_title: "Abilita ricerca testuale",
683
696
  text_search_local_not_recommended: "La ricerca testuale locale non è consigliata per collezioni di grandi dimensioni.",
@@ -687,5 +700,19 @@ export const it: FireCMSTranslations = {
687
700
  text_search_own_implementation: "Hai implementato il tuo controller di ricerca testuale. Puoi abilitare la ricerca testuale per la tua collezione.",
688
701
  text_search_enable_for_collection: "Abilita per questa collezione",
689
702
  text_search_enable_for_project: "Abilita per il progetto",
690
- text_search_enabled_snackbar: "Ricerca testuale locale abilitata"
703
+ text_search_enabled_snackbar: "Ricerca testuale locale abilitata",
704
+
705
+ // ─── GCP Marketplace ─────────────────────────────────────────
706
+ marketplace_managed_by_gcp: "Gestito tramite GCP Marketplace",
707
+ marketplace_billing_note: "Il tuo abbonamento è gestito tramite Google Cloud Marketplace. Le modifiche al piano, la fatturazione e la cancellazione vengono gestite nella console GCP.",
708
+ marketplace_manage_in_gcp_console: "Gestisci nella console GCP",
709
+ marketplace_plan_changes_note: "Per modificare il piano o annullare, visita i tuoi ordini GCP Marketplace.",
710
+ marketplace_welcome_title: "Benvenuto da GCP Marketplace!",
711
+ marketplace_welcome_subtitle: "Il tuo abbonamento Google Cloud Marketplace è attivo. Seleziona un progetto esistente o creane uno nuovo per collegarlo.",
712
+ marketplace_select_or_create_project: "Seleziona o crea un progetto",
713
+ marketplace_link_project: "Collega progetto",
714
+ marketplace_linking: "Collegamento del progetto in corso…",
715
+ marketplace_link_success: "Progetto collegato con successo! Reindirizzamento…",
716
+ marketplace_link_error: "Errore durante il collegamento del progetto. Riprova.",
717
+ marketplace_no_account_id: "Nessun ID account GCP Marketplace trovato. Inizia dal GCP Marketplace.",
691
718
  };
package/src/locales/pt.ts CHANGED
@@ -442,6 +442,8 @@ export const pt: FireCMSTranslations = {
442
442
  cms_users: "Utilizadores do CMS",
443
443
  roles_menu: "Funções",
444
444
  project_settings: "Definições do projeto",
445
+ firestore_explorer: "Explorador do Firestore",
446
+ explore_your_firestore_data: "Explore os seus dados do Firestore",
445
447
 
446
448
  // ─── FireCMS Cloud Login ──────────────────────────────────────
447
449
  build_admin_panel_in_minutes: "Construa o Seu Painel de Administração Firebase em Minutos",
@@ -687,6 +689,17 @@ export const pt: FireCMSTranslations = {
687
689
  settings_appcheck_updated: "AppCheck atualizado",
688
690
  settings_appcheck_error: "Erro ao atualizar o AppCheck",
689
691
 
692
+ // --- Permission Error View ---
693
+ missing_firestore_security_rules: "Regras de Segurança do Firestore Ausentes",
694
+ firecms_cloud_requires_security_rule: "O FireCMS Cloud requer uma regra de segurança específica no seu Firestore para conceder acesso a usuários autenticados. A coleção",
695
+ cannot_be_accessed_without_it: "não pode ser acessada sem ela.",
696
+ required_security_rule: "Regra de segurança obrigatória",
697
+ fix_automatically: "Corrigir automaticamente",
698
+ open_firebase_rules: "Abrir Regras do Firebase",
699
+ security_rules_updated_successfully: "Regras de segurança atualizadas com sucesso! Por favor atualize a página para carregar seus dados.",
700
+ sec_rules_fixing: "Corrigindo...",
701
+ sec_rules_fixed: "Corrigido!",
702
+
690
703
  // ─── Text Search Dialog ─────────────────────────────────────
691
704
  text_search_dialog_title: "Ativar pesquisa de texto",
692
705
  text_search_local_not_recommended: "A pesquisa de texto local não é recomendada para coleções grandes.",
@@ -696,5 +709,19 @@ export const pt: FireCMSTranslations = {
696
709
  text_search_own_implementation: "Implementou o seu próprio controlador de pesquisa de texto. Pode ativar a pesquisa de texto para a sua coleção.",
697
710
  text_search_enable_for_collection: "Ativar para esta coleção",
698
711
  text_search_enable_for_project: "Ativar para o projeto",
699
- text_search_enabled_snackbar: "Pesquisa de texto local ativada"
712
+ text_search_enabled_snackbar: "Pesquisa de texto local ativada",
713
+
714
+ // ─── GCP Marketplace ─────────────────────────────────────────
715
+ marketplace_managed_by_gcp: "Gerenciado via GCP Marketplace",
716
+ marketplace_billing_note: "Sua assinatura é gerenciada pelo Google Cloud Marketplace. Alterações de plano, faturamento e cancelamento são feitos no console do GCP.",
717
+ marketplace_manage_in_gcp_console: "Gerenciar no console do GCP",
718
+ marketplace_plan_changes_note: "Para alterar seu plano ou cancelar, visite seus pedidos do GCP Marketplace.",
719
+ marketplace_welcome_title: "Bem-vindo do GCP Marketplace!",
720
+ marketplace_welcome_subtitle: "Sua assinatura do Google Cloud Marketplace está ativa. Selecione um projeto existente ou crie um novo para vinculá-lo.",
721
+ marketplace_select_or_create_project: "Selecionar ou criar um projeto",
722
+ marketplace_link_project: "Vincular projeto",
723
+ marketplace_linking: "Vinculando projeto…",
724
+ marketplace_link_success: "Projeto vinculado com sucesso! Redirecionando…",
725
+ marketplace_link_error: "Erro ao vincular o projeto. Por favor, tente novamente.",
726
+ marketplace_no_account_id: "Nenhum ID de conta do GCP Marketplace encontrado. Por favor, comece pelo GCP Marketplace.",
700
727
  };
@@ -11,6 +11,7 @@ import {
11
11
  } from "../types";
12
12
 
13
13
  import { resolveProperty } from "../util";
14
+ import { jsonStringifyReplacer } from "../util/objects";
14
15
 
15
16
  import { PropertyPreviewProps } from "./PropertyPreviewProps";
16
17
  import { useAuthController, useCustomizationController } from "../hooks";
@@ -234,7 +235,7 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
234
235
  content = buildWrongValueType(propertyKey, property.dataType, value);
235
236
  }
236
237
  } else {
237
- content = JSON.stringify(value);
238
+ content = JSON.stringify(value, jsonStringifyReplacer);
238
239
  }
239
240
 
240
241
  return content === undefined || content === null || (Array.isArray(content) && content.length === 0)
@@ -246,6 +247,6 @@ function buildWrongValueType(name: string | undefined, dataType: string, value:
246
247
  console.warn(`Unexpected value for property ${name}, of type ${dataType}`, value);
247
248
  return (
248
249
  <ErrorView title={"Unexpected value"}
249
- error={`${JSON.stringify(value)}`} />
250
+ error={`${JSON.stringify(value, jsonStringifyReplacer)}`} />
250
251
  );
251
252
  }
@@ -6,6 +6,7 @@ import { PreviewSize } from "../PropertyPreviewProps";
6
6
  import { Skeleton } from "@firecms/ui";
7
7
  import { ErrorBoundary, ErrorView } from "../../components";
8
8
  import { EntityPreview, EntityPreviewContainer } from "../../components/EntityPreview";
9
+ import { jsonStringifyReplacer } from "../../util/objects";
9
10
 
10
11
  export type ReferencePreviewProps = {
11
12
  disabled?: boolean;
@@ -29,7 +30,7 @@ export const ReferencePreview = function ReferencePreview(props: ReferencePrevie
29
30
  onClick={props.onClick}
30
31
  size={props.size ?? "medium"}>
31
32
  <ErrorView error={"Unexpected value. Click to edit"}
32
- tooltip={JSON.stringify(reference)}/>
33
+ tooltip={JSON.stringify(reference, jsonStringifyReplacer)}/>
33
34
  </EntityPreviewContainer>;
34
35
  }
35
36
  return <ErrorBoundary>