Export
ExportDialog
Dialog di esportazione completo: scelta del modello, formato (Excel .xlsx o CSV .csv), PickList per i campi da esportare, progresso e download del file generato.
Crea internamente l'istanza di ImportExportApi (o usa quella passata via prop api) e la fornisce ai sotto-componenti via provide(IMPORT_EXPORT_API_KEY). Tutta la logica è delegata a useExport.
Props
| Prop | Tipo | Default | Descrizione |
|---|---|---|---|
visible | boolean | — | Visibilità dialog (v-model) |
baseUrl | string | — | URL base microservizi |
risorsa | string | — | Codice tecnico della risorsa da esportare, quello che va al servizio |
etichettaRisorsa | string | undefined | Nome della risorsa per l'utente (es. «Storico consegne»): compare nel salvataggio del modello (dalla 0.5.3) e dà il nome al file (dalla 0.6.0). Senza, si mostra il codice |
filtri | Record<string, unknown> | undefined | Filtri della pagina che apre il dialog, nel formato di node-excel-export (vedi Filtri e ordinamento). Dalla 0.6.0 |
ordinamento | OrdinamentoExport[] | undefined | Ordinamento della pagina, criteri in ordine di priorità. Dalla 0.6.0 |
nascondiCondivisione | boolean | false | Toglie «Condividi con altri utenti» dal salvataggio del modello, dove l'utente non è un amministratore (es. portale cliente). Dalla 0.5.6 |
api | ImportExportClient | undefined | Client custom (interfaccia). Utile per testing, mock o backend alternativi. Vedi Client interfaces |
Emits
| Evento | Payload | Descrizione |
|---|---|---|
update:visible | boolean | Apertura/chiusura |
exportCompleted | — | Export sincrono o asincrono terminato con stato === 'completato' |
error | Error | Errore catturato dall'ErrorBoundary interno |
Comportamento
- All'apertura del dialog (
visible: true) viene chiamatoloadMetadata(risorsa)che caricacampiDisponibilietemplates. - Cambi di
risorsamentre il dialog è aperto triggerano un re-load. - Alla chiusura viene chiamato
reset()diuseExport(azzera campi selezionati, formato, filtri e ordinamento del modello, template selezionato, polling).filtri,ordinamentoedetichettaRisorsarestano quelli delle props. - Il pulsante «Esporta» è disabilitato finché
campiSelezionati.length === 0. - Durante l'export «Esporta» diventa «Annulla», che invoca
cancelExport(chiama l'AbortController). - Se l'export è asincrono e il server risponde con
stato: 'in_corso', parte il polling tramiteusePolling. A completamento, il Blob viene scaricato automaticamente condownloadBlob. - I formati proposti sono quelli che
node-excel-exportsa produrre:xlsxecsv. Fino alla 0.5.5 c'era anche JSON, che il servizio rifiuta; un modello salvato allora conjson, applicato, lascia il formato corrente.
Nome del file
Con etichettaRisorsa il file si chiama <etichetta> <data>.<formato> («Storico consegne 2026-10-15.xlsx», dalla 0.6.0); senza, <risorsa>_<data>.<formato> («anagrafica_2026-10-15.xlsx», dalla 0.2.8). Lo stesso nome, senza estensione, va al servizio come fileName: è quello dei file degli export asincroni. Fino alla 0.2.7 il file si chiamava export.<formato>.
Filtri e ordinamento della pagina
<ExportDialog
v-model:visible="showExport"
:base-url="exportBaseUrl"
risorsa="v_tappe_cliente"
etichetta-risorsa="Storico consegne"
:filtri="{ datagiro: { operator: 'between', value: [dal, al] } }"
:ordinamento="[
{ campo: 'datagiro', direzione: 'desc' },
{ campo: 'orapartenza', direzione: 'desc', nulls: 'last' }
]"
/>
filtri e ordinamento sono quelli della pagina che apre il dialog: il file contiene le stesse righe che l'utente vede, nello stesso ordine. Valgono finché il modello applicato non porta i propri, e non finiscono nei modelli salvati: un modello salvato da una pagina filtrata non congela i filtri del momento.
Filtri — la libreria li passa intatti a node-excel-export, una chiave per colonna:
| Valore | Condizione SQL |
|---|---|
valore | = valore |
null | IS NULL |
[a, b, c] | IN (a, b, c) |
{ operator, value } | gt, gte, lt, lte, like |
{ operator: 'between', value: [da, a] } | BETWEEN da AND a |
[{ operator, value }, …] | tutte le condizioni insieme (AND) |
Dal e Al sulla stessa colonna vanno nella stessa chiave, perché un oggetto non può avere due chiavi datagiro:
{ datagiro: { operator: 'between', value: ['2026-10-01', '2026-10-15'] } }
// equivalente
{ datagiro: [{ operator: 'gte', value: '2026-10-01' }, { operator: 'lte', value: '2026-10-15' }] }
Ordinamento — tutti i criteri, in ordine di priorità (al massimo 10). nulls: 'first' | 'last' dice dove vanno i NULL, come nullsfirst / nullslast di PostgREST; senza, vale il default di PostgreSQL: in testa con desc, in coda con asc. Una pagina che ordina orapartenza.desc.nullslast passa { campo: 'orapartenza', direzione: 'desc', nulls: 'last' }.
between e array di condizioni richiedono node-excel-export ≥ 1.1.14: fino alla 1.1.13 il servizio scarta opzioni su /export/execute, quindi il file esce senza ordine. nulls richiede la 1.1.15: la 1.1.14 lo scarta senza errore e i NULL restano dove li mette PostgreSQL. La libreria manda tutti i criteri dalla 0.6.1 (prima solo il primo) e nulls dalla 0.7.0.Modelli
Se il servizio rifiuta il salvataggio di un modello (es. 403 per un modello condiviso salvato da chi non è amministratore), la finestra di salvataggio resta aperta con quello che l'utente ha scritto e mostra il messaggio del servizio. Gli errori di caricamento ed eliminazione dei modelli compaiono nel dialog, sotto la scelta del modello. «Elimina» chiede conferma prima di eliminare. Dalla 0.6.0.
nascondiCondivisione è solo interfaccia: chi può condividere un modello lo decide il servizio.
Messaggi d'errore (dalla 0.8.0) — scritti per l'utente: un'apertura per l'operazione e un dettaglio.
| Caso | Messaggio |
|---|---|
| Il servizio dà un messaggio leggibile (es. 403 sulla condivisione) | «Impossibile salvare il modello. Solo un amministratore può…» |
| 400 senza messaggio (validazione) | «Impossibile salvare il modello. Controlla nome e descrizione.» |
| 429 | «Troppe richieste, riprova tra un minuto.» (il testo del rate limit è in inglese e non si mostra) |
| Servizio non raggiungibile | «Impossibile caricare i modelli. Servizio non raggiungibile.» |
| 401 / 403 / 404 / 5xx senza messaggio | «Sessione scaduta, accedi di nuovo.» / «Operazione non consentita.» / «Modello non trovato.» / «Errore del servizio, riprova più tardi.» |
Le aperture sono «Impossibile caricare i modelli.», «Impossibile salvare il modello.» (anche per la modifica) e «Impossibile eliminare il modello.». Il testo tecnico (Errore API: 400: Bad Request) resta nei log. Fino alla 0.7.0 il dialog mostrava Salvataggio template fallito per <nome>: Errore API: 400: Bad Request.
Conferme (dalla 0.8.0) — un salvataggio o un'eliminazione riusciti si confermano sotto la scelta del modello («Modello «Consegne» salvato.», «Modello «Consegne» eliminato.»), e il modello appena salvato resta scelto nella tendina. Gli esiti si mostrano uno alla volta: un'azione nuova (campi, formato, scelta o applicazione di un modello, export) toglie quello della precedente, compreso «Esportazione completata!».
Etichette — il modello salvato registra le etichette dei campi che l'utente vede, non i nomi tecnici (dalla 0.8.0).
Esempio
<script setup lang="ts">
import { ref } from 'vue'
import { ExportDialog } from '@pzeta/vue-importexport'
const showExport = ref(false)
const baseUrl = import.meta.env.VITE_IMPORTEXPORT_API_URL
</script>
<template>
<button @click="showExport = true">Esporta anagrafica</button>
<ExportDialog
v-model:visible="showExport"
:base-url="baseUrl"
risorsa="anagrafica"
etichetta-risorsa="Anagrafiche"
@export-completed="() => console.log('Export completato')"
/>
</template>
ExportFieldSelector
PickList di @pzeta/vue-components per scegliere e ordinare i campi da esportare. Le due liste:
- Disponibili —
CampoMetadato[]non ancora selezionati, filtrabile viaInputText - Selezionati — campi che andranno nell'export, riordinabili (l'ordine determina l'ordine delle colonne nel file)
Il filtro testuale matcha contro nome, etichetta e gruppo (case-insensitive). Le righe della lista mostrano l'etichetta del campo e, se presente, il gruppo allineato a destra in font ridotto.
Props
| Prop | Tipo | Descrizione |
|---|---|---|
campiDisponibili | CampoMetadato[] | Tutti i campi esportabili dalla risorsa |
campiSelezionati | string[] | Lista nomi campo selezionati (ordinata) |
Emits
| Evento | Payload | Descrizione |
|---|---|---|
toggle | campo: string | Sposta un campo da una lista all'altra |
selectAll | — | Sposta tutto in "Selezionati" |
deselectAll | — | Sposta tutto in "Disponibili" |
move | from: number, to: number | Riordina i campi selezionati |
Esempio
<ExportFieldSelector
:campi-disponibili="campiDisponibili"
:campi-selezionati="campiSelezionati"
@toggle="toggleField"
@select-all="selectAllFields"
@deselect-all="deselectAllFields"
@move="moveField"
/>
FormatOptions
Form per le opzioni di parsing CSV. Mostrato solo nello step di upload quando il file selezionato è .csv. Contiene 4 controlli in grid 2×2:
| Campo | Controllo | Opzioni |
|---|---|---|
| Separatore | Select | ,, ;, \t, | |
| Delimitatore testo | InputText | testo libero (di solito ") |
| Encoding | Select | UTF-8, ISO-8859-1, Windows-1252 |
| Riga iniziale | InputText (numerico) | numero 1-based |
Props
| Prop | Tipo | Descrizione |
|---|---|---|
opzioni | CsvOpzioni | Opzioni correnti |
Emits
| Evento | Payload | Descrizione |
|---|---|---|
update:opzioni | CsvOpzioni | Nuove opzioni complete (la libreria ricostruisce l'oggetto sostituendo solo la chiave modificata) |
Esempio
<FormatOptions
:opzioni="opzioniCsv"
@update:opzioni="opzioniCsv = $event"
/>
Note
- Il campo
haIntestazioneè presente nell'interfacciaCsvOpzionima non è esposto daFormatOptions(defaulttrue). Se serve esporlo, è necessario un wrapper custom. - Il valore
Tabviene gestito come stringa'\t'(tab character).