@firecms/core 3.4.0-canary.f6a889a → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +6 -1
- package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +3 -1
- package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +3 -1
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +8 -0
- package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +3 -1
- package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +3 -1
- package/dist/components/EntityCollectionView/useBoardDataController.d.ts +3 -1
- package/dist/components/ErrorBoundary.d.ts +1 -3
- package/dist/components/ReferenceTable/ReferenceSelectionTable.d.ts +10 -1
- package/dist/components/SelectableTable/filters/filter_text_input.d.ts +30 -0
- package/dist/components/SelectableTable/filters/filter_text_input.test.d.ts +1 -0
- package/dist/components/common/table_url_params.d.ts +24 -0
- package/dist/components/common/useDataSourceTableController.d.ts +9 -1
- package/dist/components/common/useTableSearchHelper.d.ts +9 -1
- package/dist/core/EntityEditView.d.ts +9 -1
- package/dist/core/EntityEditViewFormActions.d.ts +1 -1
- package/dist/form/EntityForm.d.ts +8 -1
- package/dist/form/EntityFormActions.d.ts +2 -0
- package/dist/hooks/data/delete.d.ts +1 -1
- package/dist/hooks/data/save.d.ts +1 -1
- package/dist/hooks/data/useCollectionFetch.d.ts +7 -1
- package/dist/hooks/data/useEntityFetch.d.ts +9 -1
- package/dist/i18n/__tests__/FireCMSi18nProvider.test.d.ts +1 -0
- package/dist/i18n/__tests__/nested_provider_lifecycle.test.d.ts +1 -0
- package/dist/index.es.js +1753 -1170
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1751 -1168
- package/dist/index.umd.js.map +1 -1
- package/dist/types/collections.d.ts +14 -0
- package/dist/types/datasource.d.ts +67 -4
- package/dist/types/entities.d.ts +21 -1
- package/dist/types/entity_actions.d.ts +6 -0
- package/dist/types/entity_callbacks.d.ts +21 -0
- package/dist/types/navigation.d.ts +34 -5
- package/dist/types/plugins.d.ts +13 -0
- package/dist/types/properties.d.ts +17 -1
- package/dist/types/side_entity_controller.d.ts +7 -0
- package/dist/types/translations.d.ts +6 -0
- package/dist/util/__tests__/collections.test.d.ts +1 -0
- package/dist/util/__tests__/urls.test.d.ts +1 -0
- package/dist/util/collections.d.ts +1 -1
- package/dist/util/entity_cache.d.ts +11 -0
- package/dist/util/index.d.ts +1 -0
- package/dist/util/navigation_from_path.d.ts +7 -0
- package/dist/util/navigation_utils.d.ts +87 -3
- package/dist/util/parent_references_from_path.d.ts +16 -0
- package/dist/util/paths.d.ts +28 -0
- package/dist/util/permissions.d.ts +10 -4
- package/dist/util/urls.d.ts +22 -0
- package/package.json +4 -4
- package/src/components/DeleteEntityDialog.tsx +2 -0
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +2 -2
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +1 -0
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +7 -0
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +5 -1
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +12 -0
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +66 -15
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +6 -2
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +4 -0
- package/src/components/EntityCollectionView/useBoardDataController.tsx +17 -1
- package/src/components/EntityPreview.tsx +4 -1
- package/src/components/ErrorBoundary.tsx +12 -18
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +19 -2
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +33 -7
- package/src/components/SelectableTable/filters/filter_text_input.test.ts +184 -0
- package/src/components/SelectableTable/filters/filter_text_input.ts +71 -0
- package/src/components/common/default_entity_actions.tsx +22 -2
- package/src/components/common/table_url_params.ts +172 -0
- package/src/components/common/useDataSourceTableController.tsx +86 -179
- package/src/components/common/useTableSearchHelper.ts +26 -2
- package/src/contexts/SnackbarProvider.tsx +14 -1
- package/src/core/EntityEditView.tsx +20 -3
- package/src/core/EntityEditViewFormActions.tsx +3 -2
- package/src/core/EntitySidePanel.tsx +8 -4
- package/src/form/EntityForm.tsx +31 -10
- package/src/form/EntityFormActions.tsx +2 -0
- package/src/hooks/data/delete.ts +8 -0
- package/src/hooks/data/save.ts +6 -1
- package/src/hooks/data/useCollectionFetch.tsx +21 -1
- package/src/hooks/data/useEntityFetch.tsx +35 -4
- package/src/hooks/useBuildNavigationController.tsx +23 -8
- package/src/hooks/useResolvedNavigationFrom.tsx +3 -1
- package/src/hooks/useValidateAuthenticator.tsx +4 -0
- package/src/i18n/FireCMSi18nProvider.tsx +48 -4
- package/src/i18n/__tests__/FireCMSi18nProvider.test.tsx +91 -0
- package/src/i18n/__tests__/nested_provider_lifecycle.test.tsx +67 -0
- package/src/internal/useBuildDataSource.ts +37 -15
- package/src/internal/useBuildSideEntityController.tsx +19 -5
- package/src/locales/de.ts +5 -0
- package/src/locales/en.ts +5 -0
- package/src/locales/es.ts +5 -0
- package/src/locales/fr.ts +5 -0
- package/src/locales/hi.ts +5 -0
- package/src/locales/it.ts +5 -0
- package/src/locales/pl.ts +5 -0
- package/src/locales/pt.ts +5 -0
- package/src/preview/components/ReferencePreview.tsx +7 -3
- package/src/preview/components/StorageThumbnail.tsx +24 -2
- package/src/routes/FireCMSRoute.tsx +11 -3
- package/src/types/collections.ts +16 -0
- package/src/types/datasource.ts +67 -4
- package/src/types/entities.ts +24 -1
- package/src/types/entity_actions.tsx +6 -0
- package/src/types/entity_callbacks.ts +24 -0
- package/src/types/navigation.ts +35 -5
- package/src/types/plugins.tsx +13 -0
- package/src/types/properties.ts +17 -0
- package/src/types/side_entity_controller.tsx +7 -0
- package/src/types/translations.ts +6 -0
- package/src/util/__tests__/collections.test.ts +32 -0
- package/src/util/__tests__/urls.test.ts +131 -0
- package/src/util/collections.ts +1 -1
- package/src/util/entities.ts +3 -1
- package/src/util/entity_cache.ts +18 -0
- package/src/util/index.ts +1 -0
- package/src/util/navigation_from_path.ts +25 -2
- package/src/util/navigation_utils.ts +208 -2
- package/src/util/parent_references_from_path.ts +42 -3
- package/src/util/paths.ts +40 -3
- package/src/util/permissions.ts +22 -10
- package/src/util/previews.ts +8 -1
- package/src/util/resolutions.ts +8 -0
- package/src/util/urls.ts +52 -0
package/src/locales/es.ts
CHANGED
|
@@ -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",
|
|
@@ -598,6 +599,10 @@ export const es: FireCMSTranslations = {
|
|
|
598
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.",
|
|
599
600
|
no_number_properties: "No se encontraron propiedades numéricas. Agrega una propiedad numérica para habilitar el ordenamiento.",
|
|
600
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.",
|
|
601
606
|
display_settings: "Configuración de visualización",
|
|
602
607
|
default_row_size: "Tamaño de fila predeterminado",
|
|
603
608
|
side_dialog_width: "Ancho del diálogo lateral",
|
package/src/locales/fr.ts
CHANGED
|
@@ -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",
|
|
@@ -586,6 +587,10 @@ export const fr: FireCMSTranslations = {
|
|
|
586
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.",
|
|
587
588
|
no_number_properties: "Aucune propriété numérique trouvée. Ajoutez une propriété numérique pour activer le tri.",
|
|
588
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.",
|
|
589
594
|
display_settings: "Paramètres d'affichage",
|
|
590
595
|
default_row_size: "Taille de ligne par défaut",
|
|
591
596
|
side_dialog_width: "Largeur du dialogue latéral",
|
package/src/locales/hi.ts
CHANGED
|
@@ -389,6 +389,7 @@ export const hi: FireCMSTranslations = {
|
|
|
389
389
|
download: "डाउनलोड",
|
|
390
390
|
large_number_of_documents: "इस संग्रह में बड़ी संख्या में दस्तावेज़ हैं ({{count}})।",
|
|
391
391
|
include_undefined_values: "अपरिभाषित (undefined) मान शामिल करें",
|
|
392
|
+
export_apply_filter_sort: "केवल वर्तमान फ़िल्टर/सॉर्ट से मेल खाने वाले परिणाम निर्यात करें",
|
|
392
393
|
submit: "सबमिट करें",
|
|
393
394
|
|
|
394
395
|
no_filterable_properties: "कोई फ़िल्टर करने योग्य गुण उपलब्ध नहीं हैं",
|
|
@@ -586,6 +587,10 @@ export const hi: FireCMSTranslations = {
|
|
|
586
587
|
order_property_not_found: "प्रॉपर्टी \"{{property}}\" मौजूद नहीं है या एक संख्या प्रॉपर्टी नहीं है। कृपया एक वैध प्रॉपर्टी चुनें या चयन साफ़ करें।",
|
|
587
588
|
no_number_properties: "कोई संख्या प्रॉपर्टी नहीं मिली। क्रम सक्षम करने के लिए एक संख्या प्रॉपर्टी जोड़ें।",
|
|
588
589
|
order_property_description: "आइटम का क्रम बनाए रखने के लिए एक संख्या प्रॉपर्टी चुनें",
|
|
590
|
+
image_property: "इमेज प्रॉपर्टी",
|
|
591
|
+
image_property_not_found: "प्रॉपर्टी \"{{property}}\" मौजूद नहीं है या एक इमेज प्रॉपर्टी नहीं है। कृपया एक वैध प्रॉपर्टी चुनें या चयन साफ़ करें।",
|
|
592
|
+
no_image_properties: "कोई इमेज प्रॉपर्टी नहीं मिली। थंबनेल के रूप में उपयोग करने के लिए एक स्टोरेज या URL इमेज प्रॉपर्टी जोड़ें।",
|
|
593
|
+
image_property_description: "कार्ड्स और कानबन व्यू मोड में थंबनेल इमेज के रूप में उपयोग की जाने वाली प्रॉपर्टी चुनें। यदि सेट नहीं किया गया है, तो पहली मिलान वाली इमेज प्रॉपर्टी स्वचालित रूप से उपयोग की जाएगी।",
|
|
589
594
|
display_settings: "प्रदर्शन सेटिंग्स",
|
|
590
595
|
default_row_size: "डिफ़ॉल्ट पंक्ति आकार",
|
|
591
596
|
side_dialog_width: "साइड डायलॉग चौड़ाई",
|
package/src/locales/it.ts
CHANGED
|
@@ -389,6 +389,7 @@ export const it: FireCMSTranslations = {
|
|
|
389
389
|
download: "Scarica",
|
|
390
390
|
large_number_of_documents: "Questa collezione contiene un numero elevato di documenti ({{count}})",
|
|
391
391
|
include_undefined_values: "Includi valori non definiti",
|
|
392
|
+
export_apply_filter_sort: "Esporta solo i risultati che corrispondono al filtro/ordinamento attuale",
|
|
392
393
|
submit: "Invia",
|
|
393
394
|
|
|
394
395
|
no_filterable_properties: "Nessuna proprietà filtrabile disponibile",
|
|
@@ -586,6 +587,10 @@ export const it: FireCMSTranslations = {
|
|
|
586
587
|
order_property_not_found: "La proprietà \"{{property}}\" non esiste o non è una proprietà numerica. Seleziona una proprietà valida o cancella la selezione.",
|
|
587
588
|
no_number_properties: "Nessuna proprietà numerica trovata. Aggiungi una proprietà numerica per abilitare l'ordinamento.",
|
|
588
589
|
order_property_description: "Seleziona una proprietà numerica per mantenere l'ordine degli elementi",
|
|
590
|
+
image_property: "Proprietà immagine",
|
|
591
|
+
image_property_not_found: "La proprietà \"{{property}}\" non esiste o non è una proprietà immagine. Seleziona una proprietà valida o cancella la selezione.",
|
|
592
|
+
no_image_properties: "Nessuna proprietà immagine trovata. Aggiungi una proprietà di archiviazione o URL immagine da usare come miniatura.",
|
|
593
|
+
image_property_description: "Seleziona la proprietà utilizzata come miniatura nelle viste Schede e Kanban. Se non impostata, verrà utilizzata automaticamente la prima proprietà immagine corrispondente.",
|
|
589
594
|
display_settings: "Impostazioni di visualizzazione",
|
|
590
595
|
default_row_size: "Dimensione riga predefinita",
|
|
591
596
|
side_dialog_width: "Larghezza del dialogo laterale",
|
package/src/locales/pl.ts
CHANGED
|
@@ -389,6 +389,7 @@ export const pl: FireCMSTranslations = {
|
|
|
389
389
|
download: "Pobierz",
|
|
390
390
|
large_number_of_documents: "Ta kolekcja zawiera dużą liczbę dokumentów ({{count}}).",
|
|
391
391
|
include_undefined_values: "Uwzględnij niezdefiniowane wartości",
|
|
392
|
+
export_apply_filter_sort: "Eksportuj tylko wyniki zgodne z aktualnym filtrem/sortowaniem",
|
|
392
393
|
submit: "Wyślij",
|
|
393
394
|
|
|
394
395
|
no_filterable_properties: "Brak dostępnych właściwości do filtrowania",
|
|
@@ -590,6 +591,10 @@ export const pl: FireCMSTranslations = {
|
|
|
590
591
|
order_property_not_found: "Właściwość „{{property}}” nie istnieje lub nie jest właściwością liczbową. Wybierz prawidłową właściwość lub wyczyść wybór.",
|
|
591
592
|
no_number_properties: "Nie znaleziono właściwości liczbowych. Dodaj właściwość liczbową, aby włączyć sortowanie.",
|
|
592
593
|
order_property_description: "Wybierz właściwość liczbową, aby zachować kolejność elementów",
|
|
594
|
+
image_property: "Właściwość obrazu",
|
|
595
|
+
image_property_not_found: "Właściwość „{{property}}” nie istnieje lub nie jest właściwością obrazu. Wybierz prawidłową właściwość lub wyczyść wybór.",
|
|
596
|
+
no_image_properties: "Nie znaleziono właściwości obrazu. Dodaj właściwość przechowywania lub adresu URL obrazu, aby użyć jej jako miniatury.",
|
|
597
|
+
image_property_description: "Wybierz właściwość używaną jako miniatura w widokach Karty i Kanban. Jeśli nie zostanie ustawiona, automatycznie zostanie użyta pierwsza pasująca właściwość obrazu.",
|
|
593
598
|
display_settings: "Ustawienia wyświetlania",
|
|
594
599
|
default_row_size: "Domyślny rozmiar wiersza",
|
|
595
600
|
side_dialog_width: "Szerokość okna bocznego",
|
package/src/locales/pt.ts
CHANGED
|
@@ -394,6 +394,7 @@ export const pt: FireCMSTranslations = {
|
|
|
394
394
|
download: "Descarregar",
|
|
395
395
|
large_number_of_documents: "Esta coleção tem um grande número de documentos ({{count}}).",
|
|
396
396
|
include_undefined_values: "Incluir valores indefinidos",
|
|
397
|
+
export_apply_filter_sort: "Exportar apenas os resultados que correspondem ao filtro/ordenação atual",
|
|
397
398
|
submit: "Submeter",
|
|
398
399
|
|
|
399
400
|
no_filterable_properties: "Não há propriedades filtráveis disponíveis",
|
|
@@ -595,6 +596,10 @@ export const pt: FireCMSTranslations = {
|
|
|
595
596
|
order_property_not_found: "A propriedade \"{{property}}\" não existe ou não é uma propriedade numérica. Selecione uma propriedade válida ou limpe a seleção.",
|
|
596
597
|
no_number_properties: "Nenhuma propriedade numérica encontrada. Adicione uma propriedade numérica para habilitar a ordenação.",
|
|
597
598
|
order_property_description: "Selecione uma propriedade numérica para manter a ordem dos itens",
|
|
599
|
+
image_property: "Propriedade de imagem",
|
|
600
|
+
image_property_not_found: "A propriedade \"{{property}}\" não existe ou não é uma propriedade de imagem. Selecione uma propriedade válida ou limpe a seleção.",
|
|
601
|
+
no_image_properties: "Nenhuma propriedade de imagem encontrada. Adicione uma propriedade de armazenamento ou URL de imagem para usar como miniatura.",
|
|
602
|
+
image_property_description: "Selecione a propriedade usada como miniatura nas visualizações de Cartões e Kanban. Se não for definida, a primeira propriedade de imagem correspondente será usada automaticamente.",
|
|
598
603
|
display_settings: "Configurações de exibição",
|
|
599
604
|
default_row_size: "Tamanho de linha padrão",
|
|
600
605
|
side_dialog_width: "Largura do diálogo lateral",
|
|
@@ -7,6 +7,7 @@ import { Skeleton } from "@firecms/ui";
|
|
|
7
7
|
import { ErrorBoundary, ErrorView } from "../../components";
|
|
8
8
|
import { EntityPreview, EntityPreviewContainer } from "../../components/EntityPreview";
|
|
9
9
|
import { jsonStringifyReplacer } from "../../util/objects";
|
|
10
|
+
import { entityCacheKey } from "../../util/entity_cache";
|
|
10
11
|
|
|
11
12
|
export type ReferencePreviewProps = {
|
|
12
13
|
disabled?: boolean;
|
|
@@ -53,7 +54,7 @@ function ReferencePreviewInternal({
|
|
|
53
54
|
|
|
54
55
|
const navigationController = useNavigationController();
|
|
55
56
|
|
|
56
|
-
const collection = navigationController.getCollection(reference.path);
|
|
57
|
+
const collection = navigationController.getCollection(reference.path, false, reference.pathSegments);
|
|
57
58
|
if (!collection) {
|
|
58
59
|
if (customizationController.components?.missingReference) {
|
|
59
60
|
return <customizationController.components.missingReference path={reference.path}/>;
|
|
@@ -99,16 +100,19 @@ function ReferencePreviewExisting<M extends Record<string, any> = any>({
|
|
|
99
100
|
dataLoadingError
|
|
100
101
|
} = useEntityFetch({
|
|
101
102
|
path: reference.path,
|
|
103
|
+
// References carry the segments of the collection they point at, when the code that
|
|
104
|
+
// built them knew them (see getReferenceFrom).
|
|
105
|
+
pathSegments: reference.pathSegments,
|
|
102
106
|
entityId: reference.id,
|
|
103
107
|
collection,
|
|
104
108
|
useCache: true
|
|
105
109
|
});
|
|
106
110
|
|
|
107
111
|
if (entity) {
|
|
108
|
-
referencesCache.set(reference.
|
|
112
|
+
referencesCache.set(entityCacheKey(reference.path, reference.id), entity);
|
|
109
113
|
}
|
|
110
114
|
|
|
111
|
-
const usedEntity = entity ?? referencesCache.get(reference.
|
|
115
|
+
const usedEntity = entity ?? referencesCache.get(entityCacheKey(reference.path, reference.id));
|
|
112
116
|
|
|
113
117
|
let body: React.ReactNode;
|
|
114
118
|
|
|
@@ -6,6 +6,7 @@ import { useStorageSource } from "../../hooks";
|
|
|
6
6
|
import { DownloadConfig, FileType } from "../../types";
|
|
7
7
|
import { PreviewSize } from "../PropertyPreviewProps";
|
|
8
8
|
import { ErrorView } from "../../components";
|
|
9
|
+
import { getPreviewTypeFromUrl, isAbsoluteHttpUrl } from "../../util/urls";
|
|
9
10
|
|
|
10
11
|
type StorageThumbnailProps = {
|
|
11
12
|
storagePathOrDownloadUrl: string;
|
|
@@ -41,10 +42,20 @@ export function StorageThumbnailInternal({
|
|
|
41
42
|
const [error, setError] = React.useState<Error | undefined>(undefined);
|
|
42
43
|
const storage = useStorageSource();
|
|
43
44
|
|
|
45
|
+
/**
|
|
46
|
+
* The saved value may already be a resolved download URL instead of a
|
|
47
|
+
* storage path: either because the property is configured with
|
|
48
|
+
* `storeUrl: true`, or because the value was written directly in the
|
|
49
|
+
* datasource pointing to an externally hosted file. Such values can be
|
|
50
|
+
* previewed as they are, and must not be handed over to the storage source,
|
|
51
|
+
* which can only resolve paths of its own bucket.
|
|
52
|
+
*/
|
|
53
|
+
const valueIsUrl = storeUrl || isAbsoluteHttpUrl(storagePathOrDownloadUrl);
|
|
54
|
+
|
|
44
55
|
const [downloadConfig, setDownloadConfig] = React.useState<DownloadConfig>(URL_CACHE[storagePathOrDownloadUrl]);
|
|
45
56
|
|
|
46
57
|
useEffect(() => {
|
|
47
|
-
if (!storagePathOrDownloadUrl)
|
|
58
|
+
if (!storagePathOrDownloadUrl || valueIsUrl)
|
|
48
59
|
return;
|
|
49
60
|
let unmounted = false;
|
|
50
61
|
storage.getDownloadURL(storagePathOrDownloadUrl)
|
|
@@ -57,10 +68,21 @@ export function StorageThumbnailInternal({
|
|
|
57
68
|
return () => {
|
|
58
69
|
unmounted = true;
|
|
59
70
|
};
|
|
60
|
-
}, [storagePathOrDownloadUrl]);
|
|
71
|
+
}, [storagePathOrDownloadUrl, valueIsUrl]);
|
|
61
72
|
|
|
62
73
|
if (!storagePathOrDownloadUrl) return null;
|
|
63
74
|
|
|
75
|
+
if (valueIsUrl) {
|
|
76
|
+
// There is no storage metadata for a value that is already a URL, so the
|
|
77
|
+
// preview type is inferred from its file extension when possible.
|
|
78
|
+
return <UrlComponentPreview previewType={getPreviewTypeFromUrl(storagePathOrDownloadUrl) ?? "file"}
|
|
79
|
+
url={storagePathOrDownloadUrl}
|
|
80
|
+
interactive={interactive}
|
|
81
|
+
size={size}
|
|
82
|
+
fill={fill}
|
|
83
|
+
hint={storagePathOrDownloadUrl} />;
|
|
84
|
+
}
|
|
85
|
+
|
|
64
86
|
const filetype = downloadConfig?.metadata ? getFiletype(downloadConfig?.metadata.contentType) : undefined;
|
|
65
87
|
const previewType = filetype?.startsWith("image")
|
|
66
88
|
? "image"
|
|
@@ -90,7 +90,7 @@ export function FireCMSRoute() {
|
|
|
90
90
|
let collection: EntityCollection<any> | undefined;
|
|
91
91
|
collection = navigation.getCollectionById(navigationEntries[0].id);
|
|
92
92
|
if (!collection)
|
|
93
|
-
collection = navigation.getCollection(navigationEntries[0].path);
|
|
93
|
+
collection = navigation.getCollection(navigationEntries[0].path, false, navigationEntries[0].pathSegments);
|
|
94
94
|
if (!collection)
|
|
95
95
|
return null;
|
|
96
96
|
return <React.Suspense fallback={null}>
|
|
@@ -99,6 +99,7 @@ export function FireCMSRoute() {
|
|
|
99
99
|
isSubCollection={false}
|
|
100
100
|
parentCollectionIds={[]}
|
|
101
101
|
fullPath={collection.path}
|
|
102
|
+
pathSegments={navigationEntries[0].pathSegments}
|
|
102
103
|
fullIdPath={collection.id}
|
|
103
104
|
updateUrl={true}
|
|
104
105
|
{...collection}
|
|
@@ -113,7 +114,7 @@ export function FireCMSRoute() {
|
|
|
113
114
|
const firstEntry = navigationEntries[0] as NavigationViewCollectionInternal<any>;
|
|
114
115
|
collection = navigation.getCollectionById(firstEntry.id);
|
|
115
116
|
if (!collection)
|
|
116
|
-
collection = navigation.getCollection(firstEntry.path);
|
|
117
|
+
collection = navigation.getCollection(firstEntry.path, false, firstEntry.pathSegments);
|
|
117
118
|
if (!collection)
|
|
118
119
|
return null;
|
|
119
120
|
return <React.Suspense fallback={null}>
|
|
@@ -123,6 +124,7 @@ export function FireCMSRoute() {
|
|
|
123
124
|
isSubCollection={false}
|
|
124
125
|
parentCollectionIds={[]}
|
|
125
126
|
fullPath={collection.path}
|
|
127
|
+
pathSegments={firstEntry.pathSegments}
|
|
126
128
|
updateUrl={true}
|
|
127
129
|
{...collection}
|
|
128
130
|
Actions={toArray(collection.Actions)} />
|
|
@@ -184,6 +186,8 @@ function EntityFullScreenRoute({
|
|
|
184
186
|
const urlTab = getSelectedTabFromUrl(isNew, lastCustomView);
|
|
185
187
|
const [selectedTab, setSelectedTab] = useState<string | undefined>(urlTab);
|
|
186
188
|
|
|
189
|
+
// `navigationPath` comes from the URL, where entity ids are still escaped (see
|
|
190
|
+
// encodeEntityId), so splitting it on "/" inside is correct and no segments are needed.
|
|
187
191
|
const parentCollectionIds = navigation.getParentCollectionIds(navigationPath);
|
|
188
192
|
useEffect(() => {
|
|
189
193
|
if (urlTab !== selectedTab) {
|
|
@@ -248,13 +252,17 @@ function EntityFullScreenRoute({
|
|
|
248
252
|
// `fullIdPath` is used downstream to build URLs, so it carries the escaped chain;
|
|
249
253
|
// `collectionPath` addresses the datasource, so it is resolved from the raw one.
|
|
250
254
|
const fullIdPath = isNew ? lastCollectionEntry!.fullPath : (parentCollectionEntry?.fullPath ?? lastEntityEntry!.fullPath);
|
|
251
|
-
|
|
255
|
+
// The navigation entries know the real segment boundaries, so the path is resolved
|
|
256
|
+
// from them rather than re-parsed out of the flattened string.
|
|
257
|
+
const pathSegments = isNew ? lastCollectionEntry!.pathSegments : lastEntityEntry!.pathSegments;
|
|
258
|
+
const collectionPath = navigation.resolveIdsFrom(isNew ? lastCollectionEntry!.path : lastEntityEntry!.path, pathSegments);
|
|
252
259
|
return <>
|
|
253
260
|
<React.Suspense fallback={null}>
|
|
254
261
|
<EntityEditView
|
|
255
262
|
key={collection.id + "_" + (isNew ? "new" : (isCopy ? entityId + "_copy" : entityId))}
|
|
256
263
|
entityId={isNew ? undefined : entityId}
|
|
257
264
|
fullIdPath={fullIdPath}
|
|
265
|
+
pathSegments={pathSegments}
|
|
258
266
|
collection={collection}
|
|
259
267
|
layout={"full_screen"}
|
|
260
268
|
path={collectionPath}
|
package/src/types/collections.ts
CHANGED
|
@@ -101,6 +101,14 @@ export interface EntityCollection<M extends Record<string, any> = any, USER exte
|
|
|
101
101
|
*/
|
|
102
102
|
titleProperty?: keyof M;
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Property used as the image thumbnail in Cards and Kanban view modes.
|
|
106
|
+
* Must reference a storage/image property (or an array of them), or a
|
|
107
|
+
* string property with `url: "image"`.
|
|
108
|
+
* If not specified, the first matching image property will be used.
|
|
109
|
+
*/
|
|
110
|
+
imageProperty?: keyof M;
|
|
111
|
+
|
|
104
112
|
/**
|
|
105
113
|
* When editing an entity, you can choose to open the entity in a side dialog
|
|
106
114
|
* or in a full screen dialog. Defaults to `full_screen`.
|
|
@@ -489,6 +497,14 @@ export interface CollectionActionsProps<M extends Record<string, any> = any, USE
|
|
|
489
497
|
*/
|
|
490
498
|
path: string;
|
|
491
499
|
|
|
500
|
+
/**
|
|
501
|
+
* `path` split at its real segment boundaries, e.g. `["nodes", "node/42", "edges"]`.
|
|
502
|
+
*
|
|
503
|
+
* Optional, and never derived by splitting `path` — a parent entity id may itself
|
|
504
|
+
* contain "/". Absent means "not known here", not "no slashes".
|
|
505
|
+
*/
|
|
506
|
+
pathSegments?: string[];
|
|
507
|
+
|
|
492
508
|
/**
|
|
493
509
|
* Path of the last collection, like `addresses`
|
|
494
510
|
*/
|
package/src/types/datasource.ts
CHANGED
|
@@ -8,6 +8,20 @@ import { FireCMSContext } from "./firecms_context";
|
|
|
8
8
|
*/
|
|
9
9
|
export interface FetchEntityProps<M extends Record<string, any> = any> {
|
|
10
10
|
path: string;
|
|
11
|
+
/**
|
|
12
|
+
* The path split at its real segment boundaries, e.g.
|
|
13
|
+
* `["nodes", "node/42", "edges"]`.
|
|
14
|
+
*
|
|
15
|
+
* `path` is a single flattened string, so a parent entity id containing "/" cannot be
|
|
16
|
+
* recovered from it — `"nodes/node/42/edges"` is indistinguishable from a three-level
|
|
17
|
+
* nesting. This is the unambiguous form: one array element per segment, entity ids
|
|
18
|
+
* kept whole however many slashes they contain.
|
|
19
|
+
*
|
|
20
|
+
* For any backend whose ids cannot contain "/" this is exactly `path.split("/")`, so
|
|
21
|
+
* delegates that do not care can keep using `path`. Delegates that do should prefer
|
|
22
|
+
* `pathSegments ?? path.split("/")`.
|
|
23
|
+
*/
|
|
24
|
+
pathSegments?: string[];
|
|
11
25
|
entityId: string;
|
|
12
26
|
databaseId?: string;
|
|
13
27
|
collection?: EntityCollection<M, any>
|
|
@@ -28,6 +42,20 @@ export type ListenEntityProps<M extends Record<string, any> = any> =
|
|
|
28
42
|
*/
|
|
29
43
|
export interface FetchCollectionProps<M extends Record<string, any> = any> {
|
|
30
44
|
path: string;
|
|
45
|
+
/**
|
|
46
|
+
* The path split at its real segment boundaries, e.g.
|
|
47
|
+
* `["nodes", "node/42", "edges"]`.
|
|
48
|
+
*
|
|
49
|
+
* `path` is a single flattened string, so a parent entity id containing "/" cannot be
|
|
50
|
+
* recovered from it — `"nodes/node/42/edges"` is indistinguishable from a three-level
|
|
51
|
+
* nesting. This is the unambiguous form: one array element per segment, entity ids
|
|
52
|
+
* kept whole however many slashes they contain.
|
|
53
|
+
*
|
|
54
|
+
* For any backend whose ids cannot contain "/" this is exactly `path.split("/")`, so
|
|
55
|
+
* delegates that do not care can keep using `path`. Delegates that do should prefer
|
|
56
|
+
* `pathSegments ?? path.split("/")`.
|
|
57
|
+
*/
|
|
58
|
+
pathSegments?: string[];
|
|
31
59
|
collection?: EntityCollection<M> | ResolvedEntityCollection<M>;
|
|
32
60
|
filter?: FilterValues<Extract<keyof M, string>>,
|
|
33
61
|
limit?: number;
|
|
@@ -52,6 +80,20 @@ export type ListenCollectionProps<M extends Record<string, any> = any> =
|
|
|
52
80
|
*/
|
|
53
81
|
export interface SaveEntityProps<M extends Record<string, any> = any> {
|
|
54
82
|
path: string;
|
|
83
|
+
/**
|
|
84
|
+
* The path split at its real segment boundaries, e.g.
|
|
85
|
+
* `["nodes", "node/42", "edges"]`.
|
|
86
|
+
*
|
|
87
|
+
* `path` is a single flattened string, so a parent entity id containing "/" cannot be
|
|
88
|
+
* recovered from it — `"nodes/node/42/edges"` is indistinguishable from a three-level
|
|
89
|
+
* nesting. This is the unambiguous form: one array element per segment, entity ids
|
|
90
|
+
* kept whole however many slashes they contain.
|
|
91
|
+
*
|
|
92
|
+
* For any backend whose ids cannot contain "/" this is exactly `path.split("/")`, so
|
|
93
|
+
* delegates that do not care can keep using `path`. Delegates that do should prefer
|
|
94
|
+
* `pathSegments ?? path.split("/")`.
|
|
95
|
+
*/
|
|
96
|
+
pathSegments?: string[];
|
|
55
97
|
values: Partial<EntityValues<M>>;
|
|
56
98
|
entityId?: string; // can be empty for new entities
|
|
57
99
|
previousValues?: Partial<EntityValues<M>>;
|
|
@@ -64,6 +106,11 @@ export interface SaveEntityProps<M extends Record<string, any> = any> {
|
|
|
64
106
|
*/
|
|
65
107
|
export interface DeleteEntityProps<M extends Record<string, any> = any> {
|
|
66
108
|
entity: Entity<M>;
|
|
109
|
+
/**
|
|
110
|
+
* `entity.path` split at its real segment boundaries, when the caller knows them.
|
|
111
|
+
* Never derived from `entity.path` — see `pathSegments` on FetchCollectionProps.
|
|
112
|
+
*/
|
|
113
|
+
pathSegments?: string[];
|
|
67
114
|
collection?: EntityCollection<M> | ResolvedEntityCollection<M>;
|
|
68
115
|
}
|
|
69
116
|
|
|
@@ -203,13 +250,19 @@ export interface DataSource {
|
|
|
203
250
|
name: string,
|
|
204
251
|
value: any,
|
|
205
252
|
entityId?: string,
|
|
206
|
-
collection?: EntityCollection
|
|
253
|
+
collection?: EntityCollection,
|
|
254
|
+
/**
|
|
255
|
+
* Appended last, and optional, so existing implementations and callers keep
|
|
256
|
+
* working unchanged — a function declaring fewer parameters stays assignable.
|
|
257
|
+
* See `pathSegments` on FetchCollectionProps.
|
|
258
|
+
*/
|
|
259
|
+
pathSegments?: string[]
|
|
207
260
|
): Promise<boolean>;
|
|
208
261
|
|
|
209
262
|
/**
|
|
210
263
|
* Generate an id for a new entity
|
|
211
264
|
*/
|
|
212
|
-
generateEntityId(path: string, collection: EntityCollection): string;
|
|
265
|
+
generateEntityId(path: string, collection: EntityCollection, pathSegments?: string[]): string;
|
|
213
266
|
|
|
214
267
|
/**
|
|
215
268
|
* Count the number of entities in a collection
|
|
@@ -230,6 +283,10 @@ export interface DataSource {
|
|
|
230
283
|
initTextSearch?: (props: {
|
|
231
284
|
context: FireCMSContext,
|
|
232
285
|
path: string,
|
|
286
|
+
/**
|
|
287
|
+
* `path` split at its real segment boundaries, when known. Never derived from `path`.
|
|
288
|
+
*/
|
|
289
|
+
pathSegments?: string[],
|
|
233
290
|
collection: EntityCollection,
|
|
234
291
|
parentCollectionIds?: string[]
|
|
235
292
|
}) => Promise<boolean>;
|
|
@@ -237,6 +294,8 @@ export interface DataSource {
|
|
|
237
294
|
}
|
|
238
295
|
|
|
239
296
|
export type FilterCombinationValidProps = {
|
|
297
|
+
/** `path` split at its real segment boundaries — see `pathSegments` on FetchCollectionProps. */
|
|
298
|
+
pathSegments?: string[];
|
|
240
299
|
path: string;
|
|
241
300
|
collection: EntityCollection<any>;
|
|
242
301
|
filterValues: FilterValues<any>;
|
|
@@ -366,12 +425,12 @@ export interface DataSourceDelegate {
|
|
|
366
425
|
* @param collection
|
|
367
426
|
* @return `true` if there are no other fields besides the given entity
|
|
368
427
|
*/
|
|
369
|
-
checkUniqueField(path: string, name: string, value: any, entityId?: string, collection?: EntityCollection): Promise<boolean>;
|
|
428
|
+
checkUniqueField(path: string, name: string, value: any, entityId?: string, collection?: EntityCollection, pathSegments?: string[]): Promise<boolean>;
|
|
370
429
|
|
|
371
430
|
/**
|
|
372
431
|
* Generate an id for a new entity
|
|
373
432
|
*/
|
|
374
|
-
generateEntityId(path: string, collection?: EntityCollection): string;
|
|
433
|
+
generateEntityId(path: string, collection?: EntityCollection, pathSegments?: string[]): string;
|
|
375
434
|
|
|
376
435
|
/**
|
|
377
436
|
* Count the number of entities in a collection
|
|
@@ -398,6 +457,10 @@ export interface DataSourceDelegate {
|
|
|
398
457
|
initTextSearch?: (props: {
|
|
399
458
|
context: FireCMSContext,
|
|
400
459
|
path: string,
|
|
460
|
+
/**
|
|
461
|
+
* `path` split at its real segment boundaries, when known. Never derived from `path`.
|
|
462
|
+
*/
|
|
463
|
+
pathSegments?: string[],
|
|
401
464
|
databaseId?: string,
|
|
402
465
|
collection: EntityCollection,
|
|
403
466
|
parentCollectionIds?: string[]
|
package/src/types/entities.ts
CHANGED
|
@@ -21,6 +21,17 @@ export interface Entity<M extends object = any> {
|
|
|
21
21
|
*/
|
|
22
22
|
path: string;
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* `path` split at its real segment boundaries, e.g. `["nodes", "node/42", "edges"]`.
|
|
26
|
+
*
|
|
27
|
+
* `path` is a single flattened string, so a parent entity id containing "/" cannot be
|
|
28
|
+
* recovered from it. This keeps each segment whole.
|
|
29
|
+
*
|
|
30
|
+
* Optional, and never derived by splitting `path` — a guess would be wrong in exactly
|
|
31
|
+
* the case the field exists for. Absent means "not known here", not "no slashes".
|
|
32
|
+
*/
|
|
33
|
+
pathSegments?: string[];
|
|
34
|
+
|
|
24
35
|
/**
|
|
25
36
|
* Current values
|
|
26
37
|
*/
|
|
@@ -55,10 +66,22 @@ export class EntityReference {
|
|
|
55
66
|
*/
|
|
56
67
|
readonly databaseId?: string;
|
|
57
68
|
|
|
58
|
-
|
|
69
|
+
/**
|
|
70
|
+
* `path` split at its real segment boundaries, e.g. `["nodes", "node/42", "edges"]`.
|
|
71
|
+
*
|
|
72
|
+
* `path` is a single flattened string, so a parent entity id containing "/" cannot be
|
|
73
|
+
* recovered from it. This keeps each segment whole.
|
|
74
|
+
*
|
|
75
|
+
* Optional, and never derived by splitting `path` — a guess would be wrong in exactly
|
|
76
|
+
* the case the field exists for. Absent means "not known here", not "no slashes".
|
|
77
|
+
*/
|
|
78
|
+
readonly pathSegments?: string[];
|
|
79
|
+
|
|
80
|
+
constructor(id: string, path: string, databaseId?: string, pathSegments?: string[]) {
|
|
59
81
|
this.id = id;
|
|
60
82
|
this.path = path;
|
|
61
83
|
this.databaseId = databaseId;
|
|
84
|
+
this.pathSegments = pathSegments;
|
|
62
85
|
}
|
|
63
86
|
|
|
64
87
|
get pathWithId() {
|
|
@@ -65,6 +65,12 @@ export type EntityActionClickProps<M extends object, USER extends User = User> =
|
|
|
65
65
|
context: FireCMSContext<USER>;
|
|
66
66
|
|
|
67
67
|
fullPath?: string;
|
|
68
|
+
/**
|
|
69
|
+
* `fullPath` split at its real segment boundaries, e.g. `["nodes", "node/42", "edges"]`,
|
|
70
|
+
* when the caller knows them. Absent means "not known here" — never derived from
|
|
71
|
+
* `fullPath`, since a parent id may itself contain "/".
|
|
72
|
+
*/
|
|
73
|
+
pathSegments?: string[];
|
|
68
74
|
fullIdPath?: string;
|
|
69
75
|
collection?: EntityCollection<M>;
|
|
70
76
|
|
|
@@ -86,6 +86,14 @@ export interface EntityOnFetchProps<M extends Record<string, any> = any, USER ex
|
|
|
86
86
|
*/
|
|
87
87
|
path: string;
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* `path` split at its real segment boundaries, e.g. `["nodes", "node/42", "edges"]`.
|
|
91
|
+
*
|
|
92
|
+
* Optional, and never derived by splitting `path` — a parent entity id may itself
|
|
93
|
+
* contain "/". Absent means "not known here", not "no slashes".
|
|
94
|
+
*/
|
|
95
|
+
pathSegments?: string[];
|
|
96
|
+
|
|
89
97
|
/**
|
|
90
98
|
* Fetched entity
|
|
91
99
|
*/
|
|
@@ -133,6 +141,14 @@ export interface EntityOnSaveProps<M extends Record<string, any> = any, USER ext
|
|
|
133
141
|
*/
|
|
134
142
|
path: string;
|
|
135
143
|
|
|
144
|
+
/**
|
|
145
|
+
* `path` split at its real segment boundaries, e.g. `["nodes", "node/42", "edges"]`.
|
|
146
|
+
*
|
|
147
|
+
* Optional, and never derived by splitting `path` — a parent entity id may itself
|
|
148
|
+
* contain "/". Absent means "not known here", not "no slashes".
|
|
149
|
+
*/
|
|
150
|
+
pathSegments?: string[];
|
|
151
|
+
|
|
136
152
|
/**
|
|
137
153
|
* Full path where this entity is being saved, with alias resolved
|
|
138
154
|
*/
|
|
@@ -180,6 +196,14 @@ export interface EntityOnDeleteProps<M extends Record<string, any> = any, USER e
|
|
|
180
196
|
*/
|
|
181
197
|
path: string;
|
|
182
198
|
|
|
199
|
+
/**
|
|
200
|
+
* `path` split at its real segment boundaries, e.g. `["nodes", "node/42", "edges"]`.
|
|
201
|
+
*
|
|
202
|
+
* Optional, and never derived by splitting `path` — a parent entity id may itself
|
|
203
|
+
* contain "/". Absent means "not known here", not "no slashes".
|
|
204
|
+
*/
|
|
205
|
+
pathSegments?: string[];
|
|
206
|
+
|
|
183
207
|
/**
|
|
184
208
|
* Deleted entity id
|
|
185
209
|
*/
|
package/src/types/navigation.ts
CHANGED
|
@@ -57,8 +57,12 @@ export type NavigationController<EC extends EntityCollection = EntityCollection<
|
|
|
57
57
|
/**
|
|
58
58
|
* Get the collection configuration for a given path.
|
|
59
59
|
* The collection is resolved from the given path or alias.
|
|
60
|
+
*
|
|
61
|
+
* Pass `pathSegments` when you have them: without them the path is split on "/" and
|
|
62
|
+
* asserted to have an odd number of parts, which a chain containing a slash-bearing
|
|
63
|
+
* entity id fails — it throws instead of resolving.
|
|
60
64
|
*/
|
|
61
|
-
getCollection: (pathOrId: string, includeUserOverride?: boolean) => EC | undefined;
|
|
65
|
+
getCollection: (pathOrId: string, includeUserOverride?: boolean, pathSegments?: string[]) => EC | undefined;
|
|
62
66
|
|
|
63
67
|
/**
|
|
64
68
|
* Get the top level collection configuration for a given id
|
|
@@ -118,9 +122,30 @@ export type NavigationController<EC extends EntityCollection = EntityCollection<
|
|
|
118
122
|
/**
|
|
119
123
|
* Turn a path with collection ids into a resolved path.
|
|
120
124
|
* The ids (typically used in urls) will be replaced with relative paths (typically used in database paths)
|
|
125
|
+
*
|
|
126
|
+
* Pass `pathSegments` whenever you have them. Without them this has to find the entity
|
|
127
|
+
* ids inside the flattened string by reading up to the next "/", which is wrong for any
|
|
128
|
+
* id that contains one — the chain then shifts by a segment and resolution fails.
|
|
129
|
+
*
|
|
121
130
|
* @param pathWithAliases
|
|
131
|
+
* @param pathSegments `pathWithAliases` split at its real segment boundaries, if known
|
|
122
132
|
*/
|
|
123
|
-
resolveIdsFrom: (pathWithAliases: string) => string;
|
|
133
|
+
resolveIdsFrom: (pathWithAliases: string, pathSegments?: string[]) => string;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* The segment-wise counterpart of {@link resolveIdsFrom}: replaces collection ids with
|
|
137
|
+
* their real paths while carrying every entity id through whole, slashes included.
|
|
138
|
+
*
|
|
139
|
+
* Idempotent — segments that are already resolved pass through unchanged.
|
|
140
|
+
*
|
|
141
|
+
* Optional so that a `navigationController` built against an earlier version keeps
|
|
142
|
+
* working: callers fall back to using the segments as given, which is what happened
|
|
143
|
+
* before this method existed. Controllers built by `useBuildNavigationController`
|
|
144
|
+
* always provide it.
|
|
145
|
+
*
|
|
146
|
+
* @param pathSegments
|
|
147
|
+
*/
|
|
148
|
+
resolveSegmentsFrom?: (pathSegments: string[]) => string[];
|
|
124
149
|
|
|
125
150
|
/**
|
|
126
151
|
* Call this method to recalculate the navigation
|
|
@@ -128,16 +153,21 @@ export type NavigationController<EC extends EntityCollection = EntityCollection<
|
|
|
128
153
|
refreshNavigation: () => void;
|
|
129
154
|
|
|
130
155
|
/**
|
|
131
|
-
* Retrieve all the related parent references for a given path
|
|
156
|
+
* Retrieve all the related parent references for a given path.
|
|
157
|
+
*
|
|
158
|
+
* `path` is expected escaped, as it comes from the URL. Pass `pathSegments` when the
|
|
159
|
+
* path at hand is a raw datasource path, whose ids may contain a bare "/".
|
|
160
|
+
*
|
|
132
161
|
* @param path
|
|
162
|
+
* @param pathSegments `path` split at its real segment boundaries, with raw ids
|
|
133
163
|
*/
|
|
134
|
-
getParentReferencesFromPath: (path: string) => EntityReference[];
|
|
164
|
+
getParentReferencesFromPath: (path: string, pathSegments?: string[]) => EntityReference[];
|
|
135
165
|
|
|
136
166
|
/**
|
|
137
167
|
* Retrieve all the related parent collection ids for a given path
|
|
138
168
|
* @param path
|
|
139
169
|
*/
|
|
140
|
-
getParentCollectionIds: (path: string) => string[];
|
|
170
|
+
getParentCollectionIds: (path: string, pathSegments?: string[]) => string[];
|
|
141
171
|
|
|
142
172
|
/**
|
|
143
173
|
* Resolve paths from a list of ids
|