fix: refine archive label printing and public qr
This commit is contained in:
parent
8bc7783ce3
commit
49a49cdb08
|
|
@ -40,7 +40,8 @@ ## Struttura documentazione
|
||||||
## Stato operativo recente
|
## Stato operativo recente
|
||||||
|
|
||||||
- Strumenti > Documenti apre ora una dashboard `Protocollo comunicazioni` con ricerca, filtri e anteprima PDF.
|
- Strumenti > Documenti apre ora una dashboard `Protocollo comunicazioni` con ricerca, filtri e anteprima PDF.
|
||||||
- Le etichette archivio fisico generano il QR in locale e supportano i formati DYMO `11354` e `99014`.
|
- Le etichette archivio fisico generano il QR in locale, supportano i formati DYMO `11354` e `99014` e usano un URL pubblico configurabile tramite `APP_PUBLIC_URL`.
|
||||||
|
- La vista `Archivio digitale` usa ora una tabella a tutta larghezza con riepilogo rapido della cartella corrente.
|
||||||
- La topbar contestuale Filament usa layout a capo, senza scrollbar orizzontale.
|
- La topbar contestuale Filament usa layout a capo, senza scrollbar orizzontale.
|
||||||
|
|
||||||
## Contribuire
|
## Contribuire
|
||||||
|
|
|
||||||
|
|
@ -434,6 +434,30 @@ public function getDigitalArchiveCurrentFolderProperty(): ?DocumentoArchivioCart
|
||||||
return DocumentoArchivioCartella::query()->find($this->currentFolderId);
|
return DocumentoArchivioCartella::query()->find($this->currentFolderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDigitalArchiveCurrentFolderDocumentCountProperty(): int
|
||||||
|
{
|
||||||
|
$stabileId = (int) ($this->resolveActiveStabile()?->id ?? 0);
|
||||||
|
if ($stabileId <= 0 || ! $this->currentFolderId) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) Documento::query()
|
||||||
|
->where('stabile_id', $stabileId)
|
||||||
|
->where('tipo_documento', 'fattura')
|
||||||
|
->where('cartella_archivio_id', $this->currentFolderId)
|
||||||
|
->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDigitalArchiveCurrentFolderHintProperty(): string
|
||||||
|
{
|
||||||
|
$folder = $this->digitalArchiveCurrentFolder;
|
||||||
|
if (! $folder instanceof DocumentoArchivioCartella) {
|
||||||
|
return 'Seleziona la cartella annuale per vedere l’elenco dei PDF già ordinati per protocollo e data.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim((string) ($folder->percorso_logico ?: $folder->nome));
|
||||||
|
}
|
||||||
|
|
||||||
public function getDigitalArchiveFoldersProperty(): array
|
public function getDigitalArchiveFoldersProperty(): array
|
||||||
{
|
{
|
||||||
$stabile = $this->resolveActiveStabile();
|
$stabile = $this->resolveActiveStabile();
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,17 @@ public function etichettaArchivioFisico(Request $request, DocumentoArchivioFisic
|
||||||
|
|
||||||
$format = $request->query('format', '11354');
|
$format = $request->query('format', '11354');
|
||||||
$format = in_array($format, ['11354', '99014'], true) ? $format : '11354';
|
$format = in_array($format, ['11354', '99014'], true) ? $format : '11354';
|
||||||
$defaults = $this->getDymoDefaultsForUser($format);
|
$labelPrinterMode = $request->boolean('autoprint')
|
||||||
|
|| $request->has('dymo_fix')
|
||||||
|
|| $request->has('dymo_rot')
|
||||||
|
|| $request->has('dymo_dx')
|
||||||
|
|| $request->has('dymo_dy');
|
||||||
|
$defaults = $labelPrinterMode ? $this->getDymoDefaultsForUser($format) : [
|
||||||
|
'fix' => false,
|
||||||
|
'rot' => 0,
|
||||||
|
'dx' => 0.0,
|
||||||
|
'dy' => 0.0,
|
||||||
|
];
|
||||||
|
|
||||||
$dymoFix = $request->query('dymo_fix');
|
$dymoFix = $request->query('dymo_fix');
|
||||||
if ($dymoFix === null) {
|
if ($dymoFix === null) {
|
||||||
|
|
@ -181,20 +191,34 @@ public function etichettaArchivioFisico(Request $request, DocumentoArchivioFisic
|
||||||
$dymoDx = $request->has('dymo_dx') ? (float) $request->query('dymo_dx') : (float) ($defaults['dx'] ?? 0);
|
$dymoDx = $request->has('dymo_dx') ? (float) $request->query('dymo_dx') : (float) ($defaults['dx'] ?? 0);
|
||||||
$dymoDy = $request->has('dymo_dy') ? (float) $request->query('dymo_dy') : (float) ($defaults['dy'] ?? 0);
|
$dymoDy = $request->has('dymo_dy') ? (float) $request->query('dymo_dy') : (float) ($defaults['dy'] ?? 0);
|
||||||
|
|
||||||
|
if ($format === '11354' && $dymoFix) {
|
||||||
|
if (! in_array($dymoRot, [-90, 90], true)) {
|
||||||
|
$dymoRot = -90;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (! in_array($dymoRot, [-180, -90, 0, 90, 180], true)) {
|
||||||
|
$dymoRot = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$dymoDx = max(-15.0, min(15.0, $dymoDx));
|
||||||
|
$dymoDy = max(-15.0, min(15.0, $dymoDy));
|
||||||
|
|
||||||
return view('filament.print.etichetta-archivio-fisico', [
|
return view('filament.print.etichetta-archivio-fisico', [
|
||||||
'item' => $item->load(['parent', 'children', 'stabile', 'documento']),
|
'item' => $item->load(['parent', 'children', 'stabile', 'documento']),
|
||||||
'format' => $format,
|
'format' => $format,
|
||||||
|
'labelPrinterMode' => $labelPrinterMode,
|
||||||
'dymoFix' => $dymoFix,
|
'dymoFix' => $dymoFix,
|
||||||
'dymoRot' => $dymoRot,
|
'dymoRot' => $dymoRot,
|
||||||
'dymoDx' => $dymoDx,
|
'dymoDx' => $dymoDx,
|
||||||
'dymoDy' => $dymoDy,
|
'dymoDy' => $dymoDy,
|
||||||
'publicUrl' => $item->qr_code_data,
|
'publicUrl' => $item->buildPublicQrUrl(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function showPublicArchivioFisicoItem(Request $request, DocumentoArchivioFisicoItem $item)
|
public function showPublicArchivioFisicoItem(Request $request, DocumentoArchivioFisicoItem $item)
|
||||||
{
|
{
|
||||||
if (! $request->hasValidSignature()) {
|
if (! $request->hasValidSignature(false)) {
|
||||||
abort(403);
|
abort(403);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
|
@ -107,7 +106,7 @@ public function getPercorsoFisicoAttribute(): string
|
||||||
|
|
||||||
public function getQrCodeImageAttribute(): string
|
public function getQrCodeImageAttribute(): string
|
||||||
{
|
{
|
||||||
$data = trim((string) $this->qr_code_data);
|
$data = $this->buildPublicQrUrl();
|
||||||
|
|
||||||
if ($data !== '' && class_exists(\chillerlan\QRCode\QROptions::class) && class_exists(\chillerlan\QRCode\QRCode::class)) {
|
if ($data !== '' && class_exists(\chillerlan\QRCode\QROptions::class) && class_exists(\chillerlan\QRCode\QRCode::class)) {
|
||||||
$options = new \chillerlan\QRCode\QROptions([
|
$options = new \chillerlan\QRCode\QROptions([
|
||||||
|
|
@ -156,15 +155,26 @@ public static function generateCodice(int $stabileId): string
|
||||||
|
|
||||||
public function refreshQrCodeData(): void
|
public function refreshQrCodeData(): void
|
||||||
{
|
{
|
||||||
$url = URL::temporarySignedRoute(
|
$this->forceFill([
|
||||||
|
'qr_code_data' => $this->buildPublicQrUrl(),
|
||||||
|
])->saveQuietly();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildPublicQrUrl(): string
|
||||||
|
{
|
||||||
|
$relativeSignedPath = URL::temporarySignedRoute(
|
||||||
'public.archivio-fisico.show',
|
'public.archivio-fisico.show',
|
||||||
now()->addYears(5),
|
now()->addYears(5),
|
||||||
['item' => $this->id]
|
['item' => $this->id],
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->forceFill([
|
$baseUrl = rtrim((string) config('app.public_url', config('app.url')), '/');
|
||||||
'qr_code_data' => $url,
|
if ($baseUrl === '') {
|
||||||
])->saveQuietly();
|
return $relativeSignedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $baseUrl . '/' . ltrim($relativeSignedPath, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function booted(): void
|
protected static function booted(): void
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@
|
||||||
|
|
||||||
'url' => env('APP_URL', 'http://localhost'),
|
'url' => env('APP_URL', 'http://localhost'),
|
||||||
|
|
||||||
|
'public_url' => env('APP_PUBLIC_URL', env('APP_URL', 'http://localhost')),
|
||||||
|
|
||||||
'asset_url' => env('ASSET_URL'),
|
'asset_url' => env('ASSET_URL'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,12 @@ ## Archivio fisico ed etichette
|
||||||
- stampa etichette nei formati `DYMO 11354` e `DYMO 99014`;
|
- stampa etichette nei formati `DYMO 11354` e `DYMO 99014`;
|
||||||
- pagina pubblica firmata per dettaglio contenitore o documento tramite QR.
|
- pagina pubblica firmata per dettaglio contenitore o documento tramite QR.
|
||||||
|
|
||||||
|
Taratura operativa corrente:
|
||||||
|
|
||||||
|
- `11354`: layout orizzontale principale con correzione verticale leggera verso l'alto;
|
||||||
|
- `11354 verticale`: variante dedicata ai driver che ruotano l'etichetta, ora con rotazione corretta lato stampa;
|
||||||
|
- `99014`: QR spostato in basso a destra per liberare spazio scrivibile nella parte alta.
|
||||||
|
|
||||||
Per i documenti digitali resta disponibile anche l'assegnazione dei metadati fisici principali:
|
Per i documenti digitali resta disponibile anche l'assegnazione dei metadati fisici principali:
|
||||||
|
|
||||||
- supporto fisico;
|
- supporto fisico;
|
||||||
|
|
@ -75,6 +81,26 @@ ## QR locale sulle etichette
|
||||||
|
|
||||||
Questo elimina la dipendenza da URL esterni per il QR e rende piu stabile il preview di stampa.
|
Questo elimina la dipendenza da URL esterni per il QR e rende piu stabile il preview di stampa.
|
||||||
|
|
||||||
|
## QR pubblico e dominio esterno
|
||||||
|
|
||||||
|
Il QR dell'archivio fisico non deve piu dipendere dall'IP interno del server.
|
||||||
|
|
||||||
|
Implementazione attuale:
|
||||||
|
|
||||||
|
- la firma della route pubblica viene generata in forma relativa;
|
||||||
|
- il link finale viene costruito usando `APP_PUBLIC_URL`, con fallback su `APP_URL`;
|
||||||
|
- la validazione avviene lato controller con firma relativa, cosi il QR resta valido anche dietro dominio pubblico o reverse proxy.
|
||||||
|
|
||||||
|
Configurazione richiesta in ambiente:
|
||||||
|
|
||||||
|
1. impostare `APP_PUBLIC_URL` con il dominio realmente raggiungibile dall'esterno;
|
||||||
|
2. lasciare `APP_URL` per il contesto applicativo interno se serve;
|
||||||
|
3. rigenerare o aggiornare i QR gia salvati solo se si vuole riallineare anche il dato persistito nel database.
|
||||||
|
|
||||||
|
Esempio:
|
||||||
|
|
||||||
|
- `APP_PUBLIC_URL=https://netgescon.example.it`
|
||||||
|
|
||||||
## Stampa PDF e watermark archivio
|
## Stampa PDF e watermark archivio
|
||||||
|
|
||||||
Per i documenti PDF sono ora previste due aperture distinte dalla tab archivio:
|
Per i documenti PDF sono ora previste due aperture distinte dalla tab archivio:
|
||||||
|
|
@ -208,6 +234,24 @@ ## Scanner Epson da pagina web
|
||||||
2. upload/ingestione rapida in NetGescon;
|
2. upload/ingestione rapida in NetGescon;
|
||||||
3. OCR e archiviazione automatica.
|
3. OCR e archiviazione automatica.
|
||||||
|
|
||||||
|
Per il modello Epson WF-C5710 la direzione pratica da testare non e il browser puro, ma una di queste due:
|
||||||
|
|
||||||
|
- scansione verso cartella di rete osservata da NetGescon;
|
||||||
|
- piccolo bridge locale o di rete che espone una chiamata HTTP interna e usa il canale scanner disponibile sul dispositivo.
|
||||||
|
|
||||||
|
Questo evita il vincolo dei browser su TWAIN/WIA e mantiene il flusso pilotabile dalla pagina archivio.
|
||||||
|
|
||||||
|
## Archivio digitale
|
||||||
|
|
||||||
|
La vista `Strumenti > Documenti > Archivio digitale` e stata alleggerita per lavorare meglio dentro la cartella corrente.
|
||||||
|
|
||||||
|
Stato attuale:
|
||||||
|
|
||||||
|
- breadcrumb e cartelle restano in alto;
|
||||||
|
- la tabella documenti ora usa tutta la larghezza utile;
|
||||||
|
- le informazioni laterali sono state compattate in tre card sintetiche sopra la tabella;
|
||||||
|
- la pagina mostra nome cartella attiva, numero documenti del livello e stato operativo digitale/fisico.
|
||||||
|
|
||||||
## Dymo LAN 11354
|
## Dymo LAN 11354
|
||||||
|
|
||||||
Domani si puo provare una stampa etichetta su rete con formato `11354` usando:
|
Domani si puo provare una stampa etichetta su rete con formato `11354` usando:
|
||||||
|
|
|
||||||
|
|
@ -283,25 +283,27 @@ class="rounded-2xl border border-slate-200 bg-white p-4 text-left shadow-sm tran
|
||||||
@endforelse
|
@endforelse
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid gap-3 xl:grid-cols-[minmax(0,1fr)_320px]">
|
<div class="grid gap-3 lg:grid-cols-3">
|
||||||
|
<div class="rounded-xl border bg-white p-4">
|
||||||
|
<div class="text-xs uppercase tracking-wide text-slate-500">Cartella attiva</div>
|
||||||
|
<div class="mt-2 text-sm font-semibold text-slate-900">{{ $this->digitalArchiveCurrentFolder?->nome ?? 'Nessuna cartella selezionata' }}</div>
|
||||||
|
<div class="mt-1 text-xs text-slate-500">{{ $this->digitalArchiveCurrentFolderHint }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="rounded-xl border bg-white p-4">
|
||||||
|
<div class="text-xs uppercase tracking-wide text-slate-500">Documenti nel livello</div>
|
||||||
|
<div class="mt-2 text-2xl font-semibold text-slate-900">{{ $this->digitalArchiveCurrentFolderDocumentCount }}</div>
|
||||||
|
<div class="mt-1 text-xs text-slate-500">Solo fatture PDF collegate alla cartella corrente.</div>
|
||||||
|
</div>
|
||||||
|
<div class="rounded-xl border bg-white p-4">
|
||||||
|
<div class="text-xs uppercase tracking-wide text-slate-500">Operatività</div>
|
||||||
|
<div class="mt-2 text-sm font-semibold text-slate-900">Archivio digitale e fisico allineati</div>
|
||||||
|
<div class="mt-1 text-xs text-slate-500">Da qui puoi aprire, stampare, watermarkare e assegnare subito la collocazione cartacea.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{{ $this->table }}
|
{{ $this->table }}
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-3">
|
|
||||||
<div class="rounded-xl border bg-white p-4">
|
|
||||||
<div class="text-sm font-semibold text-slate-900">Flusso digitale e fisico</div>
|
|
||||||
<div class="mt-2 text-sm text-slate-600">Usa l'icona archivio per assegnare contenitore, busta, fascicolo ed etichetta del documento cartaceo. La posizione verra poi richiamata anche nel watermark PDF.</div>
|
|
||||||
</div>
|
|
||||||
<div class="rounded-xl border bg-white p-4">
|
|
||||||
<div class="text-sm font-semibold text-slate-900">Stampa</div>
|
|
||||||
<div class="mt-2 text-sm text-slate-600">Icona stampante: PDF senza timbro. Icona duplicato: PDF con watermark archivio digitale e fisico, se la codifica e presente.</div>
|
|
||||||
</div>
|
|
||||||
<div class="rounded-xl border bg-white p-4">
|
|
||||||
<div class="text-sm font-semibold text-slate-900">Scanner</div>
|
|
||||||
<div class="mt-2 text-sm text-slate-600">La struttura attuale e pronta per il prossimo aggancio scanner: acquisizione PDF, naming ordinato, assegnazione immediata a cartella digitale e posizione fisica.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</x-filament::section>
|
</x-filament::section>
|
||||||
@elseif($this->hubTab === 'template-drive')
|
@elseif($this->hubTab === 'template-drive')
|
||||||
|
|
@ -509,8 +511,9 @@ class="rounded-2xl border border-slate-200 bg-white p-4 text-left shadow-sm tran
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="flex shrink-0 flex-wrap items-center gap-2">
|
<div class="flex shrink-0 flex-wrap items-center gap-2">
|
||||||
<a href="{{ route('filament.archivio-fisico.etichetta', ['item' => $row['id']]) }}?format=11354&autoprint=1" target="_blank" class="inline-flex items-center rounded-lg border border-slate-300 bg-white px-3 py-2 text-xs font-medium text-slate-700 shadow-sm hover:bg-slate-50">11354</a>
|
<a href="{{ route('filament.archivio-fisico.etichetta', ['item' => $row['id']]) }}?format=11354&autoprint=1&dymo_fix=0&dymo_rot=0&dymo_dx=0&dymo_dy=-1" target="_blank" class="inline-flex items-center rounded-lg border border-slate-300 bg-white px-3 py-2 text-xs font-medium text-slate-700 shadow-sm hover:bg-slate-50">11354</a>
|
||||||
<a href="{{ route('filament.archivio-fisico.etichetta', ['item' => $row['id']]) }}?format=99014&autoprint=1" target="_blank" class="inline-flex items-center rounded-lg border border-slate-300 bg-white px-3 py-2 text-xs font-medium text-slate-700 shadow-sm hover:bg-slate-50">99014</a>
|
<a href="{{ route('filament.archivio-fisico.etichetta', ['item' => $row['id']]) }}?format=11354&autoprint=1&dymo_fix=1&dymo_rot=90&dymo_dx=0&dymo_dy=0" target="_blank" class="inline-flex items-center rounded-lg border border-slate-300 bg-white px-3 py-2 text-xs font-medium text-slate-700 shadow-sm hover:bg-slate-50">11354 verticale</a>
|
||||||
|
<a href="{{ route('filament.archivio-fisico.etichetta', ['item' => $row['id']]) }}?format=99014&autoprint=1&dymo_fix=0&dymo_rot=0&dymo_dx=3.5&dymo_dy=3.5" target="_blank" class="inline-flex items-center rounded-lg border border-slate-300 bg-white px-3 py-2 text-xs font-medium text-slate-700 shadow-sm hover:bg-slate-50">99014</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -10,17 +10,60 @@
|
||||||
@php($dymoDx = isset($dymoDx) ? (float) $dymoDx : 0.0)
|
@php($dymoDx = isset($dymoDx) ? (float) $dymoDx : 0.0)
|
||||||
@php($dymoDy = isset($dymoDy) ? (float) $dymoDy : 0.0)
|
@php($dymoDy = isset($dymoDy) ? (float) $dymoDy : 0.0)
|
||||||
@php($autoPrint = request()->has('autoprint') && filter_var(request()->query('autoprint'), FILTER_VALIDATE_BOOL))
|
@php($autoPrint = request()->has('autoprint') && filter_var(request()->query('autoprint'), FILTER_VALIDATE_BOOL))
|
||||||
|
@php($labelPrinterMode = isset($labelPrinterMode) ? (bool) $labelPrinterMode : false)
|
||||||
|
@php($pageWidth = $fmt === '99014' ? '54mm' : '57mm')
|
||||||
|
@php($pageHeight = $fmt === '99014' ? '101mm' : '32mm')
|
||||||
<style>
|
<style>
|
||||||
@page { margin: 0; size: {{ $fmt === '99014' ? '54mm 101mm' : '57mm 32mm' }}; }
|
@page {
|
||||||
|
margin: {{ $labelPrinterMode ? '0' : '10mm' }};
|
||||||
|
size: {{ $labelPrinterMode ? ($fmt === '99014' ? '54mm 101mm' : '57mm 32mm') : 'A4 portrait' }};
|
||||||
|
}
|
||||||
html, body {
|
html, body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: {{ $fmt === '99014' ? '54mm' : '57mm' }};
|
width: 100%;
|
||||||
height: {{ $fmt === '99014' ? '101mm' : '32mm' }};
|
min-height: 100%;
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
|
background: {{ $labelPrinterMode ? 'white' : '#eef1f5' }};
|
||||||
|
}
|
||||||
|
.sheet {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: {{ $labelPrinterMode ? $pageWidth : '210mm' }};
|
||||||
|
min-height: {{ $labelPrinterMode ? $pageHeight : '297mm' }};
|
||||||
|
padding: {{ $labelPrinterMode ? '0' : '12mm' }};
|
||||||
|
display: flex;
|
||||||
|
align-items: {{ $labelPrinterMode ? 'stretch' : 'flex-start' }};
|
||||||
|
justify-content: {{ $labelPrinterMode ? 'stretch' : 'flex-start' }};
|
||||||
|
margin: 0 auto;
|
||||||
|
background: white;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
break-inside: avoid;
|
||||||
|
break-after: avoid-page;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
page-break-after: avoid;
|
||||||
|
}
|
||||||
|
.label {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: {{ $pageWidth }};
|
||||||
|
height: {{ $pageHeight }};
|
||||||
|
padding: 0;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.calib {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
}
|
||||||
|
.label-content {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: {{ $fmt === '99014' ? '3.5mm' : '2mm' }};
|
||||||
}
|
}
|
||||||
.label { box-sizing: border-box; width: 100%; height: 100%; padding: {{ $fmt === '99014' ? '3.5mm' : '2mm' }}; }
|
|
||||||
.panel {
|
.panel {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
@ -32,7 +75,16 @@
|
||||||
padding: {{ $fmt === '99014' ? '2.4mm' : '1.5mm' }};
|
padding: {{ $fmt === '99014' ? '2.4mm' : '1.5mm' }};
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
.panel.panel-99014 {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
padding: 2.8mm;
|
||||||
|
}
|
||||||
.content { min-width: 0; }
|
.content { min-width: 0; }
|
||||||
|
.panel.panel-99014 .content {
|
||||||
|
padding-right: 0;
|
||||||
|
padding-bottom: 21mm;
|
||||||
|
}
|
||||||
.code { font-weight: 800; font-size: {{ $fmt === '99014' ? '14px' : '10px' }}; letter-spacing: 0.4px; }
|
.code { font-weight: 800; font-size: {{ $fmt === '99014' ? '14px' : '10px' }}; letter-spacing: 0.4px; }
|
||||||
.title { font-weight: 700; font-size: {{ $fmt === '99014' ? '13px' : '9px' }}; line-height: 1.15; margin-top: 1mm; }
|
.title { font-weight: 700; font-size: {{ $fmt === '99014' ? '13px' : '9px' }}; line-height: 1.15; margin-top: 1mm; }
|
||||||
.meta { font-size: {{ $fmt === '99014' ? '10px' : '7px' }}; line-height: 1.2; color: #222; margin-top: 1.1mm; }
|
.meta { font-size: {{ $fmt === '99014' ? '10px' : '7px' }}; line-height: 1.2; color: #222; margin-top: 1.1mm; }
|
||||||
|
|
@ -46,6 +98,14 @@
|
||||||
padding: 0.4mm;
|
padding: 0.4mm;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
.panel.panel-99014 .qr {
|
||||||
|
position: absolute;
|
||||||
|
right: 2.8mm;
|
||||||
|
bottom: 2.8mm;
|
||||||
|
width: 18mm;
|
||||||
|
height: 18mm;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
.qr svg,
|
.qr svg,
|
||||||
.qr img {
|
.qr img {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
@ -58,13 +118,61 @@
|
||||||
aspect-ratio: 1 / 1;
|
aspect-ratio: 1 / 1;
|
||||||
}
|
}
|
||||||
.path { font-size: {{ $fmt === '99014' ? '9px' : '6.6px' }}; line-height: 1.2; color: #444; margin-top: 1mm; word-break: break-word; }
|
.path { font-size: {{ $fmt === '99014' ? '9px' : '6.6px' }}; line-height: 1.2; color: #444; margin-top: 1mm; word-break: break-word; }
|
||||||
|
@media screen {
|
||||||
|
body {
|
||||||
|
padding: 12mm 0;
|
||||||
|
}
|
||||||
|
.sheet {
|
||||||
|
box-shadow: 0 10px 28px rgba(15, 23, 42, 0.18);
|
||||||
|
}
|
||||||
|
}
|
||||||
@media print {
|
@media print {
|
||||||
html, body { width: 100%; height: 100%; }
|
html, body {
|
||||||
.label { transform: translate({{ $dymoDx }}mm, {{ $dymoDy }}mm) rotate({{ $dymoRot }}deg); transform-origin: top left; }
|
width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
.sheet {
|
||||||
|
box-shadow: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: {{ $labelPrinterMode ? '0' : '12mm' }};
|
||||||
|
min-height: auto;
|
||||||
|
}
|
||||||
|
@if($labelPrinterMode)
|
||||||
|
html, body {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.sheet {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.calib {
|
||||||
|
transform: translate({{ $dymoDx }}mm, {{ $dymoDy }}mm) rotate({{ $dymoRot }}deg);
|
||||||
|
}
|
||||||
@if($fmt === '11354' && $dymoFix)
|
@if($fmt === '11354' && $dymoFix)
|
||||||
@page { size: 32mm 57mm; }
|
@page { size: 32mm 57mm; }
|
||||||
html, body { width: 32mm; height: 57mm; }
|
html, body {
|
||||||
.label { width: 57mm; height: 32mm; transform: translate({{ $dymoDx }}mm, calc(57mm + {{ $dymoDy }}mm)) rotate(-90deg); transform-origin: top left; }
|
width: 32mm;
|
||||||
|
height: 57mm;
|
||||||
|
}
|
||||||
|
.sheet {
|
||||||
|
width: 32mm;
|
||||||
|
height: 57mm;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.calib {
|
||||||
|
width: 57mm;
|
||||||
|
height: 32mm;
|
||||||
|
@if($dymoRot === 90)
|
||||||
|
transform: translate({{ $dymoDx }}mm, {{ $dymoDy }}mm) translateX(32mm) rotate(90deg);
|
||||||
|
@else
|
||||||
|
transform: translate({{ $dymoDx }}mm, {{ $dymoDy }}mm) translateY(57mm) rotate(-90deg);
|
||||||
|
@endif
|
||||||
|
}
|
||||||
|
@endif
|
||||||
|
@else
|
||||||
|
.calib { transform: none !important; }
|
||||||
@endif
|
@endif
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -76,16 +184,25 @@
|
||||||
@endif
|
@endif
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div class="sheet">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<div class="panel">
|
<div class="calib">
|
||||||
|
<div class="label-content">
|
||||||
|
<div @class(['panel', 'panel-99014' => $fmt === '99014'])>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="code">{{ $item->codice_univoco }}</div>
|
<div class="code">{{ $item->codice_univoco }}</div>
|
||||||
<div class="title">{{ $item->titolo }}</div>
|
<div class="title">{{ $item->titolo }}</div>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
|
@if($item->stabile)
|
||||||
|
<div><strong>Stabile:</strong> {{ $item->stabile->denominazione }}</div>
|
||||||
|
@endif
|
||||||
<div><strong>Tipo:</strong> {{ $item->tipo_label }}</div>
|
<div><strong>Tipo:</strong> {{ $item->tipo_label }}</div>
|
||||||
@if($item->voce_numero || $item->voce_titolo)
|
@if($item->voce_numero || $item->voce_titolo)
|
||||||
<div><strong>Voce:</strong> {{ $item->voce_numero ? 'Voce ' . $item->voce_numero : '' }} {{ $item->voce_titolo }}</div>
|
<div><strong>Voce:</strong> {{ $item->voce_numero ? 'Voce ' . $item->voce_numero : '' }} {{ $item->voce_titolo }}</div>
|
||||||
@endif
|
@endif
|
||||||
|
@if($item->data_archiviazione)
|
||||||
|
<div><strong>Data:</strong> {{ $item->data_archiviazione->format('d-m-Y') }}</div>
|
||||||
|
@endif
|
||||||
@if($item->parent)
|
@if($item->parent)
|
||||||
<div><strong>Dentro:</strong> {{ $item->parent->codice_univoco }}</div>
|
<div><strong>Dentro:</strong> {{ $item->parent->codice_univoco }}</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
@ -100,5 +217,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -727,7 +727,7 @@
|
||||||
// --- AUTHENTICATION ROUTES ---
|
// --- AUTHENTICATION ROUTES ---
|
||||||
require __DIR__ . '/auth.php';
|
require __DIR__ . '/auth.php';
|
||||||
|
|
||||||
Route::middleware('signed')->get('/archivio-fisico/{item}', [\App\Http\Controllers\Filament\DocumentiPrintController::class, 'showPublicArchivioFisicoItem'])
|
Route::get('/archivio-fisico/{item}', [\App\Http\Controllers\Filament\DocumentiPrintController::class, 'showPublicArchivioFisicoItem'])
|
||||||
->name('public.archivio-fisico.show');
|
->name('public.archivio-fisico.show');
|
||||||
|
|
||||||
Route::middleware(['auth'])->group(function () {
|
Route::middleware(['auth'])->group(function () {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user