fix: Etiketten-Import zeigt konkreten Grund statt generischem Fehler
Eine KI-erzeugte JSON ohne Kenntnis des echten Schemas (z.B. eigene Feldnamen wie xMm/yMm oder erfundene Elementtypen wie rectangle/svg) scheiterte bisher mit "Datei enthält keine gültige Etikettenvorlage" ohne Hinweis, was falsch ist. Jetzt wird pro Element benannt, was fehlt oder welcher Typ nicht unterstützt wird.
This commit is contained in:
1 parent
c6941a797f
commit
abe1f6e8cf
1 file changed
+35
-16
+35
-16
@@ -86,20 +86,35 @@ export interface LabelDesignerValue {
|
|||||||
// Loose runtime check for imported JSON (own export, or hand/AI-authored) -
|
// Loose runtime check for imported JSON (own export, or hand/AI-authored) -
|
||||||
// only verifies the shape is plausible enough to load into the canvas;
|
// only verifies the shape is plausible enough to load into the canvas;
|
||||||
// the backend's own DTO validation is still the real boundary check on save.
|
// the backend's own DTO validation is still the real boundary check on save.
|
||||||
function isLabelElementArray(value: unknown): value is LabelElement[] {
|
// Returns a specific reason per bad element instead of a flat true/false, so
|
||||||
return (
|
// an AI-authored file that guessed the wrong schema tells the user exactly
|
||||||
Array.isArray(value) &&
|
// what to fix rather than a generic "invalid file".
|
||||||
value.every(
|
function validateImportedElements(value: unknown): { elements: LabelElement[] } | { errors: string[] } {
|
||||||
(item) =>
|
if (!Array.isArray(value)) {
|
||||||
typeof item === "object" &&
|
return { errors: ['Die Datei enthält kein "elements"-Array.'] };
|
||||||
item !== null &&
|
}
|
||||||
"id" in item &&
|
const errors: string[] = [];
|
||||||
"type" in item &&
|
value.forEach((item, index) => {
|
||||||
"x" in item &&
|
const label = typeof item === "object" && item && "id" in item ? String((item as { id: unknown }).id) : `#${index + 1}`;
|
||||||
"y" in item &&
|
if (typeof item !== "object" || item === null) {
|
||||||
ELEMENT_TYPES.includes((item as { type: unknown }).type as (typeof ELEMENT_TYPES)[number]),
|
errors.push(`Element ${label}: kein Objekt.`);
|
||||||
)
|
return;
|
||||||
|
}
|
||||||
|
if (!("x" in item) || !("y" in item)) {
|
||||||
|
errors.push(`Element ${label}: "x"/"y" fehlen (nicht "xMm"/"yMm").`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const type = (item as { type?: unknown }).type;
|
||||||
|
if (!ELEMENT_TYPES.includes(type as (typeof ELEMENT_TYPES)[number])) {
|
||||||
|
errors.push(
|
||||||
|
`Element ${label}: Typ "${String(type)}" wird nicht unterstützt (nur ${ELEMENT_TYPES.join(", ")}).`,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (errors.length > 0) {
|
||||||
|
return { errors };
|
||||||
|
}
|
||||||
|
return { elements: value as LabelElement[] };
|
||||||
}
|
}
|
||||||
|
|
||||||
function slugify(name: string): string {
|
function slugify(name: string): string {
|
||||||
@@ -235,11 +250,15 @@ export function LabelDesigner({ initial, onSubmit, submitLabel }: LabelDesignerP
|
|||||||
const importedElements = Array.isArray(parsed)
|
const importedElements = Array.isArray(parsed)
|
||||||
? parsed
|
? parsed
|
||||||
: (parsed as { elements?: unknown })?.elements;
|
: (parsed as { elements?: unknown })?.elements;
|
||||||
if (!isLabelElementArray(importedElements)) {
|
const result = validateImportedElements(importedElements);
|
||||||
toast.error("Datei enthält keine gültige Etikettenvorlage.");
|
if ("errors" in result) {
|
||||||
|
toast.error("Vorlage konnte nicht importiert werden", {
|
||||||
|
description: result.errors.slice(0, 5).join(" · "),
|
||||||
|
duration: 15000,
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setElements(importedElements.map((element) => ({ ...element, id: newId() })));
|
setElements(result.elements.map((element) => ({ ...element, id: newId() })));
|
||||||
if (!Array.isArray(parsed)) {
|
if (!Array.isArray(parsed)) {
|
||||||
const value = parsed as Partial<LabelDesignerValue>;
|
const value = parsed as Partial<LabelDesignerValue>;
|
||||||
if (typeof value.name === "string" && value.name && !name) setName(value.name);
|
if (typeof value.name === "string" && value.name && !name) setName(value.name);
|
||||||
|
|||||||
Reference in new issue
Block a user