From cad839aea0331462e5acea9ae7195db95b163bb9 Mon Sep 17 00:00:00 2001 From: BFLOWS Date: Thu, 23 Apr 2026 15:24:05 +0200 Subject: [PATCH] fix(ar1-admin): crash su error Pydantic (detail array) -> formatErrorDetail helper Bug: click 'Crea versione' con version vuota o invalida -> pagina bianca + 'error'. Causa: il BE restituisce 422 con detail come ARRAY Pydantic [{loc, msg, type}]. Il codice faceva detail: err?.detail || 'fallback' -> array passato a PrimeReact Toast -> React render 'Objects are not valid as a React child' -> crash unhandled. Fix: helper formatErrorDetail(detail, fallback) che normalizza: - string -> ritorna direttamente - array Pydantic -> 'loc.loc: msg; loc.loc: msg' (filtrato 'body') - object -> JSON.stringify - altro -> String(x) Applicato con regex a tutti i pattern 'err?.detail || "fallback"' nel file (tutti i toast show di errore nei vari handler: saveLayout, saveNewVersion, savePolicy, savePecRule, deletePecRule, saveEmail, runPreview, runBulk, loadXxx). --- src/modules/ar1/pages/Ar1AdminConfig.js | 42 +++++++++++++++++-------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/modules/ar1/pages/Ar1AdminConfig.js b/src/modules/ar1/pages/Ar1AdminConfig.js index 8dd67c2..ace11ed 100644 --- a/src/modules/ar1/pages/Ar1AdminConfig.js +++ b/src/modules/ar1/pages/Ar1AdminConfig.js @@ -58,8 +58,24 @@ const PEC_KIND_OPTIONS = [ { label: PEC_KIND_LABEL.AR1_BULK_MANUAL, value: 'AR1_BULK_MANUAL' } ]; + +// Normalizza il campo detail che puo essere string o array Pydantic [{loc, msg, type}] +const formatErrorDetail = (detail, fallback) => { + if (!detail) return fallback || 'Errore'; + if (typeof detail === 'string') return detail; + if (Array.isArray(detail)) { + return detail.map(e => { + const loc = Array.isArray(e.loc) ? e.loc.filter(x => x !== 'body').join('.') : ''; + const msg = e.msg || e.message || JSON.stringify(e); + return loc ? `${loc}: ${msg}` : msg; + }).join('; '); + } + if (typeof detail === 'object') return JSON.stringify(detail); + return String(detail); +}; + /** - * Ar1AdminConfig — configurazione AR1 per superadmin. (build 1776950454) + * Ar1AdminConfig — configurazione AR1 per superadmin. (build 1776950637) * URL: /ar1-admin * * 5 sezioni (TabView): @@ -163,19 +179,19 @@ const Ar1AdminConfig = () => { setLoadingTpl(true); Ar1Service.listTemplates( (resp) => { setTemplates(resp?.items || resp || []); setLoadingTpl(false); }, - (err) => { setLoadingTpl(false); if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Caricamento template fallito' }); } + (err) => { setLoadingTpl(false); if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Caricamento template fallito') }); } ); }; const loadPolicy = () => { Ar1Service.getPolicy( (resp) => { setPolicy(resp); setPolicyDraft(resp); }, - (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Caricamento policy fallito' }); } + (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Caricamento policy fallito') }); } ); }; const loadPecRules = () => { Ar1Service.listPecSchedule( (resp) => setPecRules(resp?.items || resp || []), - (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Caricamento regole fallito' }); } + (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Caricamento regole fallito') }); } ); }; const loadDocCategories = () => { @@ -192,7 +208,7 @@ const Ar1AdminConfig = () => { setAvailableVariables(resp?.available_variables || []); setLoadingEmail(false); }, - (err) => { setLoadingEmail(false); if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Caricamento testi fallito' }); } + (err) => { setLoadingEmail(false); if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Caricamento testi fallito') }); } ); }; @@ -268,7 +284,7 @@ const Ar1AdminConfig = () => { setEditLayoutOpen(false); loadTemplates(); }, - (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Salvataggio fallito' }); } + (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Salvataggio fallito') }); } ); }; @@ -292,7 +308,7 @@ const Ar1AdminConfig = () => { setNewVersionOpen(false); loadTemplates(); }, - (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Creazione fallita' }); } + (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Creazione fallita') }); } ); }; @@ -319,7 +335,7 @@ const Ar1AdminConfig = () => { }, (err) => { setSavingPolicy(false); - if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Salvataggio fallito' }); + if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Salvataggio fallito') }); } ); }; @@ -353,7 +369,7 @@ const Ar1AdminConfig = () => { setPecDialogOpen(false); loadPecRules(); }; - const onKo = (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Salvataggio fallito' }); }; + const onKo = (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Salvataggio fallito') }); }; if (pecEditing) Ar1Service.updatePecRule(pecEditing.id, payload, onOk, onKo); else Ar1Service.createPecRule(payload, onOk, onKo); }; @@ -372,7 +388,7 @@ const Ar1AdminConfig = () => { if (toast.current) toast.current.show({ severity: 'success', summary: 'Eliminata', detail: 'Regola eliminata' }); loadPecRules(); }, - (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Eliminazione fallita' }); } + (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Eliminazione fallita') }); } ); } }); @@ -400,7 +416,7 @@ const Ar1AdminConfig = () => { }, (err) => { setBulkRunning(false); - if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Invio fallito' }); + if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Invio fallito') }); } ); }; @@ -433,7 +449,7 @@ const Ar1AdminConfig = () => { setEditEmailOpen(false); loadEmailTemplates(); }, - (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Salvataggio fallito' }); } + (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Salvataggio fallito') }); } ); }; @@ -444,7 +460,7 @@ const Ar1AdminConfig = () => { setPreviewSubject(resp.subject); setPreviewHtml(resp.body_html); }, - (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: err?.detail || 'Anteprima fallita' }); } + (err) => { if (toast.current) toast.current.show({ severity: 'error', summary: 'Errore', detail: formatErrorDetail(err?.detail, 'Anteprima fallita') }); } ); };