Skip to content

Commit 20f5e4f

Browse files
authored
fix(import): group project-import warnings by reason (#1910)
* fix(import): group project-import warnings by reason A File Geodatabase-backed ArcGIS Pro project made the import dialog list 257 separate lines, each reading "The layer's data format is not supported". Every one of them had the same root cause, but nothing in the dialog said so. Warnings are now grouped by the message the user actually sees, largest group first, so that project reads as one line ("245 layers: ...") with the layer names behind a toggle. Grouping on the rendered message rather than on the internal reason keeps two layer types that interpolate different text apart, and merges anything that would otherwise render two identical lines. The QGIS import dialog shares the component and gets the same treatment. FileGDB sources also get their own reason instead of a generic "format", so the dialog names the format and points at Add Data -> File Geodatabase (GDB), which the desktop build supports. Ref #1904 (item 2) * Address Claude review feedback - Cover the `extension(workspace) === "gdb"` branch of the geodatabase check with its own test, for both the vector and raster resolvers. The earlier raster test only exercised the workspaceFactory branch. - Recognize a `.gdb` workspace path in `resolveDataSource` too, so the two resolvers agree on what a geodatabase is. A vector connection that names no workspaceFactory previously fell through to a bare "format". * Address CodeRabbit review feedback - Fix the Vietnamese `arcgisImportReason.format` string, which read "Bản đồ nhỏ" ("Minimap"). Pre-existing, but it is one of the messages this dialog groups, so every non-geodatabase unsupported layer in a Vietnamese session showed unrelated text. - Say in the docs that the geodatabase reason covers rasters as well as feature layers. The suggested wording (add "those layers" via Add Data → File Geodatabase) would have overpromised: that source filters to feature classes carrying geometry and does not read geodatabase raster datasets, so the sentence now names the limit instead of widening. * Address review feedback: separate the geodatabase raster reason - Report a raster stored in a .gdb under its own reason. It previously shared the feature-class message, which sends the user to Add Data -> File Geodatabase (GDB) -- a source that lists only feature classes carrying geometry (GdbSource.tsx filters on geometry_type) and cannot open a raster dataset. The raster message points at exporting to GeoTIFF instead. Translated in all 19 catalogs. This also settles the same concern raised against the Vietnamese file-geodatabase string: that message now only ever reaches feature layers, in every locale. - Pin the ordering of the geodatabase check against the missing-dataset guard with a test. A .gdb workspace with no dataset name reports the geodatabase rather than "missing-source", matching what the vector resolver already did for the same connection: naming the geodatabase is the actionable half, and the absent dataset name would not change what the user has to do. - Link the Show/Hide layer names toggle to the list it reveals with aria-controls, alongside the aria-expanded it already set. * Keep the aria-controls target in the DOM when collapsed The names list was only rendered while expanded, so the toggle's aria-controls pointed at a missing id in the collapsed state. It is now always rendered and hidden with `hidden`, which keeps it out of the accessibility tree while leaving the reference resolvable. * Drop the unused sample field from the warning groups Only the test read it; the dialog consumes message and layerNames. The group type no longer needs a type parameter either.
1 parent 722206a commit 20f5e4f

26 files changed

Lines changed: 497 additions & 27 deletions
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { useId, useMemo, useState } from "react";
2+
import { useTranslation } from "react-i18next";
3+
import { groupImportWarnings, type ImportWarningLike } from "../../../lib/import-warning-groups";
4+
5+
interface ImportWarningListProps<T extends ImportWarningLike> {
6+
warnings: T[];
7+
/** Renders a warning's localized message. */
8+
describe: (warning: T) => string;
9+
}
10+
11+
/**
12+
* The list of layers a project importer could not load, grouped by message.
13+
*
14+
* Shared by the QGIS and ArcGIS Pro import dialogs. Groups of more than one
15+
* layer collapse to a count plus their shared message, with the layer names
16+
* behind a toggle, so a project where hundreds of layers fail the same way
17+
* reads as one line instead of hundreds (GeoLibre#1904).
18+
*/
19+
export function ImportWarningList<T extends ImportWarningLike>({
20+
warnings,
21+
describe,
22+
}: ImportWarningListProps<T>) {
23+
const { t } = useTranslation();
24+
const listId = useId();
25+
const [expanded, setExpanded] = useState<Set<string>>(() => new Set());
26+
const groups = useMemo(() => groupImportWarnings(warnings, describe), [warnings, describe]);
27+
28+
return (
29+
<ul className="max-h-64 space-y-2 overflow-y-auto text-sm">
30+
{groups.map((group, index) => {
31+
const isExpanded = expanded.has(group.message);
32+
// Indexed rather than keyed on the message, which is free text.
33+
const namesId = `${listId}-names-${index}`;
34+
return (
35+
<li key={group.message}>
36+
<strong>
37+
{group.layerNames.length === 1
38+
? `${group.layerNames[0]}:`
39+
: `${t("toolbar.item.importWarningLayerCount", {
40+
count: group.layerNames.length,
41+
})}:`}
42+
</strong>{" "}
43+
{group.message}
44+
{group.layerNames.length > 1 ? (
45+
<div className="mt-0.5">
46+
<button
47+
type="button"
48+
aria-expanded={isExpanded}
49+
aria-controls={namesId}
50+
className="text-xs text-primary underline underline-offset-2"
51+
onClick={() =>
52+
setExpanded((current) => {
53+
const next = new Set(current);
54+
if (!next.delete(group.message)) next.add(group.message);
55+
return next;
56+
})
57+
}
58+
>
59+
{isExpanded ? t("toolbar.item.hideLayerNames") : t("toolbar.item.showLayerNames")}
60+
</button>
61+
{/* Rendered even when collapsed, and hidden with `hidden`, so
62+
the button's aria-controls always resolves to a real
63+
element. `hidden` keeps it out of the accessibility tree. */}
64+
<p
65+
id={namesId}
66+
hidden={!isExpanded}
67+
className="mt-1 break-words text-xs text-muted-foreground"
68+
>
69+
{group.layerNames.join(", ")}
70+
</p>
71+
</div>
72+
) : null}
73+
</li>
74+
);
75+
})}
76+
</ul>
77+
);
78+
}

apps/geolibre-desktop/src/components/layout/toolbar/ProjectFileDialogs.tsx

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ import {
99
Input,
1010
Label,
1111
} from "@geolibre/ui";
12-
import { useRef } from "react";
12+
import { useCallback, useRef } from "react";
1313
import { useTranslation } from "react-i18next";
1414
import {
1515
LARGE_EMBED_WARNING_BYTES,
1616
type ProjectFileActions,
1717
} from "../../../hooks/useProjectFileActions";
18+
import type { ArcgisProjectImportWarning } from "../../../lib/arcgis-project-import";
19+
import type { QgisProjectImportWarning } from "../../../lib/qgis-project-import";
1820
import { SaveTemplateDialog } from "../SaveTemplateDialog";
21+
import { ImportWarningList } from "./ImportWarningList";
1922

2023
interface ProjectFileDialogsProps {
2124
projectFiles: ProjectFileActions;
@@ -35,6 +38,22 @@ export function ProjectFileDialogs({ projectFiles }: ProjectFileDialogsProps) {
3538
}
3639
const saveNameLabels = projectFiles.saveNamePrompt ?? lastSaveNamePrompt.current;
3740

41+
// Stable identities so the warning lists regroup only when the warnings change.
42+
const describeArcgisWarning = useCallback(
43+
(warning: ArcgisProjectImportWarning) =>
44+
t(`toolbar.item.arcgisImportReason.${warning.reason}`, {
45+
layerType: warning.layerType || t("toolbar.item.arcgisUnknownLayerType"),
46+
}),
47+
[t],
48+
);
49+
const describeQgisWarning = useCallback(
50+
(warning: QgisProjectImportWarning) =>
51+
t(`toolbar.item.qgisImportReason.${warning.reason}`, {
52+
provider: warning.provider || t("toolbar.item.qgisUnknownProvider"),
53+
}),
54+
[t],
55+
);
56+
3857
return (
3958
<>
4059
<Dialog
@@ -94,16 +113,10 @@ export function ProjectFileDialogs({ projectFiles }: ProjectFileDialogsProps) {
94113
})}
95114
</DialogDescription>
96115
</DialogHeader>
97-
<ul className="max-h-64 space-y-2 overflow-y-auto text-sm">
98-
{projectFiles.arcgisImportWarnings?.map((warning, index) => (
99-
<li key={`${warning.layerName}-${index}`}>
100-
<strong>{warning.layerName}:</strong>{" "}
101-
{t(`toolbar.item.arcgisImportReason.${warning.reason}`, {
102-
layerType: warning.layerType || t("toolbar.item.arcgisUnknownLayerType"),
103-
})}
104-
</li>
105-
))}
106-
</ul>
116+
<ImportWarningList
117+
warnings={projectFiles.arcgisImportWarnings ?? []}
118+
describe={describeArcgisWarning}
119+
/>
107120
<div className="flex justify-end">
108121
<Button onClick={() => projectFiles.setArcgisImportWarnings(null)}>
109122
{t("common.ok")}
@@ -144,16 +157,10 @@ export function ProjectFileDialogs({ projectFiles }: ProjectFileDialogsProps) {
144157
})}
145158
</DialogDescription>
146159
</DialogHeader>
147-
<ul className="max-h-64 space-y-2 overflow-y-auto text-sm">
148-
{projectFiles.qgisImportWarnings?.map((warning, index) => (
149-
<li key={`${warning.layerName}-${index}`}>
150-
<strong>{warning.layerName}:</strong>{" "}
151-
{t(`toolbar.item.qgisImportReason.${warning.reason}`, {
152-
provider: warning.provider || t("toolbar.item.qgisUnknownProvider"),
153-
})}
154-
</li>
155-
))}
156-
</ul>
160+
<ImportWarningList
161+
warnings={projectFiles.qgisImportWarnings ?? []}
162+
describe={describeQgisWarning}
163+
/>
157164
<div className="flex justify-end">
158165
<Button onClick={() => projectFiles.setQgisImportWarnings(null)}>
159166
{t("common.ok")}

apps/geolibre-desktop/src/i18n/locales/ar.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2806,10 +2806,20 @@
28062806
"arcgisImportWarnings_zero": "تم استيراد المشروع، لكن تعذّر تحميل {{count}} من الطبقات.",
28072807
"arcgisImportWarnings_other": "تم استيراد المشروع، لكن تعذّر تحميل {{count}} طبقة.",
28082808
"arcgisUnknownLayerType": "غير معروف",
2809+
"importWarningLayerCount_zero": "{{count}} طبقة",
2810+
"importWarningLayerCount_one": "{{count}} طبقة",
2811+
"importWarningLayerCount_two": "{{count}} من الطبقات",
2812+
"importWarningLayerCount_few": "{{count}} طبقات",
2813+
"importWarningLayerCount_many": "{{count}} طبقةً",
2814+
"importWarningLayerCount_other": "{{count}} طبقة",
2815+
"showLayerNames": "عرض أسماء الطبقات",
2816+
"hideLayerNames": "إخفاء أسماء الطبقات",
28092817
"arcgisImportReason": {
28102818
"layer-type": "نوع الطبقة {{layerType}} غير مدعوم.",
28112819
"missing-source": "لا تحتوي الطبقة على مصدر بيانات محلي قابل للقراءة.",
28122820
"format": "تنسيق بيانات الطبقة غير مدعوم.",
2821+
"file-geodatabase": "لا تُحمَّل مصادر File Geodatabase (‎.gdb) من المشاريع. في GeoLibre Desktop أضِفها من إضافة بيانات ← قاعدة بيانات جغرافية ملفية (GDB).",
2822+
"file-geodatabase-raster": "مجموعات البيانات النقطية المخزَّنة في File Geodatabase (‎.gdb) غير مدعومة. صدِّر الراستر إلى GeoTIFF ثم أضِفه كطبقة نقطية.",
28132823
"network-path": "لا يتم تحميل مسارات مشاركة الشبكة لأسباب أمنية.",
28142824
"service": "طبقات خدمات ArcGIS داخل المشاريع غير مدعومة بعد.",
28152825
"browser-local-file": "تمت الإشارة إلى الملف المحلي، لكن المتصفحات لا تستطيع إعادة فتح مسارات بيانات ArcGIS Pro. استخدم GeoLibre Desktop لتحميله.",

apps/geolibre-desktop/src/i18n/locales/de.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,10 +2623,16 @@
26232623
"arcgisImportWarnings_one": "Das Projekt wurde importiert, aber {{count}} Ebene konnte nicht geladen werden.",
26242624
"arcgisImportWarnings_other": "Das Projekt wurde importiert, aber {{count}} Ebenen konnten nicht geladen werden.",
26252625
"arcgisUnknownLayerType": "unbekannt",
2626+
"importWarningLayerCount_one": "{{count}} Ebene",
2627+
"importWarningLayerCount_other": "{{count}} Ebenen",
2628+
"showLayerNames": "Ebenennamen anzeigen",
2629+
"hideLayerNames": "Ebenennamen ausblenden",
26262630
"arcgisImportReason": {
26272631
"layer-type": "Der Ebenentyp {{layerType}} wird nicht unterstützt.",
26282632
"missing-source": "Die Ebene hat keine lesbare lokale Datenquelle.",
26292633
"format": "Das Datenformat der Ebene wird nicht unterstützt.",
2634+
"file-geodatabase": "File-Geodatabase-Quellen (.gdb) werden nicht aus Projekten geladen. Fügen Sie sie in GeoLibre Desktop über Daten hinzufügen → File-Geodatabase (GDB) hinzu.",
2635+
"file-geodatabase-raster": "Rasterdatensätze in einer File-Geodatabase (.gdb) werden nicht unterstützt. Exportieren Sie das Raster nach GeoTIFF und fügen Sie es als Rasterebene hinzu.",
26302636
"network-path": "Netzwerkfreigabepfade werden aus Sicherheitsgründen nicht geladen.",
26312637
"service": "ArcGIS-Dienstebenen in Projekten werden noch nicht unterstützt.",
26322638
"browser-local-file": "Die lokale Datei wird referenziert, aber Browser können ArcGIS-Pro-Datenpfade nicht erneut öffnen. Verwenden Sie GeoLibre Desktop, um sie zu laden.",

apps/geolibre-desktop/src/i18n/locales/en.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,10 +2633,16 @@
26332633
"arcgisImportWarnings_one": "The project was imported, but {{count}} layer could not be loaded.",
26342634
"arcgisImportWarnings_other": "The project was imported, but {{count}} layers could not be loaded.",
26352635
"arcgisUnknownLayerType": "unknown",
2636+
"importWarningLayerCount_one": "{{count}} layer",
2637+
"importWarningLayerCount_other": "{{count}} layers",
2638+
"showLayerNames": "Show layer names",
2639+
"hideLayerNames": "Hide layer names",
26362640
"arcgisImportReason": {
26372641
"layer-type": "The {{layerType}} layer type is not supported.",
26382642
"missing-source": "The layer has no readable local data source.",
26392643
"format": "The layer's data format is not supported.",
2644+
"file-geodatabase": "File Geodatabase (.gdb) sources are not loaded from projects. In GeoLibre Desktop, add them with Add Data → File Geodatabase (GDB).",
2645+
"file-geodatabase-raster": "Raster datasets stored in a File Geodatabase (.gdb) are not supported. Export the raster to GeoTIFF and add it as a raster layer.",
26402646
"network-path": "Network share paths are not loaded for security reasons.",
26412647
"service": "ArcGIS service layers in projects are not supported yet.",
26422648
"browser-local-file": "The local file is referenced, but browsers cannot reopen ArcGIS Pro data paths. Use GeoLibre Desktop to load it.",

apps/geolibre-desktop/src/i18n/locales/es.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,10 +2623,16 @@
26232623
"arcgisImportWarnings_one": "El proyecto se importó, pero no se pudo cargar {{count}} capa.",
26242624
"arcgisImportWarnings_other": "El proyecto se importó, pero no se pudieron cargar {{count}} capas.",
26252625
"arcgisUnknownLayerType": "desconocido",
2626+
"importWarningLayerCount_one": "{{count}} capa",
2627+
"importWarningLayerCount_other": "{{count}} capas",
2628+
"showLayerNames": "Mostrar los nombres de las capas",
2629+
"hideLayerNames": "Ocultar los nombres de las capas",
26262630
"arcgisImportReason": {
26272631
"layer-type": "El tipo de capa {{layerType}} no es compatible.",
26282632
"missing-source": "La capa no tiene una fuente de datos local legible.",
26292633
"format": "El formato de datos de la capa no es compatible.",
2634+
"file-geodatabase": "Las fuentes de geodatabase de archivos (.gdb) no se cargan desde los proyectos. En GeoLibre Desktop, añádelas con Añadir datos → Geodatabase de archivos (GDB).",
2635+
"file-geodatabase-raster": "Los conjuntos de datos ráster almacenados en una geodatabase de archivos (.gdb) no son compatibles. Exporta el ráster a GeoTIFF y añádelo como capa ráster.",
26302636
"network-path": "Las rutas de recursos compartidos de red no se cargan por motivos de seguridad.",
26312637
"service": "Las capas de servicio de ArcGIS incluidas en proyectos aún no son compatibles.",
26322638
"browser-local-file": "Se hace referencia al archivo local, pero los navegadores no pueden volver a abrir rutas de datos de ArcGIS Pro. Use GeoLibre Desktop para cargarlo.",

apps/geolibre-desktop/src/i18n/locales/fa.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,10 +2623,16 @@
26232623
"arcgisImportWarnings_one": "پروژه وارد شد، اما بارگیری {{count}} لایه ممکن نشد.",
26242624
"arcgisImportWarnings_other": "پروژه وارد شد، اما بارگیری {{count}} لایه ممکن نشد.",
26252625
"arcgisUnknownLayerType": "ناشناخته",
2626+
"importWarningLayerCount_one": "{{count}} لایه",
2627+
"importWarningLayerCount_other": "{{count}} لایه",
2628+
"showLayerNames": "نمایش نام لایه‌ها",
2629+
"hideLayerNames": "پنهان کردن نام لایه‌ها",
26262630
"arcgisImportReason": {
26272631
"layer-type": "نوع لایهٔ {{layerType}} پشتیبانی نمی‌شود.",
26282632
"missing-source": "این لایه هیچ منبع دادهٔ محلی خواندنی ندارد.",
26292633
"format": "قالب دادهٔ این لایه پشتیبانی نمی‌شود.",
2634+
"file-geodatabase": "منابع File Geodatabase (‎.gdb) از پروژه‌ها بارگیری نمی‌شوند. در GeoLibre Desktop آن‌ها را از افزودن داده ← File Geodatabase (GDB) بیفزایید.",
2635+
"file-geodatabase-raster": "مجموعه‌داده‌های رستری ذخیره‌شده در File Geodatabase (‎.gdb) پشتیبانی نمی‌شوند. رستر را به GeoTIFF صادر کنید و آن را به‌عنوان لایهٔ رستری بیفزایید.",
26302636
"network-path": "مسیرهای اشتراک شبکه به دلایل امنیتی بارگیری نمی‌شوند.",
26312637
"service": "لایه‌های سرویس ArcGIS در پروژه‌ها هنوز پشتیبانی نمی‌شوند.",
26322638
"browser-local-file": "به فایل محلی ارجاع شده، اما مرورگرها نمی‌توانند مسیرهای دادهٔ ArcGIS Pro را دوباره باز کنند. برای بارگیری آن از GeoLibre Desktop استفاده کنید.",

apps/geolibre-desktop/src/i18n/locales/fr.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,10 +2623,16 @@
26232623
"arcgisImportWarnings_one": "Le projet a été importé, mais {{count}} couche n'a pas pu être chargée.",
26242624
"arcgisImportWarnings_other": "Le projet a été importé, mais {{count}} couches n'ont pas pu être chargées.",
26252625
"arcgisUnknownLayerType": "inconnu",
2626+
"importWarningLayerCount_one": "{{count}} couche",
2627+
"importWarningLayerCount_other": "{{count}} couches",
2628+
"showLayerNames": "Afficher les noms des couches",
2629+
"hideLayerNames": "Masquer les noms des couches",
26262630
"arcgisImportReason": {
26272631
"layer-type": "Le type de couche {{layerType}} n'est pas pris en charge.",
26282632
"missing-source": "La couche n'a pas de source de données locale lisible.",
26292633
"format": "Le format de données de la couche n'est pas pris en charge.",
2634+
"file-geodatabase": "Les sources File Geodatabase (.gdb) ne sont pas chargées depuis les projets. Dans GeoLibre Desktop, ajoutez-les via Ajouter des données → File Geodatabase (GDB).",
2635+
"file-geodatabase-raster": "Les jeux de données raster stockés dans une File Geodatabase (.gdb) ne sont pas pris en charge. Exportez le raster en GeoTIFF et ajoutez-le comme couche raster.",
26302636
"network-path": "Les chemins de partage réseau ne sont pas chargés pour des raisons de sécurité.",
26312637
"service": "Les couches de service ArcGIS présentes dans les projets ne sont pas encore prises en charge.",
26322638
"browser-local-file": "Le fichier local est référencé, mais les navigateurs ne peuvent pas rouvrir les chemins de données ArcGIS Pro. Utilisez GeoLibre Desktop pour le charger.",

apps/geolibre-desktop/src/i18n/locales/hi.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,10 +2623,16 @@
26232623
"arcgisImportWarnings_one": "प्रोजेक्ट आयात हो गया, लेकिन {{count}} लेयर लोड नहीं की जा सकी।",
26242624
"arcgisImportWarnings_other": "प्रोजेक्ट आयात हो गया, लेकिन {{count}} लेयर लोड नहीं की जा सकीं।",
26252625
"arcgisUnknownLayerType": "अज्ञात",
2626+
"importWarningLayerCount_one": "{{count}} लेयर",
2627+
"importWarningLayerCount_other": "{{count}} लेयर",
2628+
"showLayerNames": "लेयर के नाम दिखाएँ",
2629+
"hideLayerNames": "लेयर के नाम छिपाएँ",
26262630
"arcgisImportReason": {
26272631
"layer-type": "{{layerType}} लेयर प्रकार समर्थित नहीं है।",
26282632
"missing-source": "लेयर के पास कोई पठनीय स्थानीय डेटा स्रोत नहीं है।",
26292633
"format": "लेयर का डेटा स्वरूप समर्थित नहीं है।",
2634+
"file-geodatabase": "फ़ाइल जियोडेटाबेस (.gdb) स्रोत प्रोजेक्ट से लोड नहीं किए जाते। GeoLibre Desktop में उन्हें डेटा जोड़ें → फ़ाइल जियोडेटाबेस (GDB) से जोड़ें।",
2635+
"file-geodatabase-raster": "फ़ाइल जियोडेटाबेस (.gdb) में संग्रहीत रास्टर डेटासेट समर्थित नहीं हैं। रास्टर को GeoTIFF में निर्यात करें और उसे रास्टर लेयर के रूप में जोड़ें।",
26302636
"network-path": "सुरक्षा कारणों से नेटवर्क शेयर पथ लोड नहीं किए जाते।",
26312637
"service": "प्रोजेक्ट में मौजूद ArcGIS सेवा लेयर अभी समर्थित नहीं हैं।",
26322638
"browser-local-file": "स्थानीय फ़ाइल का संदर्भ है, लेकिन ब्राउज़र ArcGIS Pro डेटा पथ दोबारा नहीं खोल सकते। इसे लोड करने के लिए GeoLibre Desktop का उपयोग करें।",

0 commit comments

Comments
 (0)