Vue Attachment

Libreria Vue 3 per la gestione allegati con upload, download, preview ed eliminazione. Architettura Adapter Strategy + componenti Presentational/Connected.

Cos'è @pzeta/vue-attachment

@pzeta/vue-attachment è una libreria di componenti Vue 3 per la gestione completa di file allegati associati a entità di business: upload, lista (grid/list), preview popover e download/eliminazione. Backend di riferimento: API REST + storage MinIO/S3.

Questa documentazione si riferisce alla v2.x, che introduce l'architettura Adapter Strategy (data source pluggable) e la separazione Presentational/Connected dei componenti. Vedi la sezione Migration v1 → v2 se arrivi dalla v1.

Funzionalità principali

  • Componenti Presentational + Connected: usa quelli puri (props in, eventi out) o le varianti che fanno il fetch da sole via useAttachments
  • Adapter Strategy: backend pluggable. createAxiosAdapter di default; implementa AttachmentAdapter per GraphQL, fetch o mock
  • Composables: useAttachments (CRUD), useFileIcon (MIME → icona PrimeIcons), useFileSize (formattazione bytes IEC)
  • Plugin Vue: VueAttachmentPlugin registra globalmente i componenti e fornisce l'adapter via provide/inject
  • Mapper opzionale: backend con schema diverso da Attachment (camelCase)? Passa mapper.toAttachment al createAxiosAdapter senza toccare la logica di trasporto
  • Admin endpoint: findOrphaned() / cleanOrphaned() per pulizia file orfani
  • i18n: dizionari it/en/de/es/fr lazy via @pzeta/vue-i18n

Architettura

@pzeta/vue-attachment
├── components/      # AttachmentsManager(+Connected) · AttachmentPopover(+Connected)
│                    # AttachmentDialog · AttachmentsList/Grid/Toolbar · AttachmentCard/Row
├── composables/     # useAttachments · useFileIcon · useFileSize
├── services/        # AxiosAttachmentAdapter · createAxiosAdapter
├── types/           # Attachment (dominio) · AttachmentAdapter (Strategy) · AttachmentQuery · ...
├── plugins/         # VueAttachmentPlugin · ATTACHMENT_ADAPTER_KEY
└── i18n/            # locales

Modello di dominio

interface Attachment {
  id: string
  fileName: string
  fileType: string   // MIME type
  size: number       // bytes
  uploadDate: string // ISO 8601
  thumbnailUrl?: string
}

Il modello è indipendente dal trasporto e dallo schema DB. Backend con campi diversi (es. idallegato/nomefile) si integrano tramite mapper.toAttachment.

Sotto-pagine

Quick start

// main.ts
import { createApp } from 'vue'
import axios from 'axios'
import {
  VueAttachmentPlugin,
  createAxiosAdapter
} from '@pzeta/vue-attachment'
import '@pzeta/vue-attachment/style.css'

const http = axios.create({ baseURL: '/api/storage' })

createApp(App)
  .use(VueAttachmentPlugin, {
    adapter: createAxiosAdapter(http, { storagePath: 'attachments/tickets' })
  })
  .mount('#app')
<!-- in qualsiasi pagina: il container fetcha autonomamente -->
<template>
  <AttachmentsManagerConnected
    reference-table="tickets"
    reference-column="idticket"
    :reference-value="42"
    :max-size="10485760"
    :allowed-types="['image/png', 'image/jpeg', 'application/pdf']"
  />
</template>

Quando usare cosa

ScenarioComponente / API
Pagina dettaglio entità con allegatiAttachmentsManagerConnected
Indicatore compatto allegati nell'header (Ticket, Anagrafica, ...)AttachmentPopoverConnected
Modal di gestione allegatiAttachmentDialog (wrappa AttachmentsManagerConnected)
Lista già in memoria (cache, SSR, Storybook, demo)AttachmentsManager / AttachmentPopover (presentational)
CRUD custom in uno script setupcomposable useAttachments
Backend non-axios (GraphQL, fetch, tRPC, mock)implementa AttachmentAdapter
Backend axios con schema legacy snake_casecreateAxiosAdapter(http, { mapper })

Migration v1 → v2

Cambiamentov1v2
ConfigurazioneConfigService (singleton legato a import.meta.env)app.use(VueAttachmentPlugin, { adapter })
HTTP clientnew AttachmentService(http)createAxiosAdapter(http)
DB mappingAttachmentDB + mapDbToAttachment in libreriaBackend deve restituire Attachment (camelCase). Per backend legacy: opzione mapper
Componenti smartAttachmentsManager faceva fetch internamente con configServiceAttachmentsManager è presentational; per fetch automatico → AttachmentsManagerConnected
AttachmentPopoverRiceveva referenceTable/Column/Value e fetchavaPresentational: riceve attachments via prop. Per fetch → AttachmentPopoverConnected
Tipo Attachmentesportato da services/AttachmentServiceesportato da types

Simboli rimossi

ConfigService, configService, AttachmentService (classe), mapDbToAttachment, mapAttachmentToDb, AttachmentDB. Chi li importava direttamente deve riscrivere usando createAxiosAdapter / AxiosAttachmentAdapter / mapper opzionale.