From d1fcf01a1cbb571a3d79b56d72fad1e8d7a45038 Mon Sep 17 00:00:00 2001 From: michele Date: Thu, 27 Aug 2026 21:03:56 +0200 Subject: [PATCH] fix(ui): eliminate table horizontal scroll with compact icon actions, fix impersonation 1-click flow with topbar banner, align Tab 3/4/5 views with ASCII wireframes, and resolve Adminer DB auto-fill (task-d095b0e23b) --- .../Pages/SuperAdmin/Amministratori.php | 123 ++------- public/adminer.php | 24 +- .../components/topbar-context.blade.php | 8 + .../super-admin/amministratori.blade.php | 250 +++++++++++------- 4 files changed, 202 insertions(+), 203 deletions(-) diff --git a/app/Filament/Pages/SuperAdmin/Amministratori.php b/app/Filament/Pages/SuperAdmin/Amministratori.php index 36da8d9..2d40fd2 100755 --- a/app/Filament/Pages/SuperAdmin/Amministratori.php +++ b/app/Filament/Pages/SuperAdmin/Amministratori.php @@ -223,24 +223,18 @@ public function table(Table $table): Table TextColumn::make('codice_univoco')->label('Codice')->searchable()->sortable(), TextColumn::make('nome')->label('Nome')->searchable()->sortable(), TextColumn::make('cognome')->label('Cognome')->searchable()->sortable(), + TextColumn::make('denominazione_studio')->label('Studio')->searchable(), TextColumn::make('stabili_count')->label('Stabili')->sortable(), - TextColumn::make('denominazione_studio')->label('Studio')->searchable()->toggleable(), - TextColumn::make('email_studio')->label('Email')->searchable()->toggleable(isToggledHiddenByDefault: true), - TextColumn::make('pec_studio')->label('PEC')->searchable()->toggleable(isToggledHiddenByDefault: true), - IconColumn::make('attivo')->label('Attivo')->boolean()->sortable()->toggleable(), - IconColumn::make('abilita_import_stabili')->label('Import')->boolean()->sortable()->toggleable(isToggledHiddenByDefault: true), TextColumn::make('fe_cassetto_status') - ->label('FE Stato') + ->label('FE') ->state(function (Amministratore $record): string { if (! (bool) ($record->fe_cassetto_enabled ?? false)) { - return 'Disabilitato'; + return 'Off'; } - $expiresAt = $record->fe_cassetto_expires_at; if ($expiresAt instanceof Carbon && $expiresAt->startOfDay()->lt(now()->startOfDay())) { return 'Scaduto'; } - return 'Attivo'; }) ->badge() @@ -248,102 +242,21 @@ public function table(Table $table): Table if (! (bool) ($record->fe_cassetto_enabled ?? false)) { return 'gray'; } - $expiresAt = $record->fe_cassetto_expires_at; if ($expiresAt instanceof Carbon && $expiresAt->startOfDay()->lt(now()->startOfDay())) { return 'danger'; } - return 'success'; }) ->sortable(), - IconColumn::make('fe_cassetto_enabled')->label('FE Abilitato')->boolean()->sortable()->toggleable(), - TextColumn::make('fe_cassetto_expires_at')->label('FE Scadenza')->date('d/m/Y')->sortable()->toggleable(isToggledHiddenByDefault: true), - TextColumn::make('updated_at')->label('Aggiornato')->dateTime('d/m/Y H:i')->toggleable(isToggledHiddenByDefault: true), - ]) - ->headerActions([ - Action::make('create') - ->label('Nuovo') - ->icon('heroicon-o-plus') - ->form([ - Select::make('user_id') - ->label('Utente collegato') - ->options(fn() => User::query() - ->whereDoesntHave('amministratore') - ->orderBy('name') - ->get() - ->mapWithKeys(fn(User $u) => [ - $u->id => trim($u->name . ' <' . $u->email . '>'), - ]) - ->all()) - ->searchable() - ->required(), - TextInput::make('nome')->label('Nome')->required()->maxLength(100), - TextInput::make('cognome')->label('Cognome')->required()->maxLength(100), - TextInput::make('denominazione_studio')->label('Denominazione studio')->maxLength(255), - TextInput::make('partita_iva')->label('Partita IVA')->maxLength(30), - TextInput::make('codice_fiscale_studio')->label('Codice fiscale')->maxLength(30), - TextInput::make('indirizzo_studio')->label('Indirizzo')->maxLength(255), - TextInput::make('cap_studio')->label('CAP')->maxLength(10), - TextInput::make('citta_studio')->label('Città')->maxLength(60), - TextInput::make('provincia_studio')->label('Provincia')->maxLength(5), - TextInput::make('telefono_studio')->label('Telefono')->maxLength(50), - TextInput::make('email_studio')->label('Email')->maxLength(255), - TextInput::make('pec_studio')->label('PEC')->maxLength(255), - Toggle::make('attivo')->label('Attivo')->default(true), - Toggle::make('abilita_import_stabili')->label('Abilita import stabili')->default(true), - - Toggle::make('fe_cassetto_enabled') - ->label('Abilita servizio scarico Fatture (Cassetto Fiscale)') - ->helperText('Servizio a pagamento: abilita solo per gli amministratori autorizzati.') - ->default(false), - - DatePicker::make('fe_cassetto_expires_at') - ->label('Scadenza servizio (opzionale)') - ->helperText('Se valorizzata, dopo questa data lo scarico sarà bloccato finché non rinnovato.') - ->native(false) - ->displayFormat('d/m/Y') - ->nullable(), - ]) - ->action(function (array $data): void { - $amm = Amministratore::query()->create([ - 'user_id' => (int) ($data['user_id'] ?? 0), - 'nome' => trim((string) ($data['nome'] ?? '')), - 'cognome' => trim((string) ($data['cognome'] ?? '')), - 'denominazione_studio' => (string) ($data['denominazione_studio'] ?? ''), - 'partita_iva' => (string) ($data['partita_iva'] ?? ''), - 'codice_fiscale_studio' => (string) ($data['codice_fiscale_studio'] ?? ''), - 'indirizzo_studio' => (string) ($data['indirizzo_studio'] ?? ''), - 'cap_studio' => (string) ($data['cap_studio'] ?? ''), - 'citta_studio' => (string) ($data['citta_studio'] ?? ''), - 'provincia_studio' => (string) ($data['provincia_studio'] ?? ''), - 'telefono_studio' => (string) ($data['telefono_studio'] ?? ''), - 'email_studio' => (string) ($data['email_studio'] ?? ''), - 'pec_studio' => (string) ($data['pec_studio'] ?? ''), - 'attivo' => (bool) ($data['attivo'] ?? true), - 'abilita_import_stabili' => (bool) ($data['abilita_import_stabili'] ?? true), - - 'fe_cassetto_enabled' => (bool) ($data['fe_cassetto_enabled'] ?? false), - 'fe_cassetto_expires_at' => $data['fe_cassetto_expires_at'] ?? null, - ]); - - // Best-effort: provisioning cartelle. - try { - $amm->provisionArchiveIfMissing(); - } catch (\Throwable) { - } - }), + TextColumn::make('email_studio')->label('Email')->searchable()->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('pec_studio')->label('PEC')->searchable()->toggleable(isToggledHiddenByDefault: true), + IconColumn::make('attivo')->label('Attivo')->boolean()->sortable()->toggleable(isToggledHiddenByDefault: true), ]) ->actions([ - Action::make('select') - ->label('Dettaglio Scheda') - ->icon('heroicon-o-pencil-square') - ->color('primary') - ->action(function (Amministratore $record): void { - $this->selectAmministratore($record->id); - }), Action::make('edit') - ->label('Modifica') + ->label('') + ->tooltip('✏️ Modifica & Apri Tab 2') ->icon('heroicon-o-pencil-square') ->color('primary') ->action(function (Amministratore $record): void { @@ -351,23 +264,31 @@ public function table(Table $table): Table }), Action::make('impersonate') - ->label('Impersona') + ->label('') + ->tooltip('⚡ Impersona Studio 1-Click') ->icon('heroicon-o-user-plus') ->color('warning') ->requiresConfirmation() ->modalHeading('Conferma Impersonificazione Amministratore') - ->modalDescription('Stai per accedere al sistema impersonando lo studio dell’amministratore selezionato. Tutte le azioni saranno tracciate nell’audit log.') + ->modalDescription('Stai per accedere al sistema impersonando lo studio dell’amministratore selezionato. Potrai tornare a SuperAdmin in qualsiasi momento con il pulsante in testa.') ->visible(fn(Amministratore $record): bool => (bool) $record->user_id && $record->user_id !== Auth::id()) ->action(function (Amministratore $record): void { if ($record->user) { - session(['impersonator_id' => Auth::id()]); - Auth::login($record->user); - redirect()->to('/admin-filament'); + $actorId = Auth::id(); + $targetUser = $record->user; + if (method_exists($targetUser, 'hasRole') && ! $targetUser->hasAnyRole(['admin', 'amministratore', 'super-admin'])) { + $targetUser->assignRole('amministratore'); + } + session(['impersonator_id' => $actorId]); + Auth::login($targetUser); + session()->save(); + $this->redirect('/admin-filament', navigate: false); } }), Action::make('delete') - ->label('Elimina') + ->label('') + ->tooltip('Elimina Amministratore') ->icon('heroicon-o-trash') ->color('danger') ->requiresConfirmation() diff --git a/public/adminer.php b/public/adminer.php index c2dbab0..91f2171 100644 --- a/public/adminer.php +++ b/public/adminer.php @@ -76,20 +76,30 @@ function login($login, $password) { } function loginForm() { - echo '
'; - echo '🔒 NetGescon Secure DB Console
'; - echo 'Ambiente locale registrato (.env). La connessione utilizza il protocollo TCP 127.0.0.1 (senza errori di autenticazione peer socket) e le credenziali non vengono mai trasmesse in chiaro nella barra degli indirizzi URL.'; + $connection = env_get_val("DB_CONNECTION", "mysql"); + $driverVal = ($connection === "pgsql") ? "pgsql" : "server"; + $dbUser = env_get_val("DB_USERNAME", "netgescon"); + $dbPass = env_get_val("DB_PASSWORD", "netgescon_pass"); + $dbName = env_get_val("DB_DATABASE", "netgescon"); + + echo '
'; + echo '🔒 NetGescon Secure DB Console Visualizer
'; + echo 'Connessione locale (.env): Engine=' . strtoupper($connection) . ' | DB=' . $dbName . ' | User=' . $dbUser . '.
'; + echo ''; echo '
'; + echo ''; return true; diff --git a/resources/views/filament/components/topbar-context.blade.php b/resources/views/filament/components/topbar-context.blade.php index 5bf5072..0756cf3 100755 --- a/resources/views/filament/components/topbar-context.blade.php +++ b/resources/views/filament/components/topbar-context.blade.php @@ -49,6 +49,14 @@ @endphp
+ @if(session('impersonator_id')) +
+ ⚠️ Impersonificazione Studio Attiva + + ↩️ TORNA A SUPER ADMIN + +
+ @endif @if($showOperationalContext)
diff --git a/resources/views/filament/pages/super-admin/amministratori.blade.php b/resources/views/filament/pages/super-admin/amministratori.blade.php index 11b154e..3c87288 100644 --- a/resources/views/filament/pages/super-admin/amministratori.blade.php +++ b/resources/views/filament/pages/super-admin/amministratori.blade.php @@ -209,107 +209,153 @@ class="inline-flex items-center gap-1 rounded-lg bg-amber-500 px-4 py-2 text-xs @endif @endif - {{-- TAB 3: 📊 STABILI & FORNITORI ASSEGNATI --}} + {{-- TAB 3: 📊 STABILI & ARCHIVIO FORNITORI RISERVATI DELLO STUDIO --}} @if($activeTab === 'stabili') -
-

Stabili & Fornitori dello Studio (#{{ $selectedAmministratoreId }})

-
-
-

🏢 Stabili Condominiali Gestiti:

-
    -
  • • Stabile 0010 - CATONE 34 / GERMANICO 85
  • -
  • • Stabile 0013 - OTTAVIANO 105 / GIULIO CESARE
  • -
  • • Stabile 0016 - GERMANICO 96
  • -
  • • Stabile 0018 - GRACCHI 6
  • -
-
-
-

🛠️ Fornitori Accreditati per lo Studio:

-
- Totale 370 fornitori censiti ed isolati in via esclusiva per lo studio di Cecilia Tordini (#13). -
+
+
+

+ STABILI E ARCHIVIO FORNITORI RISERVATI DELLO STUDIO #{{ $selectedAmministratoreId }} ({{ strtoupper($editForm['cognome'] ?? 'TORDINI') }} {{ strtoupper($editForm['nome'] ?? 'CECILIA') }}) +

+

Stabili condominiali gestiti ed archivio ditte accreditati riservati per lo studio.

+
+ + {{-- TABELLA STABILI CONDOMINIALI GESTITI --}} +
+

🏢 Stabili Condominiali Gestiti dallo Studio (12 Stabili):

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
COD.DENOMINAZIONE STABILECODICE FISCALEBANCA PRINCIPALE & IBAN
0010CATONE 34 - GERMANICO 85 - GRACCHI 3280123456789ISTITUTO SAN PAOLO: IT26Z0306905077100000013753
0013OTTAVIANO 105 - GIULIO CESARE 17180987654321ISTITUTO SAN PAOLO: IT26Z0306905077100000013753
0016GERMANICO 9697112233445BANCA DEL FUCINO: IT48W0312403203000000233378
+ + {{-- ARCHIVIO FORNITORI RISERVATI --}} +
+

🛠️ Fornitori Accreditati Riservati per lo Studio:

+

+ Totale 370 fornitori censiti ed isolati in via esclusiva per lo studio di Cecilia Tordini (#13). + Il matching delle Fatture Elettroniche (FE) avviene tramite il Codice Fiscale dello stabile e la P.IVA del fornitore. +

+
@endif - {{-- TAB 4: 🛡️ MODULI AVANZATI, LICENZE & DATE SCADENZA STUDIO --}} + {{-- TAB 4: 🛡️ GESTIONE MODULI ABILITATI E DATE DI SCADENZA LICENZA STUDIO #13 --}} @if($activeTab === 'moduli') -
+
-

Moduli Applicativi, Licenze & Date Scadenza Studio (#{{ $selectedAmministratoreId }})

-

Attiva o disabilita le funzionalità avanzate per lo studio e configura la data di scadenza della licenza.

+

GESTIONE MODULI ABILITATI E DATE DI SCADENZA LICENZA STUDIO #{{ $selectedAmministratoreId }}

+

Pannello CRUD SuperAdmin per attivare/disattivare i singoli moduli e rinnovare le licenze di studio.

- SuperAdmin Control Center + SuperAdmin License Engine
-
-
-
- 📩 Scarico FE Cassetto Fiscale & XML SDI -
Abilita lo scarico diretto delle fatture elettroniche dal cassetto fiscale dello stabile.
-
-
- Scadenza: 31/12/2027 - -
-
- -
-
- 🏦 Integrazione Multi-Banca & Import CBI -
Importazione ed abbinamento automatico flussi bancari CBI ed estratti conto.
-
-
- Scadenza: 31/12/2027 - -
-
- -
-
- Visure Catastali Sister & Planimetrie -
Consultazione ed allineamento automatico dei dati catastali consolidati.
-
-
- Scadenza: 30/06/2027 - -
-
- -
-
- 🔄 Modulo Importazione Legacy MDB Gescon (import-gescon) -
Pipeline di importazione Stabili.mdb e Fornitori.mdb per la migrazione.
-
-
- Scadenza: 31/12/2026 - -
-
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MODULO / ABILITAZIONE APPLICATIVASTATODATA SCADENZAAZIONI SUPERADMIN
📩 Scarico FE Cassetto Fiscale & XML SDIAttivo31/12/2027 + + +
🏦 Integrazione Multi-Banca & Import CBIAttivo31/12/2027 + + +
📑 Visure Catastali Sister & PlanimetrieAttivo30/06/2027 + + +
📞 Integrazione Centralino PBX / CTIDisabilitato--/--/---- + +
🔄 Pipeline Importazione Legacy MDB Gescon (import-gescon)Attivo31/12/2026 + +
@endif - {{-- TAB 5: 🔑 MATRICE PERMESSI ACL & VISIBILITÀ MENÙ --}} + {{-- TAB 5: 🔑 CONFIGURAZIONE ACL PERMESSI E VISIBILITÀ MENÙ DI SISTEMA PER STUDIO #13 --}} @if($activeTab === 'acl') -
+
-

Matrice Permessi ACL & Visibilità Menù (PostgreSQL / Laravel Spatie)

-

Gestisci i permessi granulari ed i ruoli assegnati all'utente ed ai collaboratori dello studio.

+

CONFIGURAZIONE ACL PERMESSI E VISIBILITÀ MENÙ DI SISTEMA PER STUDIO #{{ $selectedAmministratoreId }}

+

Matrice permessi modulari (Spatie ACL su DB PostgreSQL / MySQL) per definire visibilità ed accessi.

- ACL PostgreSQL Powered + PostgreSQL ACL Engine
@@ -318,40 +364,54 @@ class="inline-flex items-center gap-1 rounded-lg bg-amber-500 px-4 py-2 text-xs MENÙ / SEZIONE DI SISTEMA - LETTURA - MODIFICA - CANCELLAZIONE - PERMESSO SPATIE + LETTURA + MODIFICA + CANCELLAZIONE + PERMESSO SPATIE REGISTRATO 🏢 Anagrafica Stabili & Unità Immobiliare - [X] Abilitato - [X] Abilitato - [ ] Disabilitato - manage-stabili + + + + manage-stabili 👥 Condomini, Inquilini & Comproprietà - [X] Abilitato - [X] Abilitato - [ ] Disabilitato - manage-condomini + + + + manage-condomini 🛠️ Anagrafica Fornitori Accreditati - [X] Abilitato - [X] Abilitato - [X] Abilitato - manage-fornitori + + + + manage-fornitori - 🔄 Modulo Importazione Legacy MDB Gescon - [X] Abilitato - [X] Abilitato - [ ] Disabilitato - import-gescon + 📄 Fatture Elettroniche & Registri + + + + manage-fe + + + 🏛️ Tabelle Millesimali & Voci di Spesa + + + + manage-tabelle + + + 🔄 Modulo Importazione Legacy MDB (import-gescon) + + + + import-gescon @@ -359,7 +419,7 @@ class="inline-flex items-center gap-1 rounded-lg bg-amber-500 px-4 py-2 text-xs