2026-05-26 08:14:29 +02:00
@ extends ( 'layouts.adminlte' )
@ section ( 'title' , 'Impostazioni' )
@ section ( 'page_title' , 'Impostazioni' )
@ section ( 'breadcrumbs' )
< li class = " breadcrumb-item " >< a href = " { { route('dashboard') }} " > Dashboard </ a ></ li >
< li class = " breadcrumb-item active " > Impostazioni </ li >
@ endsection
@ section ( 'content' )
< div class = " row " >
< div class = " col-md-3 " >
< div class = " card card-secondary " >
< div class = " card-header " >
< h3 class = " card-title " > Sezioni </ h3 >
</ div >
< div class = " list-group list-group-flush " >
< a href = " #applicazione " class = " list-group-item list-group-item-action " data - toggle = " tab " >
< i class = " nav-icon fas fa-cog mr-2 " ></ i > Applicazione
</ a >
2026-05-28 09:34:28 +02:00
< a href = " #repository " class = " list-group-item list-group-item-action " data - toggle = " tab " >
< i class = " nav-icon fas fa-cloud mr-2 " ></ i > Repository Remoti
</ a >
< a href = " #documenti " class = " list-group-item list-group-item-action " data - toggle = " tab " >
< i class = " nav-icon fas fa-file mr-2 " ></ i > Repository Documenti
</ a >
2026-05-26 08:14:29 +02:00
< a href = " #logo " class = " list-group-item list-group-item-action " data - toggle = " tab " >
< i class = " nav-icon fas fa-image mr-2 " ></ i > Logo
</ a >
2026-05-26 14:10:04 +02:00
< a href = " #email " class = " list-group-item list-group-item-action " data - toggle = " tab " >
< i class = " nav-icon fas fa-envelope mr-2 " ></ i > Email
</ a >
< a href = " #calendario " class = " list-group-item list-group-item-action " data - toggle = " tab " >
< i class = " nav-icon fas fa-calendar-alt mr-2 " ></ i > Calendario
</ a >
2026-05-26 08:14:29 +02:00
< a href = " #tipologie " class = " list-group-item list-group-item-action " data - toggle = " tab " >
< i class = " nav-icon fas fa-file mr-2 " ></ i > Tipologie Documenti
</ a >
2026-05-26 12:28:39 +02:00
< a href = " #tipologie-eventi " class = " list-group-item list-group-item-action " data - toggle = " tab " >
< i class = " nav-icon fas fa-calendar mr-2 " ></ i > Tipologie Eventi
</ a >
2026-05-26 14:10:04 +02:00
< a href = " #ruoli " class = " list-group-item list-group-item-action " data - toggle = " tab " >
< i class = " nav-icon fas fa-users-cog mr-2 " ></ i > Tipi di Ruolo
</ a >
2026-05-26 08:14:29 +02:00
</ div >
</ div >
</ div >
< div class = " col-md-9 " >
< div class = " tab-content " >
2026-05-26 14:10:04 +02:00
{{ -- === APPLICAZIONE === -- }}
2026-05-26 08:14:29 +02:00
< div class = " tab-pane " id = " applicazione " >
< div class = " card card-primary " >
< div class = " card-header " >
< h3 class = " card-title " > Configurazione Applicazione </ h3 >
</ div >
< div class = " card-body " >
< p class = " text-muted " > Configura il nome e il testo visualizzato dall 'applicazione.</p>
@if(session(' success '))
<div class="alert alert-success">{{ session(' success ') }}</div>
@endif
<form method="POST" action="{{ route(' impostazioni . app - settings . save ') }}">
@csrf
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="nome_applicazione">Nome Applicazione</label>
2026-05-26 14:10:04 +02:00
<input type="text" name="nome_applicazione" id="nome_applicazione" class="form-control"
2026-05-26 08:14:29 +02:00
value="{{ old(' nome_applicazione ', $appSettings->nome_applicazione ?? ' ') }}"
placeholder="es. Glastree">
<small class="text-muted">Nome mostrato nel titolo, sidebar e login</small>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="nome_organizzazione">Nome Organizzazione</label>
2026-05-26 14:10:04 +02:00
<input type="text" name="nome_organizzazione" id="nome_organizzazione" class="form-control"
2026-05-26 08:14:29 +02:00
value="{{ old(' nome_organizzazione ', $appSettings->nome_organizzazione ?? ' ') }}"
placeholder="es. Parrocchia Santa Maria">
<small class="text-muted">Nome organizzazione mostrato sotto il logo nel login</small>
</div>
</div>
</div>
<div class="form-group">
<label for="footer_text">Testo Footer</label>
2026-05-26 14:10:04 +02:00
<input type="text" name="footer_text" id="footer_text" class="form-control"
2026-05-26 08:14:29 +02:00
value="{{ old(' footer_text ', $appSettings->footer_text ?? ' ') }}"
placeholder="es. © 2026 Parrocchia Santa Maria">
<small class="text-muted">Lascia vuoto per usare il formato predefinito: © {anno} {nome_applicazione}</small>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="app_version">Versione Applicazione</label>
2026-05-26 14:10:04 +02:00
<input type="text" name="app_version" id="app_version" class="form-control"
2026-05-26 08:14:29 +02:00
value="{{ old(' app_version ', $appSettings->app_version ?? ' ') }}"
placeholder="es. 1.0.0">
<small class="text-muted">Versione mostrata nel footer</small>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label> </label>
<div class="custom-control custom-switch mt-2">
<input type="checkbox" class="custom-control-input" id="show_version" name="show_version" value="1"
{{ ($appSettings->show_version ?? false) ? ' checked ' : ' ' }}>
<label class="custom-control-label" for="show_version">Mostra versione nel footer</label>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="dashboard_welcome">Messaggio di Benvenuto (Dashboard)</label>
<textarea name="dashboard_welcome" id="dashboard_welcome" class="form-control" rows="3"
placeholder="Lascia vuoto per usare il messaggio predefinito">{{ old(' dashboard_welcome ', $appSettings->dashboard_welcome ?? ' ') }}</textarea>
<small class="text-muted">Messaggio mostrato nella dashboard. Lascia vuoto per usare il testo predefinito.</small>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save mr-1"></i> Salva Impostazioni
</button>
</form>
</div>
</div>
</div>
2026-05-28 09:34:28 +02:00
{{-- === REPOSITORY REMOTI (Opzione B) === --}}
<div class="tab-pane" id="repository">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-cloud mr-2"></i> Repository Remoti</h3>
<div class="card-tools">
<button type="button" class="btn btn-sm btn-success" data-toggle="modal" data-target="#repoModal" onclick="resetRepoForm()">
<i class="fas fa-plus mr-1"></i> Nuovo Repository
</button>
</div>
</div>
<div class="card-body">
<p class="text-muted">Configura repository remoti (WebDAV, Google Drive) per archiviare documenti. Ogni repository appare come root separata nell' albero delle cartelle in Gestione Documenti .</ p >
@ if ( session ( 'success' ))
< div class = " alert alert-success " > {{ session ( 'success' ) }} </ div >
@ endif
@ if ( session ( 'error' ))
< div class = " alert alert-danger " > {{ session ( 'error' ) }} </ div >
@ endif
@ if ( $repositories -> count () > 0 )
< div class = " table-responsive " >
< table class = " table table-bordered table-hover table-sm " id = " repoTable " >
< thead >
< tr >
< th style = " width:40px; " > #</th>
< th > Nome </ th >
< th > Tipo </ th >
< th > Stato </ th >
< th style = " width:180px; " > Azioni </ th >
</ tr >
</ thead >
< tbody id = " repoSortable " >
@ foreach ( $repositories as $repo )
< tr data - id = " { { $repo->id }} " >
< td class = " text-center handle " style = " cursor:grab; " >< i class = " fas fa-grip-vertical text-muted " ></ i ></ td >
< td >< strong > {{ $repo -> nome }} </ strong ></ td >
< td >
< span class = " badge badge- { { $repo->tipo === 'google_drive' ? 'danger' : 'secondary' }} " >
< i class = " fas { { $repo->tipo === 'google_drive' ? 'fa-google-drive' : 'fa-server' }} mr-1 " ></ i >
{{ \App\Models\StorageRepository :: etichettaTipo ( $repo -> tipo ) }}
</ span >
</ td >
< td >
@ if ( $repo -> is_active )
< span class = " badge badge-success " > Attivo </ span >
@ else
< span class = " badge badge-secondary " > Disattivo </ span >
@ endif
</ td >
< td >
< button type = " button " class = " btn btn-xs btn-info " onclick = " editRepo( { { $repo->id }}) " title = " Modifica " >
< i class = " fas fa-edit " ></ i >
</ button >
< button type = " button " class = " btn btn-xs btn-success test-repo-btn " onclick = " testRepo( { { $repo->id }}, this) " title = " Test connessione " >
< i class = " fas fa-plug " ></ i >
</ button >
< button type = " button " class = " btn btn-xs btn-danger " onclick = " deleteRepo( { { $repo->id }}, ' { { addslashes( $repo->nome ) }}') " title = " Elimina " >
< i class = " fas fa-trash " ></ i >
</ button >
</ td >
</ tr >
@ endforeach
</ tbody >
</ table >
</ div >
@ else
< div class = " text-center text-muted py-4 " >
< i class = " fas fa-cloud fa-3x mb-3 " ></ i >
< p class = " mb-0 " > Nessun repository remoto configurato .</ p >
< p class = " mb-0 " > Clicca " Nuovo Repository " per aggiungere un server WebDAV o Google Drive .</ p >
</ div >
@ endif
</ div >
</ div >
@ if ( $repositories -> count () > 0 )
< div class = " card card-secondary " >
< div class = " card-header " >
< h3 class = " card-title " >< i class = " fas fa-info-circle mr-2 " ></ i > Come funziona </ h3 >
</ div >
< div class = " card-body " >
< ul class = " mb-0 " >
< li > Ogni repository configurato apparirà come < strong > root separata </ strong > nella sidebar < strong > Gestione Documenti </ strong > , sotto " Repository Remoti " .</ li >
< li > Puoi navigare i file e le cartelle di ogni repository remoto direttamente dall 'interfaccia documenti.</li>
<li><strong>WebDAV</strong>: supporta server che parlano il protocollo WebDAV (es. NextCloud, ownCloud, Synology).</li>
<li><strong>Google Drive</strong>: richiede OAuth 2.0 con client ID, client secret e refresh token configurati nella <a href="https://console.cloud.google.com/" target="_blank">Google Cloud Console</a>.</li>
<li>Usa il pulsante <i class="fas fa-plug text-success"></i> <strong>Test</strong> per verificare la connettività dopo la configurazione.</li>
</ul>
</div>
</div>
@endif
</div>
{{-- === REPOSITORY DOCUMENTI === --}}
<div class="tab-pane" id="documenti">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">Repository Documenti</h3>
</div>
<div class="card-body">
<p class="text-muted">Configura il repository filesystem dove vengono salvati i documenti caricati.</p>
@php
$currentDisk = $appSettings->documenti_storage_disk ?? ' local ';
$currentPath = $appSettings->documenti_storage_path ?? ' documenti ';
$absPath = storage_path(' app / ' . ($currentDisk === ' local ' ? ' private / ' : ' ') . $currentPath);
@endphp
<form method="POST" action="{{ route(' impostazioni . app - settings . save ') }}">
@csrf
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="documenti_storage_disk">Disco di archiviazione</label>
<select name="documenti_storage_disk" id="documenti_storage_disk" class="form-control">
<option value="local" {{ $currentDisk === ' local ' ? ' selected ' : ' ' }}>Locale (storage/app/private)</option>
<option value="public" {{ $currentDisk === ' public ' ? ' selected ' : ' ' }}>Pubblico (storage/app/public)</option>
</select>
<small class="text-muted">Il disco predefinito per salvare i documenti</small>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="documenti_storage_path">Percorso relativo</label>
<input type="text" name="documenti_storage_path" id="documenti_storage_path" class="form-control"
value="{{ $currentPath }}" placeholder="es. documenti">
<small class="text-muted">Sottocartella all' interno del disco </ small >
</ div >
</ div >
</ div >
< div class = " alert alert-info " >
< i class = " fas fa-info-circle mr-2 " ></ i >
< strong > Percorso assoluto calcolato :</ strong >
< code > {{ $absPath }} </ code >
< br >
< small class = " text-muted " > I nuovi documenti verranno salvati in questa directory .</ small >
</ div >
@ if ( session ( 'path_changed' ))
@ php
$migrateCount = session ( 'migration_count' , 0 );
$oldD = session ( 'old_storage_disk' , 'local' );
$oldP = session ( 'old_storage_path' , 'documenti' );
$newD = session ( 'new_storage_disk' , 'local' );
$newP = session ( 'new_storage_path' , 'documenti' );
@ endphp
< div class = " alert alert-warning " >
< i class = " fas fa-exclamation-triangle mr-2 " ></ i >
< strong > Percorso modificato !</ strong >
< p class = " mb-2 " > La nuova directory < code > {{ $newD }} :// {{ $newP }} </ code > è stata creata .
@ if ( $migrateCount > 0 )
Ci sono < strong > {{ $migrateCount }} </ strong > file nella vecchia posizione < code > {{ $oldD }} :// {{ $oldP }} </ code >.</ p >
< form method = " POST " action = " { { route('impostazioni.migrate-percorso') }} " class = " d-inline " onsubmit = " return confirm('Spostare { { $migrateCount }} file? Questa operazione potrebbe richiedere alcuni secondi.'); " >
@ csrf
< input type = " hidden " name = " old_storage_disk " value = " { { $oldD }} " >
< input type = " hidden " name = " old_storage_path " value = " { { $oldP }} " >
< input type = " hidden " name = " new_storage_disk " value = " { { $newD }} " >
< input type = " hidden " name = " new_storage_path " value = " { { $newP }} " >
< button type = " submit " class = " btn btn-warning " >
< i class = " fas fa-exchange-alt mr-1 " ></ i > Sposta {{ $migrateCount }} file nel nuovo percorso
</ button >
< a href = " /impostazioni#documenti " class = " btn btn-secondary ml-2 " >
< i class = " fas fa-times mr-1 " ></ i > Ignora
</ a >
</ form >
@ else
< p class = " mb-0 " > Nessun file da spostare .</ p >
@ endif
</ div >
@ endif
< button type = " submit " class = " btn btn-primary " >
< i class = " fas fa-save mr-1 " ></ i > Salva Impostazioni
</ button >
</ form >
</ div >
</ div >
</ div >
2026-05-26 14:10:04 +02:00
{{ -- === LOGO === -- }}
2026-05-26 08:14:29 +02:00
< div class = " tab-pane " id = " logo " >
< div class = " card card-primary " >
< div class = " card-header " >
< h3 class = " card-title " > Logo </ h3 >
</ div >
< div class = " card-body " >
< p class = " text-muted " > Carica il logo dell 'applicazione. Verrà visualizzato nella pagina di login e nella sidebar.</p>
@if(session(' success '))
<div class="alert alert-success">{{ session(' success ') }}</div>
@endif
<form method="POST" action="{{ route(' impostazioni . logo . upload ') }}" enctype="multipart/form-data">
@csrf
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Logo Grande (pagina login)</label>
<div class="text-center p-3 border rounded bg-light mb-2" style="min-height: 120px;">
@if($appSettings && $appSettings->getLogoPath())
<img src="{{ $appSettings->getLogoPath() }}" alt="Logo" style="max-height: 100px; max-width: 100%;">
@else
<span class="text-muted">Nessun logo caricato</span>
@endif
</div>
<input type="file" name="logo" class="form-control" accept="image/*">
<small class="text-muted">PNG, JPG, GIF, SVG - Max 2MB</small>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label>Logo Piccolo (sidebar)</label>
<div class="text-center p-3 border rounded bg-light mb-2" style="min-height: 80px;">
@if($appSettings && $appSettings->getLogoSmallPath())
<img src="{{ $appSettings->getLogoSmallPath() }}" alt="Logo Small" style="max-height: 60px; max-width: 100%;">
@else
<span class="text-muted">Nessun logo caricato</span>
@endif
</div>
<input type="file" name="logo_small" class="form-control" accept="image/*">
<small class="text-muted">PNG, JPG, GIF, SVG - Max 512KB</small>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save mr-1"></i> Salva Logo
</button>
</form>
</div>
</div>
</div>
2026-05-26 14:10:04 +02:00
{{-- === EMAIL === --}}
<div class="tab-pane" id="email">
<div class="card card-secondary">
<div class="card-header">
<h3 class="card-title">Sezioni Email</h3>
</div>
<div class="card-body p-0">
<ul class="nav nav-pills p-2">
<li class="nav-item"><a href="#email-imap" class="nav-link active" data-toggle="tab">Server IMAP</a></li>
<li class="nav-item"><a href="#email-smtp" class="nav-link" data-toggle="tab">Server SMTP</a></li>
<li class="nav-item"><a href="#email-account" class="nav-link" data-toggle="tab">Account</a></li>
<li class="nav-item"><a href="#email-sync" class="nav-link" data-toggle="tab">Sincronizzazione</a></li>
<li class="nav-item"><a href="#email-firma" class="nav-link" data-toggle="tab">Firma</a></li>
2026-05-27 08:37:37 +02:00
<li class="nav-item"><a href="#email-mittenti" class="nav-link" data-toggle="tab">Mittenti Aggiuntivi</a></li>
2026-05-26 14:10:04 +02:00
</ul>
</div>
</div>
<form method="POST" action="{{ route(' impostazioni . email . save ') }}">
@csrf
<input type="hidden" name="id" value="{{ $emailSettings->id ?? 1 }}">
<div class="tab-content">
<div class="tab-pane active" id="email-imap">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">Configurazione Server IMAP</h3>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="imap_host">Host IMAP</label>
<input type="text" name="imap_host" id="imap_host" class="form-control"
value="{{ $emailSettings->imap_host ?? ' imap . gmail . com ' }}"
placeholder="es. imap.gmail.com">
<small class="text-muted">Gmail: imap.gmail.com | Outlook: outlook.office365.com</small>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="imap_port">Porta</label>
<input type="number" name="imap_port" id="imap_port" class="form-control"
value="{{ $emailSettings->imap_port ?? 993 }}">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="imap_encryption">Crittografia</label>
<select name="imap_encryption" id="imap_encryption" class="form-control">
<option value="ssl" {{ ($emailSettings->imap_encryption ?? ' ssl ') == ' ssl ' ? ' selected ' : ' ' }}>SSL</option>
<option value="tls" {{ ($emailSettings->imap_encryption ?? ' ') == ' tls ' ? ' selected ' : ' ' }}>TLS</option>
<option value="none" {{ ($emailSettings->imap_encryption ?? ' ') == ' none ' ? ' selected ' : ' ' }}>Nessuna</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="email-smtp">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">Configurazione Server SMTP (per invio email)</h3>
</div>
<div class="card-body">
<div class="alert alert-info">
<i class="fas fa-info-circle"></i>
<strong>Nota:</strong> Per inviare email devi configurare il server SMTP.
Per Gmail, usa <code>smtp.gmail.com</code> sulla porta <code>587</code> con TLS
e genera una <a href="https://support.google.com/accounts/answer/185833" target="_blank">App Password</a>.
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="smtp_host">Host SMTP</label>
<input type="text" name="smtp_host" id="smtp_host" class="form-control"
value="{{ $emailSettings->smtp_host ?? ' smtp . gmail . com ' }}"
placeholder="es. smtp.gmail.com">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="smtp_port">Porta</label>
<input type="number" name="smtp_port" id="smtp_port" class="form-control"
value="{{ $emailSettings->smtp_port ?? 587 }}">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="smtp_encryption">Crittografia</label>
<select name="smtp_encryption" id="smtp_encryption" class="form-control">
<option value="tls" {{ ($emailSettings->smtp_encryption ?? ' tls ') == ' tls ' ? ' selected ' : ' ' }}>TLS</option>
<option value="ssl" {{ ($emailSettings->smtp_encryption ?? ' ') == ' ssl ' ? ' selected ' : ' ' }}>SSL</option>
<option value="none" {{ ($emailSettings->smtp_encryption ?? ' ') == ' none ' ? ' selected ' : ' ' }}>Nessuna</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="smtp_username">Username SMTP</label>
<input type="text" name="smtp_username" id="smtp_username" class="form-control"
value="{{ $emailSettings->smtp_username ?? ' ' }}"
placeholder="lascia vuoto per usare l' account IMAP " >
<small class= " text - muted " >Generalmente uguale all'account email</small>
</div>
</div>
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " smtp_password " >Password SMTP / App Password</label>
<input type= " password " name= " smtp_password " id= " smtp_password " class= " form - control "
placeholder= " {{ $emailSettings -> smtp_password ? '••••••••' : '' }} " >
<small class= " text - muted " >Lascia vuoto per usare la password IMAP</small>
</div>
</div>
</div>
</div>
</div>
</div>
<div class= " tab - pane " id= " email - account " >
<div class= " card card - primary " >
<div class= " card - header " >
<h3 class= " card - title " >Credenziali Account</h3>
</div>
<div class= " card - body " >
<div class= " row " >
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " imap_username " >Username/Email</label>
<input type= " text " name= " imap_username " id= " imap_username " class= " form - control "
value= " {{ $emailSettings -> imap_username ? ? '' }} "
placeholder= " es . tuo @ gmail . com " >
<small class= " text - muted " >Per Gmail usa l'indirizzo completo</small>
</div>
</div>
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " imap_password " >Password / App Password</label>
<input type= " password " name= " imap_password " id= " imap_password " class= " form - control " placeholder= " " >
<small class= " text - muted " >
<a href= " https :// support . google . com / accounts / answer / 185833 " target= " _blank " >Per Gmail: genera una App Password</a>
</small>
</div>
</div>
</div>
<hr>
<div class= " row " >
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " email_address " >Email Indirizzo</label>
<input type= " email " name= " email_address " id= " email_address " class= " form - control "
value= " {{ $emailSettings -> email_address ? ? '' }} " >
</div>
</div>
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " email_name " >Nome Visualizzato</label>
<input type= " text " name= " email_name " id= " email_name " class= " form - control "
value= " {{ $emailSettings -> email_name ? ? '' }} "
placeholder= " es . Nome Cognome " >
</div>
</div>
</div>
<div class= " row " >
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " reply_to " >Email Risposta (Reply-To)</label>
<input type= " email " name= " reply_to " id= " reply_to " class= " form - control "
value= " {{ $emailSettings -> reply_to ? ? '' }} " >
</div>
</div>
</div>
</div>
</div>
</div>
<div class= " tab - pane " id= " email - sync " >
<div class= " card card - primary " >
<div class= " card - header " >
<h3 class= " card - title " >Sincronizzazione</h3>
</div>
<div class= " card - body " >
<div class= " row " >
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " sync_interval_minutes " >Intervallo Sync (minuti)</label>
<select name= " sync_interval_minutes " id= " sync_interval_minutes " class= " form - control " >
<option value= " 1 " { { ( $emailSettings->sync_interval_minutes ?? 5) == 1 ? 'selected' : '' }}>1 minuto</option>
<option value= " 5 " { { ( $emailSettings->sync_interval_minutes ?? 5) == 5 ? 'selected' : '' }}>5 minuti</option>
<option value= " 15 " { { ( $emailSettings->sync_interval_minutes ?? 5) == 15 ? 'selected' : '' }}>15 minuti</option>
<option value= " 30 " { { ( $emailSettings->sync_interval_minutes ?? 5) == 30 ? 'selected' : '' }}>30 minuti</option>
<option value= " 60 " { { ( $emailSettings->sync_interval_minutes ?? 5) == 60 ? 'selected' : '' }}>1 ora</option>
</select>
</div>
</div>
<div class= " col - md - 6 " >
<div class= " form - group " >
<label>Stato Connessione</label>
<div class= " mt - 2 " >
@if( $emailSettings->last_sync_at )
<span class= " badge badge - success " >
<i class= " fas fa - check - circle " ></i> Ultimo sync: { { $emailSettings->last_sync_at ->format('d/m/Y H:i') }}
</span>
@else
<span class= " badge badge - secondary " >
<i class= " fas fa - clock " ></i> Mai sincronizzato
</span>
@endif
</div>
</div>
</div>
</div>
<div class= " form - group " >
<div class= " custom - control custom - switch " >
2026-06-08 12:09:45 +02:00
<input type= " hidden " name= " is_active " value= " 0 " >
2026-05-26 14:10:04 +02:00
<input type= " checkbox " class= " custom - control - input " id= " is_active "
name= " is_active " value= " 1 " { { ( $emailSettings->is_active ?? false) ? 'checked' : '' }}>
<label class= " custom - control - label " for= " is_active " >Account Email Attivo</label>
</div>
</div>
</div>
</div>
</div>
<div class= " tab - pane " id= " email - firma " >
<div class= " card card - primary " >
<div class= " card - header " >
<h3 class= " card - title " >Firma Email</h3>
</div>
<div class= " card - body " >
<div class= " form - group " >
2026-06-08 12:09:45 +02:00
<div class= " custom - control custom - switch " >
<input type= " hidden " name= " signature_enabled " value= " 0 " >
<input type= " checkbox " class= " custom - control - input " id= " signature_enabled "
name= " signature_enabled " value= " 1 " { { ( $emailSettings->signature_enabled ?? true) ? 'checked' : '' }}>
<label class= " custom - control - label " for= " signature_enabled " >Attiva firma automatica</label>
</div>
2026-05-26 14:10:04 +02:00
<small class= " text - muted " >Quando attivo, la firma verrà aggiunta in fondo a ogni email inviata</small>
</div>
<hr>
<div class= " form - group " >
<label for= " signature " >Testo Firma (formato HTML)</label>
<div id= " signature - editor " style= " height : 200 px ; " ></div>
<input type= " hidden " name= " signature " id= " signature_input " value= " {{ $emailSettings -> signature ? ? '' }} " >
<small class= " text - muted " >Usa il riquadro sopra per comporre la tua firma. HTML supportato.</small>
</div>
</div>
</div>
</div>
2026-05-27 08:37:37 +02:00
<div class= " tab - pane " id= " email - mittenti " >
<div class= " card card - primary " >
<div class= " card - header " >
<h3 class= " card - title " >Mittenti Aggiuntivi</h3>
<div class= " card - tools " >
<button type= " button " class= " btn btn - sm btn - success " data-toggle= " modal " data-target= " #senderModal" onclick="resetSenderForm()">
< i class = " fas fa-plus mr-1 " ></ i > Nuovo Mittente
</ button >
</ div >
</ div >
< div class = " card-body " >
@ if ( session ( 'success' ))
< div class = " alert alert-success " > {{ session ( 'success' ) }} </ div >
@ endif
@ if ( session ( 'error' ))
< div class = " alert alert-danger " > {{ session ( 'error' ) }} </ div >
@ endif
@ if ( $senderAccounts -> count () > 0 )
< div class = " table-responsive " >
< table class = " table table-bordered table-hover table-sm " >
< thead >
< tr >
< th > Email </ th >
< th > Nome </ th >
< th > SMTP </ th >
< th > Reply - To </ th >
< th > Verify </ th >
< th > Stato </ th >
< th style = " width: 160px; " > Azioni </ th >
</ tr >
</ thead >
< tbody >
@ foreach ( $senderAccounts as $sender )
< tr >
< td >< strong > {{ $sender -> email_address }} </ strong ></ td >
< td > {{ $sender -> email_name ? : '-' }} </ td >
< td >< small > {{ $sender -> smtp_host ? : '-' }} : {{ $sender -> smtp_port ? : '-' }} </ small ></ td >
< td >< small class = " text-muted " > {{ $sender -> reply_to ? : '-' }} </ small ></ td >
< td >< small class = " text-muted " > {{ $sender -> verify_email ? : '-' }} </ small ></ td >
< td >
@ if ( $sender -> is_active )
< span class = " badge badge-success " > Attivo </ span >
@ else
< span class = " badge badge-secondary " > Disattivo </ span >
@ endif
</ td >
< td >
< button type = " button " class = " btn btn-xs btn-info " onclick = " editSender( { { $sender->id }}) " title = " Modifica " >
< i class = " fas fa-edit " ></ i >
</ button >
< button type = " button " class = " btn btn-xs btn-success " onclick = " testSenderSmtp( { { $sender->id }}) " title = " Test SMTP " >
< i class = " fas fa-paper-plane " ></ i >
</ button >
< button type = " button " class = " btn btn-xs btn-danger " onclick = " deleteSender( { { $sender->id }}, ' { { addslashes( $sender->email_address ) }}') " title = " Elimina " >
< i class = " fas fa-trash " ></ i >
</ button >
</ td >
</ tr >
@ endforeach
</ tbody >
</ table >
</ div >
@ else
< div class = " text-center text-muted py-4 " >
< i class = " fas fa-user-plus fa-2x mb-2 " ></ i >
< p class = " mb-0 " > Nessun mittente aggiuntivo configurato .</ p >
< p class = " mb-0 " > Usa il pulsante " Nuovo Mittente " per aggiungere un account di invio dedicato ( es . Newsletter ) .</ p >
</ div >
@ endif
</ div >
</ div >
@ if ( $senderAccounts -> count () > 0 )
< div class = " card card-secondary " >
< div class = " card-header " >
< h3 class = " card-title " >< i class = " fas fa-info-circle mr-2 " ></ i > Come funziona </ h3 >
</ div >
< div class = " card-body " >
< ul class = " mb-0 " >
< li > I mittenti aggiuntivi sono account < strong > solo invio </ strong > ( SMTP ) senza IMAP .</ li >
< li > Puoi selezionarli nel < strong > compose email </ strong > o negli < strong > invii mailing </ strong >.</ li >
< li > Il campo < strong > Reply - To </ strong > imposta l 'indirizzo di risposta (es. <code>no-reply@parrocchia.it</code>).</li>
<li>Il campo <strong>Verify Email</strong> riceve un report di riepilogo dopo ogni invio massivo con l' esito ( ok / falliti ) .</ li >
< li > Se Reply - To non è impostato , viene usato Verify Email come fallback .</ li >
</ ul >
</ div >
</ div >
@ endif
</ div >
2026-05-26 14:10:04 +02:00
</ div >
2026-06-02 22:07:16 +02:00
< div class = " card-footer d-flex flex-wrap align-items-center gap-2 " >
2026-05-26 14:10:04 +02:00
< button type = " submit " class = " btn btn-primary " >
< i class = " fas fa-save mr-1 " ></ i > Salva Impostazioni Email
</ button >
< button type = " button " class = " btn btn-info ml-2 " onclick = " testConnection() " >
< i class = " fas fa-plug mr-1 " ></ i > Test Connessione IMAP
</ button >
< button type = " button " class = " btn btn-success ml-2 " onclick = " testSmtp() " >
< i class = " fas fa-paper-plane mr-1 " ></ i > Test Invio Email ( SMTP )
</ button >
< a href = " { { route('impostazioni.email.sync') }} " class = " btn btn-warning ml-2 " >
< i class = " fas fa-sync mr-1 " ></ i > Sincronizza Ora
</ a >
</ div >
</ form >
2026-06-08 09:47:24 +02:00
< div class = " d-flex justify-content-end mt-2 " >
< form action = " { { route('impostazioni.email.destroy') }} " method = " POST " onsubmit = " return confirm('Eliminare definitivamente la configurazione email? Tutti i dati di connessione verranno rimossi.') " >
@ csrf @ method ( 'DELETE' )
< button type = " submit " class = " btn btn-danger btn-sm " >
< i class = " fas fa-trash mr-1 " ></ i > Elimina Configurazione
</ button >
</ form >
</ div >
2026-05-26 14:10:04 +02:00
</ div >
{{ -- === CALENDARIO === -- }}
< div class = " tab-pane " id = " calendario " >
< div class = " card card-primary " >
< div class = " card-header " >
2026-06-02 22:07:16 +02:00
< h3 class = " card-title " >< i class = " fas fa-calendar-alt mr-2 " ></ i > Calendari Remoti </ h3 >
< div class = " card-tools " >
< button type = " button " class = " btn btn-sm btn-success " data - toggle = " modal " data - target = " #calendarioModal " onclick = " resetCalendarioForm() " >
< i class = " fas fa-plus mr-1 " ></ i > Nuova Connessione
</ button >
</ div >
2026-05-26 14:10:04 +02:00
</ div >
< div class = " card-body " >
2026-06-02 22:07:16 +02:00
< p class = " text-muted " > Configura la sincronizzazione con calendari esterni ( Google Calendar , CalDAV come Infomaniak / NextCloud ) .</ p >
@ if ( session ( 'success' ))
< div class = " alert alert-success " > {{ session ( 'success' ) }} </ div >
@ endif
@ if ( session ( 'error' ))
< div class = " alert alert-danger " > {{ session ( 'error' ) }} </ div >
@ endif
@ php
$calendarioConnessioni = \App\Models\CalendarioConnessione :: orderBy ( 'ordine' ) -> get ();
@ endphp
@ if ( $calendarioConnessioni -> count () > 0 )
< div class = " table-responsive " >
< table class = " table table-bordered table-hover table-sm " >
< thead >
< tr >
< th style = " width:40px; " > #</th>
< th > Nome </ th >
< th > Tipo </ th >
< th > Direzione Sync </ th >
< th > Stato </ th >
< th > Ultimo Sync </ th >
< th style = " width:200px; " > Azioni </ th >
</ tr >
</ thead >
< tbody id = " calendarioSortable " >
@ foreach ( $calendarioConnessioni as $cal )
< tr data - id = " { { $cal->id }} " >
< td class = " text-center handle " style = " cursor:grab; " >< i class = " fas fa-grip-vertical text-muted " ></ i ></ td >
< td >< strong > {{ $cal -> nome }} </ strong ></ td >
< td >
< span class = " badge badge- { { $cal->tipo === 'google_calendar' ? 'danger' : 'info' }} " >
< i class = " fas { { $cal->tipo === 'google_calendar' ? 'fa-google' : 'fa-calendar-alt' }} mr-1 " ></ i >
{{ \App\Models\CalendarioConnessione :: etichettaTipo ( $cal -> tipo ) }}
</ span >
</ td >
< td >
@ switch ( $cal -> sync_direction )
@ case ( 'import' ) < span class = " badge badge-primary " >< i class = " fas fa-download mr-1 " ></ i > Solo Import </ span > @ break
@ case ( 'export' ) < span class = " badge badge-warning " >< i class = " fas fa-upload mr-1 " ></ i > Solo Export </ span > @ break
@ default < span class = " badge badge-success " >< i class = " fas fa-exchange-alt mr-1 " ></ i > Bidirezionale </ span >
@ endswitch
</ td >
< td >
@ if ( $cal -> stato === 'connesso' )
< span class = " badge badge-success " >< i class = " fas fa-check-circle mr-1 " ></ i > Connesso </ span >
@ elseif ( $cal -> stato === 'errore' )
< span class = " badge badge-danger " title = " { { $cal->last_error_message ?? '' }} " >< i class = " fas fa-exclamation-circle mr-1 " ></ i > Errore </ span >
@ else
< span class = " badge badge-secondary " >< i class = " fas fa-circle mr-1 " ></ i > {{ ucfirst ( $cal -> stato ) }} </ span >
@ endif
</ td >
< td >
@ if ( $cal -> last_sync_at )
< small class = " text-muted " > {{ $cal -> last_sync_at -> format ( 'd/m/Y H:i' ) }} </ small >
@ else
< small class = " text-muted " > Mai </ small >
@ endif
</ td >
< td >
< button type = " button " class = " btn btn-xs btn-info " onclick = " editCalendario( { { $cal->id }}) " title = " Modifica " >
< i class = " fas fa-edit " ></ i >
</ button >
< button type = " button " class = " btn btn-xs btn-success " onclick = " testCalendario( { { $cal->id }}, this) " title = " Test Connessione " >
< i class = " fas fa-plug " ></ i >
</ button >
< form action = " { { route('calendario-connessioni.sync', $cal->id ) }} " method = " POST " class = " d-inline " onsubmit = " return confirm('Avviare la sincronizzazione ora?') " >
@ csrf
< button type = " submit " class = " btn btn-xs btn-primary " title = " Sincronizza Ora " >
< i class = " fas fa-sync " ></ i >
</ button >
</ form >
< button type = " button " class = " btn btn-xs btn-danger " onclick = " deleteCalendario( { { $cal->id }}, ' { { addslashes( $cal->nome ) }}') " title = " Elimina " >
< i class = " fas fa-trash " ></ i >
</ button >
</ td >
</ tr >
@ endforeach
</ tbody >
</ table >
2026-05-26 14:10:04 +02:00
</ div >
2026-06-02 22:07:16 +02:00
@ else
< div class = " text-center text-muted py-4 " >
< i class = " fas fa-calendar-plus fa-3x mb-3 " ></ i >
< p class = " mb-0 " > Nessun calendario remoto configurato .</ p >
< p class = " mb-0 " > Clicca " Nuova Connessione " per collegare Google Calendar o un server CalDAV ( Infomaniak , NextCloud ) .</ p >
2026-05-26 14:10:04 +02:00
</ div >
2026-06-02 22:07:16 +02:00
@ endif
2026-05-26 14:10:04 +02:00
</ div >
</ div >
</ div >
{{ -- === TIPOLOGIE DOCUMENTI === -- }}
2026-05-26 08:14:29 +02:00
< div class = " tab-pane active " id = " tipologie " >
< div class = " card card-primary " >
< div class = " card-header " >
< h3 class = " card-title " > Tipologie Documenti </ h3 >
</ div >
< div class = " card-body " >
< p class = " text-muted " > Gestisci le tipologie disponibili per i documenti caricati nel sistema .</ p >
@ if ( session ( 'success' ))
< div class = " alert alert-success " > {{ session ( 'success' ) }} </ div >
@ endif
@ if ( session ( 'error' ))
< div class = " alert alert-danger " > {{ session ( 'error' ) }} </ div >
@ endif
< div class = " mb-3 " >
< button type = " button " class = " btn btn-success btn-sm " data - toggle = " modal " data - target = " #addTipologiaModal " >
< i class = " fas fa-plus " ></ i > Nuova Tipologia
</ button >
</ div >
< table class = " table table-bordered table-striped " id = " tipologie-table " >
< thead >
< tr >
< th style = " width: 40px; " > Ordine </ th >
< th > Nome </ th >
< th > Descrizione </ th >
< th style = " width: 100px; " > Stato </ th >
< th style = " width: 150px; " > Azioni </ th >
</ tr >
</ thead >
< tbody id = " tipologie-sortable " >
@ foreach ( $tipologie as $tipologia )
< tr data - id = " { { $tipologia->id }} " >
< td class = " text-center " >
< i class = " fas fa-arrows-alt handle " style = " cursor: grab; " ></ i >
</ td >
< td >
< span class = " tipologia-nome " > {{ $tipologia -> nome }} </ span >
</ td >
< td > {{ $tipologia -> descrizione ? ? '-' }} </ td >
< td >
@ if ( $tipologia -> attiva )
< span class = " badge badge-success " > Attiva </ span >
@ else
< span class = " badge badge-secondary " > Disattivata </ span >
@ endif
</ td >
< td >
< button type = " button " class = " btn btn-xs btn-warning " onclick = " editTipologia( { { $tipologia->id }}, ' { { addslashes( $tipologia->nome ) }}', ' { { addslashes( $tipologia->descrizione ?? '') }}', { { $tipologia->attiva ? 'true' : 'false' }}) " >
< i class = " fas fa-edit " ></ i >
</ button >
@ if ( $tipologia -> documenti () -> count () == 0 )
< form method = " POST " action = " { { route('impostazioni.tipologie.destroy', $tipologia->id ) }} " style = " display: inline; " >
@ csrf
@ method ( 'DELETE' )
< button type = " submit " class = " btn btn-xs btn-danger " onclick = " return confirm('Eliminare questa tipologia?') " >
< i class = " fas fa-trash " ></ i >
</ button >
</ form >
@ else
< button type = " button " class = " btn btn-xs btn-danger " disabled title = " Documenti associati: { { $tipologia->documenti ()->count() }} " >
< i class = " fas fa-trash " ></ i >
</ button >
@ endif
</ td >
</ tr >
@ endforeach
</ tbody >
</ table >
</ div >
</ div >
</ div >
2026-05-26 14:10:04 +02:00
{{ -- === TIPOLOGIE EVENTI === -- }}
< div class = " tab-pane " id = " tipologie-eventi " >
2026-05-26 08:14:29 +02:00
< div class = " card card-primary " >
< div class = " card-header " >
2026-05-26 14:10:04 +02:00
< h3 class = " card-title " > Tipologie Eventi </ h3 >
2026-05-26 08:14:29 +02:00
</ div >
< div class = " card-body " >
2026-05-26 14:10:04 +02:00
< p class = " text-muted " > Gestisci le tipologie disponibili per gli eventi del calendario .</ p >
2026-05-26 08:14:29 +02:00
@ if ( session ( 'success' ))
< div class = " alert alert-success " > {{ session ( 'success' ) }} </ div >
@ endif
@ if ( session ( 'error' ))
< div class = " alert alert-danger " > {{ session ( 'error' ) }} </ div >
@ endif
< div class = " mb-3 " >
2026-05-26 14:10:04 +02:00
< button type = " button " class = " btn btn-success btn-sm " data - toggle = " modal " data - target = " #addTipologiaEventoModal " >
< i class = " fas fa-plus " ></ i > Nuova Tipologia
2026-05-26 08:14:29 +02:00
</ button >
</ div >
2026-05-26 14:10:04 +02:00
< table class = " table table-bordered table-striped " id = " tipologie-eventi-table " >
2026-05-26 08:14:29 +02:00
< thead >
< tr >
< th style = " width: 40px; " > Ordine </ th >
< th > Nome </ th >
< th > Descrizione </ th >
< th style = " width: 100px; " > Stato </ th >
< th style = " width: 150px; " > Azioni </ th >
</ tr >
</ thead >
2026-05-26 14:10:04 +02:00
< tbody id = " tipologie-eventi-sortable " >
@ foreach ( $tipologieEventi as $tipologia )
< tr data - id = " { { $tipologia->id }} " >
2026-05-26 08:14:29 +02:00
< td class = " text-center " >
< i class = " fas fa-arrows-alt handle " style = " cursor: grab; " ></ i >
</ td >
< td >
2026-05-26 14:10:04 +02:00
< span class = " tipologia-evento-nome " > {{ $tipologia -> nome }} </ span >
2026-05-26 08:14:29 +02:00
</ td >
2026-05-26 14:10:04 +02:00
< td > {{ $tipologia -> descrizione ? ? '-' }} </ td >
2026-05-26 08:14:29 +02:00
< td >
2026-05-26 14:10:04 +02:00
@ if ( $tipologia -> attiva )
< span class = " badge badge-success " > Attiva </ span >
2026-05-26 08:14:29 +02:00
@ else
2026-05-26 14:10:04 +02:00
< span class = " badge badge-secondary " > Disattivata </ span >
2026-05-26 08:14:29 +02:00
@ endif
</ td >
< td >
2026-05-26 14:10:04 +02:00
< button type = " button " class = " btn btn-xs btn-warning " onclick = " editTipologiaEvento( { { $tipologia->id }}, ' { { addslashes( $tipologia->nome ) }}', ' { { addslashes( $tipologia->descrizione ?? '') }}', { { $tipologia->attiva ? 'true' : 'false' }}) " >
2026-05-26 08:14:29 +02:00
< i class = " fas fa-edit " ></ i >
</ button >
2026-05-26 14:10:04 +02:00
@ if ( $tipologia -> eventi () -> count () == 0 )
< form method = " POST " action = " { { route('impostazioni.tipologie-eventi.destroy', $tipologia->id ) }} " style = " display: inline; " >
2026-05-26 08:14:29 +02:00
@ csrf
@ method ( 'DELETE' )
2026-05-26 14:10:04 +02:00
< button type = " submit " class = " btn btn-xs btn-danger " onclick = " return confirm('Eliminare questa tipologia?') " >
2026-05-26 08:14:29 +02:00
< i class = " fas fa-trash " ></ i >
</ button >
</ form >
@ else
2026-05-26 14:10:04 +02:00
< button type = " button " class = " btn btn-xs btn-danger " disabled title = " Eventi associati: { { $tipologia->eventi ()->count() }} " >
2026-05-26 08:14:29 +02:00
< i class = " fas fa-trash " ></ i >
</ button >
@ endif
</ td >
</ tr >
@ endforeach
</ tbody >
</ table >
</ div >
</ div >
</ div >
2026-05-26 12:28:39 +02:00
2026-05-26 14:10:04 +02:00
{{ -- === TIPI DI RUOLO === -- }}
< div class = " tab-pane " id = " ruoli " >
2026-05-26 12:28:39 +02:00
< div class = " card card-primary " >
< div class = " card-header " >
2026-05-26 14:10:04 +02:00
< h3 class = " card-title " > Tipi di Ruolo </ h3 >
2026-05-26 12:28:39 +02:00
</ div >
< div class = " card-body " >
2026-05-26 14:10:04 +02:00
< p class = " text-muted " > Gestisci i ruoli che possono essere assegnati agli individui nei gruppi .</ p >
2026-05-26 12:28:39 +02:00
@ if ( session ( 'success' ))
< div class = " alert alert-success " > {{ session ( 'success' ) }} </ div >
@ endif
@ if ( session ( 'error' ))
< div class = " alert alert-danger " > {{ session ( 'error' ) }} </ div >
@ endif
< div class = " mb-3 " >
2026-05-26 14:10:04 +02:00
< button type = " button " class = " btn btn-success btn-sm " data - toggle = " modal " data - target = " #addRuoloModal " >
< i class = " fas fa-plus " ></ i > Nuovo Ruolo
2026-05-26 12:28:39 +02:00
</ button >
</ div >
2026-05-26 14:10:04 +02:00
< table class = " table table-bordered table-striped " id = " ruoli-table " >
2026-05-26 12:28:39 +02:00
< thead >
< tr >
< th style = " width: 40px; " > Ordine </ th >
< th > Nome </ th >
< th > Descrizione </ th >
< th style = " width: 100px; " > Stato </ th >
< th style = " width: 150px; " > Azioni </ th >
</ tr >
</ thead >
2026-05-26 14:10:04 +02:00
< tbody id = " ruoli-sortable " >
@ foreach ( $ruoli as $ruolo )
< tr data - id = " { { $ruolo->id }} " >
2026-05-26 12:28:39 +02:00
< td class = " text-center " >
< i class = " fas fa-arrows-alt handle " style = " cursor: grab; " ></ i >
</ td >
< td >
2026-05-26 14:10:04 +02:00
< span class = " ruolo-nome " > {{ $ruolo -> nome }} </ span >
2026-05-26 12:28:39 +02:00
</ td >
2026-05-26 14:10:04 +02:00
< td > {{ $ruolo -> descrizione ? ? '-' }} </ td >
2026-05-26 12:28:39 +02:00
< td >
2026-05-26 14:10:04 +02:00
@ if ( $ruolo -> attiva )
< span class = " badge badge-success " > Attivo </ span >
2026-05-26 12:28:39 +02:00
@ else
2026-05-26 14:10:04 +02:00
< span class = " badge badge-secondary " > Disattivato </ span >
2026-05-26 12:28:39 +02:00
@ endif
</ td >
< td >
2026-05-26 14:10:04 +02:00
< button type = " button " class = " btn btn-xs btn-warning " onclick = " editRuolo( { { $ruolo->id }}, ' { { addslashes( $ruolo->nome ) }}', ' { { addslashes( $ruolo->descrizione ?? '') }}', { { $ruolo->attiva ? 'true' : 'false' }}) " >
2026-05-26 12:28:39 +02:00
< i class = " fas fa-edit " ></ i >
</ button >
2026-05-26 14:10:04 +02:00
@ php $membriCount = $ruolo -> getMembriCount () @ endphp
@ if ( $membriCount == 0 )
< form method = " POST " action = " { { route('impostazioni.ruoli.destroy', $ruolo->id ) }} " style = " display: inline; " >
2026-05-26 12:28:39 +02:00
@ csrf
@ method ( 'DELETE' )
2026-05-26 14:10:04 +02:00
< button type = " submit " class = " btn btn-xs btn-danger " onclick = " return confirm('Eliminare questo ruolo?') " >
2026-05-26 12:28:39 +02:00
< i class = " fas fa-trash " ></ i >
</ button >
</ form >
@ else
2026-05-26 14:10:04 +02:00
< button type = " button " class = " btn btn-xs btn-danger " disabled title = " Membri associati: { { $membriCount }} " >
2026-05-26 12:28:39 +02:00
< i class = " fas fa-trash " ></ i >
</ button >
@ endif
</ td >
</ tr >
@ endforeach
</ tbody >
</ table >
</ div >
</ div >
</ div >
2026-05-26 08:14:29 +02:00
</ div >
</ div >
</ div >
2026-05-26 14:10:04 +02:00
{{ -- ===== MODALI TIPOLOGIE DOCUMENTI ===== -- }}
2026-05-26 08:14:29 +02:00
< div class = " modal fade " id = " addTipologiaModal " >
< div class = " modal-dialog " >
< div class = " modal-content " >
< form method = " POST " action = " { { route('impostazioni.tipologie.store') }} " >
@ csrf
< div class = " modal-header " >
< h4 class = " modal-title " > Nuova Tipologia </ h4 >
< button type = " button " class = " close " data - dismiss = " modal " >& times ; </ button >
</ div >
< div class = " modal-body " >
< div class = " form-group " >
< label for = " nome " > Nome *</ label >
< input type = " text " name = " nome " id = " nome " class = " form-control " required maxlength = " 50 " placeholder = " es. certificato " >
</ div >
< div class = " form-group " >
< label for = " descrizione " > Descrizione </ label >
< input type = " text " name = " descrizione " id = " descrizione " class = " form-control " maxlength = " 255 " placeholder = " es. Certificato di formazione " >
</ div >
</ div >
< div class = " modal-footer " >
< button type = " button " class = " btn btn-default " data - dismiss = " modal " > Annulla </ button >
< button type = " submit " class = " btn btn-primary " > Salva </ button >
</ div >
</ form >
</ div >
</ div >
</ div >
< div class = " modal fade " id = " editTipologiaModal " >
< div class = " modal-dialog " >
< div class = " modal-content " >
< form method = " POST " action = " " id = " editTipologiaForm " >
@ csrf
@ method ( 'PUT' )
< input type = " hidden " name = " id " id = " edit_tipologia_id " >
< div class = " modal-header " >
< h4 class = " modal-title " > Modifica Tipologia </ h4 >
< button type = " button " class = " close " data - dismiss = " modal " >& times ; </ button >
</ div >
< div class = " modal-body " >
< div class = " form-group " >
< label for = " edit_tipologia_nome " > Nome *</ label >
< input type = " text " name = " nome " id = " edit_tipologia_nome " class = " form-control " required maxlength = " 50 " >
</ div >
< div class = " form-group " >
< label for = " edit_tipologia_descrizione " > Descrizione </ label >
< input type = " text " name = " descrizione " id = " edit_tipologia_descrizione " class = " form-control " maxlength = " 255 " >
</ div >
< div class = " form-group " >
< div class = " custom-control custom-switch " >
< input type = " checkbox " class = " custom-control-input " id = " edit_tipologia_attiva " name = " attiva " value = " 1 " >
< label class = " custom-control-label " for = " edit_tipologia_attiva " > Attiva </ label >
</ div >
</ div >
</ div >
< div class = " modal-footer " >
< button type = " button " class = " btn btn-default " data - dismiss = " modal " > Annulla </ button >
< button type = " submit " class = " btn btn-primary " > Salva </ button >
</ div >
</ form >
</ div >
</ div >
</ div >
2026-05-26 14:10:04 +02:00
{{ -- ===== MODALI TIPI DI RUOLO ===== -- }}
2026-05-26 08:14:29 +02:00
< div class = " modal fade " id = " addRuoloModal " >
< div class = " modal-dialog " >
< div class = " modal-content " >
< form method = " POST " action = " { { route('impostazioni.ruoli.store') }} " >
@ csrf
< div class = " modal-header " >
< h4 class = " modal-title " > Nuovo Ruolo </ h4 >
< button type = " button " class = " close " data - dismiss = " modal " >& times ; </ button >
</ div >
< div class = " modal-body " >
< div class = " form-group " >
< label for = " ruolo_nome " > Nome *</ label >
< input type = " text " name = " nome " id = " ruolo_nome " class = " form-control " required maxlength = " 50 " placeholder = " es. Catechista " >
</ div >
< div class = " form-group " >
< label for = " ruolo_descrizione " > Descrizione </ label >
< input type = " text " name = " descrizione " id = " ruolo_descrizione " class = " form-control " maxlength = " 255 " placeholder = " es. Catechista del gruppo " >
</ div >
</ div >
< div class = " modal-footer " >
< button type = " button " class = " btn btn-default " data - dismiss = " modal " > Annulla </ button >
< button type = " submit " class = " btn btn-primary " > Salva </ button >
</ div >
</ form >
</ div >
</ div >
</ div >
< div class = " modal fade " id = " editRuoloModal " >
< div class = " modal-dialog " >
< div class = " modal-content " >
< form method = " POST " action = " " id = " editRuoloForm " >
@ csrf
@ method ( 'PUT' )
< input type = " hidden " name = " id " id = " edit_ruolo_id " >
< div class = " modal-header " >
< h4 class = " modal-title " > Modifica Ruolo </ h4 >
< button type = " button " class = " close " data - dismiss = " modal " >& times ; </ button >
</ div >
< div class = " modal-body " >
< div class = " form-group " >
< label for = " edit_ruolo_nome " > Nome *</ label >
< input type = " text " name = " nome " id = " edit_ruolo_nome " class = " form-control " required maxlength = " 50 " >
</ div >
< div class = " form-group " >
< label for = " edit_ruolo_descrizione " > Descrizione </ label >
< input type = " text " name = " descrizione " id = " edit_ruolo_descrizione " class = " form-control " maxlength = " 255 " >
</ div >
< div class = " form-group " >
< div class = " custom-control custom-switch " >
< input type = " checkbox " class = " custom-control-input " id = " edit_ruolo_attiva " name = " attiva " value = " 1 " >
< label class = " custom-control-label " for = " edit_ruolo_attiva " > Attivo </ label >
</ div >
</ div >
</ div >
< div class = " modal-footer " >
< button type = " button " class = " btn btn-default " data - dismiss = " modal " > Annulla </ button >
< button type = " submit " class = " btn btn-primary " > Salva </ button >
</ div >
</ form >
</ div >
</ div >
</ div >
2026-05-26 12:28:39 +02:00
2026-05-26 14:10:04 +02:00
{{ -- ===== MODALI TIPOLOGIE EVENTI ===== -- }}
2026-05-26 12:28:39 +02:00
< div class = " modal fade " id = " addTipologiaEventoModal " >
< div class = " modal-dialog " >
< div class = " modal-content " >
< form method = " POST " action = " { { route('impostazioni.tipologie-eventi.store') }} " >
@ csrf
< div class = " modal-header " >
< h4 class = " modal-title " > Nuova Tipologia Evento </ h4 >
< button type = " button " class = " close " data - dismiss = " modal " >& times ; </ button >
</ div >
< div class = " modal-body " >
< div class = " form-group " >
< label for = " tipologia_evento_nome " > Nome *</ label >
< input type = " text " name = " nome " id = " tipologia_evento_nome " class = " form-control " required maxlength = " 50 " placeholder = " es. catechesi " >
</ div >
< div class = " form-group " >
< label for = " tipologia_evento_descrizione " > Descrizione </ label >
< input type = " text " name = " descrizione " id = " tipologia_evento_descrizione " class = " form-control " maxlength = " 255 " placeholder = " es. Catechesi " >
</ div >
</ div >
< div class = " modal-footer " >
< button type = " button " class = " btn btn-default " data - dismiss = " modal " > Annulla </ button >
< button type = " submit " class = " btn btn-primary " > Salva </ button >
</ div >
</ form >
</ div >
</ div >
</ div >
< div class = " modal fade " id = " editTipologiaEventoModal " >
< div class = " modal-dialog " >
< div class = " modal-content " >
< form method = " POST " action = " " id = " editTipologiaEventoForm " >
@ csrf
@ method ( 'PUT' )
< input type = " hidden " name = " id " id = " edit_tipologia_evento_id " >
< div class = " modal-header " >
< h4 class = " modal-title " > Modifica Tipologia Evento </ h4 >
< button type = " button " class = " close " data - dismiss = " modal " >& times ; </ button >
</ div >
< div class = " modal-body " >
< div class = " form-group " >
< label for = " edit_tipologia_evento_nome " > Nome *</ label >
< input type = " text " name = " nome " id = " edit_tipologia_evento_nome " class = " form-control " required maxlength = " 50 " >
</ div >
< div class = " form-group " >
< label for = " edit_tipologia_evento_descrizione " > Descrizione </ label >
< input type = " text " name = " descrizione " id = " edit_tipologia_evento_descrizione " class = " form-control " maxlength = " 255 " >
</ div >
< div class = " form-group " >
< div class = " custom-control custom-switch " >
< input type = " checkbox " class = " custom-control-input " id = " edit_tipologia_evento_attiva " name = " attiva " value = " 1 " >
< label class = " custom-control-label " for = " edit_tipologia_evento_attiva " > Attiva </ label >
</ div >
</ div >
</ div >
< div class = " modal-footer " >
< button type = " button " class = " btn btn-default " data - dismiss = " modal " > Annulla </ button >
< button type = " submit " class = " btn btn-primary " > Salva </ button >
</ div >
</ form >
</ div >
</ div >
</ div >
2026-05-27 08:37:37 +02:00
{{ -- ===== MODALE MITTENTI AGGIUNTIVI ===== -- }}
< div class = " modal fade " id = " senderModal " tabindex = " -1 " role = " dialog " >
< div class = " modal-dialog " role = " document " >
< div class = " modal-content " >
< form id = " senderForm " method = " POST " action = " { { route('impostazioni.sender.store') }} " >
@ csrf
< input type = " hidden " name = " _method " id = " senderMethod " value = " POST " >
< input type = " hidden " name = " id " id = " senderId " value = " " >
< div class = " modal-header bg-primary " >
< h5 class = " modal-title " id = " senderModalTitle " >< i class = " fas fa-user-plus mr-2 " ></ i > Nuovo Mittente </ h5 >
< button type = " button " class = " close text-white " data - dismiss = " modal " >& times ; </ button >
</ div >
< div class = " modal-body " >
< div class = " row " >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " sender_email " > Email *</ label >
< input type = " email " name = " email_address " id = " sender_email " class = " form-control " required placeholder = " newsletter@parrocchia.it " >
</ div >
</ div >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " sender_name " > Nome visualizzato </ label >
< input type = " text " name = " email_name " id = " sender_name " class = " form-control " placeholder = " Newsletter Parrocchiale " >
</ div >
</ div >
</ div >
< hr >
< h6 > Configurazione SMTP </ h6 >
< div class = " row " >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " sender_smtp_host " > Host SMTP </ label >
< input type = " text " name = " smtp_host " id = " sender_smtp_host " class = " form-control " placeholder = " smtp.gmail.com " >
</ div >
</ div >
< div class = " col-md-3 " >
< div class = " form-group " >
< label for = " sender_smtp_port " > Porta </ label >
< input type = " number " name = " smtp_port " id = " sender_smtp_port " class = " form-control " value = " 587 " >
</ div >
</ div >
< div class = " col-md-3 " >
< div class = " form-group " >
< label for = " sender_smtp_encryption " > Crittografia </ label >
< select name = " smtp_encryption " id = " sender_smtp_encryption " class = " form-control " >
< option value = " tls " > TLS </ option >
< option value = " ssl " > SSL </ option >
< option value = " none " > Nessuna </ option >
</ select >
</ div >
</ div >
</ div >
< div class = " row " >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " sender_smtp_username " > Username SMTP </ label >
< input type = " text " name = " smtp_username " id = " sender_smtp_username " class = " form-control " placeholder = " Lascia vuoto per usare l'email " >
</ div >
</ div >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " sender_smtp_password " > Password SMTP </ label >
< input type = " password " name = " smtp_password " id = " sender_smtp_password " class = " form-control " placeholder = " ...... " >
< small class = " text-muted " > Lascia vuoto per non cambiare </ small >
</ div >
</ div >
</ div >
< hr >
< div class = " row " >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " sender_reply_to " > Reply - To < small class = " text-muted " > ( no - reply ) </ small ></ label >
< input type = " email " name = " reply_to " id = " sender_reply_to " class = " form-control " placeholder = " no-reply@parrocchia.it " >
< small class = " text-muted " > Indirizzo di risposta per le email inviate </ small >
</ div >
</ div >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " sender_verify_email " > Verify Email < small class = " text-muted " > ( report ) </ small ></ label >
< input type = " email " name = " verify_email " id = " sender_verify_email " class = " form-control " placeholder = " verifica@parrocchia.it " >
< small class = " text-muted " > Riceve report riepilogo dopo invii massivi </ small >
</ div >
</ div >
</ div >
< div class = " form-group " >
< label for = " sender_note " > Nota interna </ label >
< textarea name = " note " id = " sender_note " class = " form-control " rows = " 2 " placeholder = " Es. Newsletter settimanale " ></ textarea >
</ div >
< div class = " form-group " >
< div class = " custom-control custom-switch " >
< input type = " checkbox " class = " custom-control-input " id = " sender_is_active " name = " is_active " value = " 1 " checked >
< label class = " custom-control-label " for = " sender_is_active " > Mittente attivo </ label >
</ div >
</ div >
</ div >
< div class = " modal-footer " >
< button type = " button " class = " btn btn-secondary " data - dismiss = " modal " > Annulla </ button >
< button type = " submit " class = " btn btn-primary " >
< i class = " fas fa-save mr-1 " ></ i > Salva Mittente
</ button >
</ div >
</ form >
</ div >
</ div >
</ div >
2026-06-02 22:07:16 +02:00
{{ -- ===== MODALE CONNESSIONE CALENDARIO ===== -- }}
< div class = " modal fade " id = " calendarioModal " tabindex = " -1 " role = " dialog " >
< div class = " modal-dialog modal-lg " role = " document " >
< div class = " modal-content " >
< form id = " calendarioForm " method = " POST " action = " { { route('calendario-connessioni.store') }} " >
@ csrf
< input type = " hidden " name = " _method " id = " calendarioMethod " value = " POST " >
< input type = " hidden " name = " id " id = " calendarioId " value = " " >
< div class = " modal-header bg-primary " >
< h5 class = " modal-title " id = " calendarioModalTitle " >< i class = " fas fa-calendar-plus mr-2 " ></ i > Nuova Connessione Calendario </ h5 >
< button type = " button " class = " close text-white " data - dismiss = " modal " >& times ; </ button >
</ div >
< div class = " modal-body " >
< div class = " row " >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " cal_nome " > Nome *</ label >
< input type = " text " name = " nome " id = " cal_nome " class = " form-control " required placeholder = " es. Calendario Parrocchia " >
</ div >
</ div >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " cal_tipo " > Tipo *</ label >
< select name = " tipo " id = " cal_tipo " class = " form-control " required onchange = " toggleCalendarioConfigFields() " >
< option value = " caldav " > CalDAV ( Infomaniak / NextCloud ) </ option >
< option value = " google_calendar " > Google Calendar </ option >
</ select >
</ div >
</ div >
</ div >
< div class = " row " >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " cal_sync_direction " > Direzione Sync </ label >
< select name = " sync_direction " id = " cal_sync_direction " class = " form-control " >
< option value = " bidirectional " > Bidirezionale </ option >
< option value = " import " > Solo Import ( da remoto a locale ) </ option >
< option value = " export " > Solo Export ( da locale a remoto ) </ option >
</ select >
</ div >
</ div >
< div class = " col-md-6 " >
< div class = " form-group " >
< label for = " cal_sync_interval " > Intervallo Sync ( minuti ) </ label >
< select name = " sync_interval_minutes " id = " cal_sync_interval " class = " form-control " >
< option value = " 5 " > 5 minuti </ option >
< option value = " 15 " > 15 minuti </ option >
< option value = " 30 " > 30 minuti </ option >
< option value = " 60 " selected > 1 ora </ option >
< option value = " 360 " > 6 ore </ option >
< option value = " 1440 " > 24 ore </ option >
</ select >
</ div >
</ div >
</ div >
< div class = " form-group " >
< div class = " custom-control custom-switch " >
< input type = " checkbox " class = " custom-control-input " id = " cal_is_active " name = " is_active " value = " 1 " checked >
< label class = " custom-control-label " for = " cal_is_active " > Connessione attiva </ label >
</ div >
</ div >
< hr >
< h6 > Configurazione </ h6 >
{{ -- CalDAV Fields -- }}
< div id = " caldavFields " >
< div class = " form-group " >
< label for = " cal_caldav_url " > URL Server CalDAV *</ label >
< input type = " url " name = " config[url] " id = " cal_caldav_url " class = " form-control " placeholder = " es. https://nextcloud.parrocchia.it/remote.php/dav/calendars/utente/ " >
< small class = " text-muted " > URL principale del server CalDAV ( es . NextCloud , Infomaniak , Synology ) </ small >
</ div >
< div class = " form-group " >
< label for = " cal_caldav_calendar_url " > URL Calendario ( opzionale ) </ label >
< input type = " url " name = " config[calendar_url] " id = " cal_caldav_calendar_url " class = " form-control " placeholder = " Lascia vuoto per usare l'URL principale " >
< small class = " text-muted " > URL specifico del calendario , se diverso dall 'URL del server</small>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="cal_caldav_username">Username</label>
<input type="text" name="config[username]" id="cal_caldav_username" class="form-control">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="cal_caldav_password">Password / App Password</label>
<input type="password" name="config[password]" id="cal_caldav_password" class="form-control">
</div>
</div>
</div>
</div>
{{-- Google Calendar Fields --}}
<div id="googleCalendarFields" style="display:none;">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="cal_gc_client_id">Client ID *</label>
<input type="text" name="config[client_id]" id="cal_gc_client_id" class="form-control" placeholder="Google Client ID">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="cal_gc_client_secret">Client Secret *</label>
<input type="password" name="config[client_secret]" id="cal_gc_client_secret" class="form-control" placeholder="Google Client Secret">
</div>
</div>
</div>
<div class="form-group">
<label for="cal_gc_refresh_token">Refresh Token</label>
<input type="text" name="config[refresh_token]" id="cal_gc_refresh_token" class="form-control" placeholder="Generato dopo l' autorizzazione OAuth " >
<small class= " text - muted " >Dopo aver configurato Client ID e Client Secret, salva la connessione e usa il test per verificare.</small>
</div>
<div class= " form - group " >
<label for= " cal_gc_calendar_id " >Calendar ID</label>
<input type= " text " name= " config [ calendar_id ] " id= " cal_gc_calendar_id " class= " form - control " value= " primary " placeholder= " primary " >
<small class= " text - muted " >ID del calendario Google (default: primary per il calendario principale)</small>
</div>
<div class= " alert alert - info " >
<i class= " fas fa - info - circle mr - 2 " ></i>
<strong>Google Calendar:</strong> Crea il progetto in <a href= " https :// console . cloud . google . com / " target= " _blank " >Google Cloud Console</a>
→ API & Services → Credentials → Crea OAuth Client ID (Web Application).
Abilita <strong>Google Calendar API</strong> e configura l'URI di redirect.
</div>
</div>
</div>
<div class= " modal - footer " >
<button type= " button " class= " btn btn - secondary " data-dismiss= " modal " >Annulla</button>
<button type= " submit " class= " btn btn - primary " >
<i class= " fas fa - save mr - 1 " ></i> Salva Connessione
</button>
</div>
</form>
</div>
</div>
</div>
2026-05-26 08:14:29 +02:00
@endsection
@section('scripts')
<script src= " https :// cdn . jsdelivr . net / npm / sortablejs @ 1.15 . 0 / Sortable . min . js " ></script>
<script>
2026-05-26 12:28:39 +02:00
function activateTabFromHash() {
var hash = window.location.hash;
if (hash) {
var tabLink = document.querySelector('.list-group a[href= " ' + hash + ' " ]');
if (tabLink) {
$ (tabLink).tab('show');
}
}
}
$ (document).ready(function() {
activateTabFromHash();
});
$ (window).on('hashchange', function() {
activateTabFromHash();
});
2026-05-26 08:14:29 +02:00
function editTipologia(id, nome, descrizione, attiva) {
$ ('#edit_tipologia_id').val(id);
$ ('#edit_tipologia_nome').val(nome);
$ ('#edit_tipologia_descrizione').val(descrizione);
$ ('#edit_tipologia_attiva').prop('checked', attiva);
$ ('#editTipologiaForm').attr('action', '/impostazioni/tipologie/' + id);
$ ('#editTipologiaModal').modal('show');
}
function editRuolo(id, nome, descrizione, attiva) {
$ ('#edit_ruolo_id').val(id);
$ ('#edit_ruolo_nome').val(nome);
$ ('#edit_ruolo_descrizione').val(descrizione);
$ ('#edit_ruolo_attiva').prop('checked', attiva);
$ ('#editRuoloForm').attr('action', '/impostazioni/ruoli/' + id);
$ ('#editRuoloModal').modal('show');
}
2026-05-26 12:28:39 +02:00
function editTipologiaEvento(id, nome, descrizione, attiva) {
$ ('#edit_tipologia_evento_id').val(id);
$ ('#edit_tipologia_evento_nome').val(nome);
$ ('#edit_tipologia_evento_descrizione').val(descrizione);
$ ('#edit_tipologia_evento_attiva').prop('checked', attiva);
$ ('#editTipologiaEventoForm').attr('action', '/impostazioni/tipologie-eventi/' + id);
$ ('#editTipologiaEventoModal').modal('show');
}
2026-05-26 08:14:29 +02:00
var sortableTipologie = Sortable.create(document.getElementById('tipologie-sortable'), {
handle: '.handle',
animation: 150,
onEnd: function(evt) {
var order = [];
$ ('#tipologie-sortable tr').each(function() {
order.push( $ (this).data('id'));
});
fetch(' { { route('impostazioni.tipologie.reorder') }}', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': ' { { csrf_token() }}',
'Content-Type': 'application/json',
},
body: JSON.stringify( { order: order })
});
}
});
var sortableRuoli = Sortable.create(document.getElementById('ruoli-sortable'), {
handle: '.handle',
animation: 150,
onEnd: function(evt) {
var order = [];
$ ('#ruoli-sortable tr').each(function() {
order.push( $ (this).data('id'));
});
fetch(' { { route('impostazioni.ruoli.reorder') }}', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': ' { { csrf_token() }}',
'Content-Type': 'application/json',
},
body: JSON.stringify( { order: order })
});
}
});
2026-05-26 12:28:39 +02:00
var sortableTipologieEventi = Sortable.create(document.getElementById('tipologie-eventi-sortable'), {
handle: '.handle',
animation: 150,
onEnd: function(evt) {
var order = [];
$ ('#tipologie-eventi-sortable tr').each(function() {
order.push( $ (this).data('id'));
});
fetch(' { { route('impostazioni.tipologie-eventi.reorder') }}', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': ' { { csrf_token() }}',
'Content-Type': 'application/json',
},
body: JSON.stringify( { order: order })
});
}
});
2026-05-26 08:14:29 +02:00
$ ('a[data-toggle= " tab " ]').on('shown.bs.tab', function (e) {
var target = $ (e.target).attr('href');
if (target === '#ruoli') {
sortableRuoli.refresh();
}
2026-05-26 12:28:39 +02:00
if (target === '#tipologie-eventi') {
sortableTipologieEventi.refresh();
}
2026-06-02 22:07:16 +02:00
if (target === '#calendario') {
if (typeof sortableCalendario !== 'undefined') {
sortableCalendario.refresh();
}
}
2026-06-08 12:09:45 +02:00
if (target === '#email-firma') {
setTimeout(initSignatureEditor, 100);
}
2026-05-26 08:14:29 +02:00
});
2026-05-26 14:10:04 +02:00
2026-05-27 08:37:37 +02:00
// ===== MITTENTI AGGIUNTIVI =====
let senderAccounts = @json( $senderAccounts );
function resetSenderForm() {
document.getElementById('senderForm').action = ' { { route('impostazioni.sender.store') }}';
document.getElementById('senderMethod').value = 'POST';
document.getElementById('senderModalTitle').textContent = 'Nuovo Mittente';
document.getElementById('senderForm').reset();
document.getElementById('senderId').value = '';
document.getElementById('sender_is_active').checked = true;
document.getElementById('sender_smtp_password').placeholder = '';
document.getElementById('sender_smtp_password').required = false;
}
function editSender(id) {
const sender = senderAccounts.find(s => s.id === id);
if (!sender) return;
document.getElementById('senderForm').action = ' { { route('impostazioni.sender.update', '__ID__') }}'.replace('__ID__', id);
document.getElementById('senderMethod').value = 'PUT';
document.getElementById('senderModalTitle').textContent = 'Modifica Mittente - ' + sender.email_address;
document.getElementById('senderId').value = sender.id;
document.getElementById('sender_email').value = sender.email_address;
document.getElementById('sender_name').value = sender.email_name || '';
document.getElementById('sender_smtp_host').value = sender.smtp_host || '';
document.getElementById('sender_smtp_port').value = sender.smtp_port || 587;
document.getElementById('sender_smtp_encryption').value = sender.smtp_encryption || 'tls';
document.getElementById('sender_smtp_username').value = sender.smtp_username || '';
document.getElementById('sender_smtp_password').value = '';
document.getElementById('sender_smtp_password').placeholder = '......';
document.getElementById('sender_smtp_password').required = false;
document.getElementById('sender_reply_to').value = sender.reply_to || '';
document.getElementById('sender_verify_email').value = sender.verify_email || '';
document.getElementById('sender_note').value = sender.note || '';
document.getElementById('sender_is_active').checked = sender.is_active;
$ ('#senderModal').modal('show');
}
function deleteSender(id, email) {
if (!confirm('Eliminare il mittente ' + email + '?')) return;
var url = ' { { route('impostazioni.sender.destroy', '__ID__') }}'.replace('__ID__', id);
fetch(url, {
method: 'POST',
headers: {
'X-CSRF-TOKEN': ' { { csrf_token() }}',
'X-HTTP-Method-Override': 'DELETE'
}
}).then(function(r) { return r.json(); }).then(function(data) {
if (data.success) {
location.reload();
} else {
alert('❌ ' + (data.message || 'Errore'));
}
}).catch(function() {
alert('❌ Errore di rete');
});
}
function testSenderSmtp(id) {
const email = prompt('Inserisci l \ 'indirizzo email a cui inviare il test:');
if (!email || !email.includes('@')) return;
const btn = event.target;
btn.disabled = true;
btn.innerHTML = '<i class= " fas fa - spinner fa - spin " ></i>';
$ .ajax( {
url: ' { { route('impostazioni.sender.test', '__ID__') }}'.replace('__ID__', id),
method: 'POST',
headers: { 'X-CSRF-TOKEN': ' { { csrf_token() }}' },
data: { email: email },
timeout: 30000,
success: function(response) {
btn.disabled = false;
btn.innerHTML = '<i class= " fas fa - paper - plane " ></i>';
alert(response.success ? '✅ ' + response.message : '❌ ' + response.message);
},
error: function(xhr) {
btn.disabled = false;
btn.innerHTML = '<i class= " fas fa - paper - plane " ></i>';
const msg = xhr.responseJSON?.message || 'Errore di connessione';
alert('❌ ' + msg);
}
});
}
2026-05-26 14:10:04 +02:00
// ===== EMAIL FUNCTIONS =====
function testConnection() {
$ .ajax( {
url: ' { { route('impostazioni.email.test') }}',
method: 'POST',
headers: { 'X-CSRF-TOKEN': ' { { csrf_token() }}' },
success: function(response) {
if (response.success) {
alert('✅ ' + response.message);
} else {
alert('❌ ' + response.message);
}
},
error: function() {
alert('❌ Errore nella richiesta');
}
});
}
function testSmtp() {
var email = prompt('Inserisci l \ 'indirizzo email a cui inviare il test:');
if (!email) return;
if (!email.includes('@')) {
alert('⚠️ Indirizzo email non valido');
return;
}
var btn = event.target;
btn.disabled = true;
btn.innerHTML = '<i class= " fas fa - spinner fa - spin " ></i> Invio...';
$ .ajax( {
url: ' { { route('impostazioni.email.testSmtp') }}',
method: 'POST',
headers: { 'X-CSRF-TOKEN': ' { { csrf_token() }}' },
data: { email: email },
timeout: 30000,
success: function(response) {
btn.disabled = false;
btn.innerHTML = '<i class= " fas fa - paper - plane mr - 1 " ></i> Test Invio Email (SMTP)';
if (response.success) {
alert('✅ ' + response.message);
} else {
alert('❌ ' + response.message);
}
},
error: function(xhr, status, error) {
btn.disabled = false;
btn.innerHTML = '<i class= " fas fa - paper - plane mr - 1 " ></i> Test Invio Email (SMTP)';
if (xhr.responseJSON && xhr.responseJSON.message) {
alert('❌ ' + xhr.responseJSON.message);
} else {
alert('❌ Errore: ' + status + ' - ' + error);
}
}
});
}
2026-06-02 22:07:16 +02:00
var quillEditorInstance = null;
2026-05-26 14:10:04 +02:00
function createEditor() {
var container = document.querySelector('#signature-editor');
2026-06-02 22:07:16 +02:00
if (!container || quillEditorInstance) return;
2026-05-26 14:10:04 +02:00
var quill = new Quill('#signature-editor', {
theme: 'snow',
modules: {
toolbar: [
['bold', 'italic', 'underline'],
[ { 'color': [] }, { 'background': [] }],
[ { 'header': 1 }, { 'header': 2 }, { 'header': 3 }],
[ { 'align': [] }],
[ { 'list': 'ordered'}, { 'list': 'bullet' }],
['link', 'image'],
['clean', 'code']
]
}
});
var signatureInput = document.getElementById('signature_input');
var isEditingHtml = false;
quill.getModule('toolbar').addHandler('code', function() {
if (!isEditingHtml) {
var textarea = document.createElement('textarea');
textarea.className = 'ql-editor';
textarea.style.cssText = 'font-family: monospace; min-height: 150px; width: 100%;';
textarea.value = signatureInput.value;
quill.root.innerHTML = '';
quill.root.appendChild(textarea);
textarea.focus();
isEditingHtml = true;
} else {
var textarea = quill.root.querySelector('textarea');
if (textarea) {
signatureInput.value = textarea.value;
quill.root.innerHTML = textarea.value;
}
isEditingHtml = false;
}
});
if (signatureInput.value) {
quill.root.innerHTML = signatureInput.value;
}
quill.on('text-change', function() {
if (!isEditingHtml) {
signatureInput.value = quill.root.innerHTML;
}
});
2026-06-02 22:07:16 +02:00
quillEditorInstance = quill;
2026-05-26 14:10:04 +02:00
}
function initSignatureEditor() {
2026-06-02 22:07:16 +02:00
if (quillEditorInstance) return;
2026-05-26 14:10:04 +02:00
if (typeof Quill === 'undefined') {
var script = document.createElement('script');
script.src = 'https://cdn.quilljs.com/1.3.7/quill.min.js';
script.onload = createEditor;
document.head.appendChild(script);
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://cdn.quilljs.com/1.3.7/quill.snow.css';
document.head.appendChild(link);
} else {
createEditor();
}
}
$ ('a[data-toggle= " tab " ]').on('shown.bs.tab', function(e) {
var target = $ (e.target).attr('href');
if (target === '#email-firma' || target === '#email') {
setTimeout(initSignatureEditor, 100);
}
});
if (window.location.hash === '#email') {
$ (document).ready(function() {
setTimeout(initSignatureEditor, 300);
});
}
2026-05-28 09:34:28 +02:00
// ===== REPOSITORY REMOTI =====
let repositories = @json( $repositories );
2026-05-28 13:25:47 +02:00
let newToken = @json( $googleDriveNewToken );
2026-05-28 09:34:28 +02:00
function resetRepoForm() {
document.getElementById('repoForm').action = ' { { route('storage-repositories.store') }}';
document.getElementById('repoMethod').value = 'POST';
document.getElementById('repoModalTitle').textContent = 'Nuovo Repository Remoto';
document.getElementById('repoForm').reset();
document.getElementById('repoId').value = '';
document.getElementById('repo_is_active').checked = true;
2026-05-28 13:25:47 +02:00
setGdAuthStatus(false, '');
2026-05-28 09:34:28 +02:00
toggleRepoConfigFields();
}
function toggleRepoConfigFields() {
const tipo = document.getElementById('repo_tipo').value;
document.getElementById('webdavFields').style.display = tipo === 'webdav' ? '' : 'none';
document.getElementById('googleDriveFields').style.display = tipo === 'google_drive' ? '' : 'none';
2026-05-28 13:25:47 +02:00
if (tipo === 'google_drive') {
updateGdAuthUrl();
}
}
function setGdAuthStatus(authorized, clientId) {
const statusEl = document.getElementById('gdAuthStatus');
const btn = document.getElementById('gdAuthBtn');
if (authorized) {
statusEl.innerHTML = '<span class= " text - success " ><i class= " fas fa - check - circle mr - 1 " ></i> Autorizzato</span>';
btn.innerHTML = '<i class= " fas fa - refresh mr - 1 " ></i> Ri-autorizza con Google';
} else {
statusEl.innerHTML = '<span class= " text - muted " ><i class= " fas fa - circle mr - 1 " ></i> Non autorizzato</span>';
btn.innerHTML = '<i class= " fas fa - google mr - 1 " ></i> Autorizza con Google';
}
}
function updateGdAuthUrl() {
const clientId = document.getElementById('gd_client_id').value.trim();
const clientSecret = document.getElementById('gd_client_secret').value.trim();
const repoId = document.getElementById('repoId').value;
const nome = document.getElementById('repo_nome').value.trim();
const isActive = document.getElementById('repo_is_active').checked ? '1' : '0';
const rootFolderId = document.getElementById('gd_root_folder_id').value.trim();
const btn = document.getElementById('gdAuthBtn');
if (clientId && clientSecret) {
const params = new URLSearchParams( {
client_id: clientId,
client_secret: clientSecret,
repo_id: repoId || '0',
nome: nome,
is_active: isActive,
root_folder_id: rootFolderId || 'root',
});
btn.href = ' { { route('google-drive.redirect') }}?' + params.toString();
btn.classList.remove('disabled');
} else {
btn.href = '#';
btn.classList.add('disabled');
}
}
function startGdAuth() {
const clientId = document.getElementById('gd_client_id').value.trim();
const clientSecret = document.getElementById('gd_client_secret').value.trim();
if (!clientId || !clientSecret) {
alert('Inserisci Client ID e Client Secret prima di autorizzare.');
return false;
}
// Open in same window (full redirect flow)
updateGdAuthUrl();
window.location.href = document.getElementById('gdAuthBtn').href;
return false;
2026-05-28 09:34:28 +02:00
}
function editRepo(id) {
const repo = repositories.find(r => r.id === id);
if (!repo) return;
document.getElementById('repoForm').action = ' { { route('storage-repositories.update', '__ID__') }}'.replace('__ID__', id);
document.getElementById('repoMethod').value = 'PUT';
document.getElementById('repoModalTitle').textContent = 'Modifica Repository - ' + repo.nome;
document.getElementById('repoId').value = repo.id;
document.getElementById('repo_nome').value = repo.nome;
document.getElementById('repo_tipo').value = repo.tipo;
document.getElementById('repo_is_active').checked = repo.is_active;
const config = repo.config || { };
document.getElementById('webdav_base_uri').value = config.base_uri || '';
document.getElementById('webdav_username').value = config.username || '';
document.getElementById('webdav_password').value = '';
document.getElementById('webdav_password').placeholder = config.password ? '......' : '';
document.getElementById('webdav_root').value = config.root || '/';
document.getElementById('webdav_auth_type').value = config.auth_type || 'basic';
document.getElementById('gd_client_id').value = config.client_id || '';
document.getElementById('gd_client_secret').value = '';
document.getElementById('gd_client_secret').placeholder = config.client_secret ? '......' : '';
2026-05-28 13:25:47 +02:00
document.getElementById('gd_refresh_token').value = config.refresh_token || '';
2026-05-28 09:34:28 +02:00
document.getElementById('gd_root_folder_id').value = config.root_folder_id || 'root';
2026-05-28 13:25:47 +02:00
const hasRefreshToken = !!(config.refresh_token && config.refresh_token !== '');
setGdAuthStatus(hasRefreshToken, config.client_id || '');
2026-05-28 09:34:28 +02:00
toggleRepoConfigFields();
$ ('#repoModal').modal('show');
}
function deleteRepo(id, nome) {
if (!confirm('Eliminare il repository " ' + nome + ' " ?')) return;
var url = ' { { route('storage-repositories.destroy', '__ID__') }}'.replace('__ID__', id);
fetch(url, {
method: 'POST',
headers: {
'X-CSRF-TOKEN': ' { { csrf_token() }}',
'X-HTTP-Method-Override': 'DELETE'
}
}).then(function(r) { return r.json(); }).then(function(data) {
if (data.success) {
location.reload();
} else {
alert('❌ ' + (data.message || 'Errore'));
}
}).catch(function() {
alert('❌ Errore di rete');
});
}
function testRepo(id, btn) {
btn.disabled = true;
btn.innerHTML = '<i class= " fas fa - spinner fa - spin " ></i> Test...';
$ .ajax( {
url: ' { { route('storage-repositories.test', '__ID__') }}'.replace('__ID__', id),
method: 'POST',
headers: { 'X-CSRF-TOKEN': ' { { csrf_token() }}' },
timeout: 30000,
success: function(response) {
btn.disabled = false;
btn.innerHTML = '<i class= " fas fa - plug " ></i>';
alert(response.success ? 'Connessione OK: ' + response.message : 'Errore: ' + response.message);
},
error: function(xhr) {
btn.disabled = false;
btn.innerHTML = '<i class= " fas fa - plug " ></i>';
const msg = xhr.responseJSON?.message || 'Errore di connessione';
alert('Errore: ' + msg);
}
});
}
2026-06-02 22:07:16 +02:00
// ===== CONNESSIONI CALENDARIO =====
var calendarioConnessioni = @json( $calendarioConnessioni ?? []);
function resetCalendarioForm() {
document.getElementById('calendarioForm').action = ' { { route('calendario-connessioni.store') }}';
document.getElementById('calendarioMethod').value = 'POST';
document.getElementById('calendarioModalTitle').textContent = 'Nuova Connessione Calendario';
document.getElementById('calendarioForm').reset();
document.getElementById('calendarioId').value = '';
document.getElementById('cal_is_active').checked = true;
document.getElementById('cal_caldav_password').placeholder = '';
document.getElementById('cal_gc_client_secret').placeholder = '';
toggleCalendarioConfigFields();
}
function toggleCalendarioConfigFields() {
const tipo = document.getElementById('cal_tipo').value;
document.getElementById('caldavFields').style.display = tipo === 'caldav' ? '' : 'none';
document.getElementById('googleCalendarFields').style.display = tipo === 'google_calendar' ? '' : 'none';
}
function editCalendario(id) {
const cal = calendarioConnessioni.find(c => c.id === id);
if (!cal) return;
document.getElementById('calendarioForm').action = ' { { route('calendario-connessioni.update', '__ID__') }}'.replace('__ID__', id);
document.getElementById('calendarioMethod').value = 'PUT';
document.getElementById('calendarioModalTitle').textContent = 'Modifica Connessione - ' + cal.nome;
document.getElementById('calendarioId').value = cal.id;
document.getElementById('cal_nome').value = cal.nome;
document.getElementById('cal_tipo').value = cal.tipo;
document.getElementById('cal_sync_direction').value = cal.sync_direction || 'bidirectional';
document.getElementById('cal_sync_interval').value = cal.sync_interval_minutes || 60;
document.getElementById('cal_is_active').checked = cal.is_active;
const cfg = cal.config || { };
document.getElementById('cal_caldav_url').value = cfg.url || '';
document.getElementById('cal_caldav_calendar_url').value = cfg.calendar_url || '';
document.getElementById('cal_caldav_username').value = cfg.username || '';
document.getElementById('cal_caldav_password').value = '';
document.getElementById('cal_caldav_password').placeholder = cfg.password ? '......' : '';
document.getElementById('cal_gc_client_id').value = cfg.client_id || '';
document.getElementById('cal_gc_client_secret').value = '';
document.getElementById('cal_gc_client_secret').placeholder = cfg.client_secret ? '......' : '';
document.getElementById('cal_gc_refresh_token').value = cfg.refresh_token || '';
document.getElementById('cal_gc_calendar_id').value = cfg.calendar_id || 'primary';
toggleCalendarioConfigFields();
$ ('#calendarioModal').modal('show');
}
function deleteCalendario(id, nome) {
if (!confirm('Eliminare la connessione " ' + nome + ' " ?')) return;
var url = ' { { route('calendario-connessioni.destroy', '__ID__') }}'.replace('__ID__', id);
fetch(url, {
method: 'POST',
headers: {
'X-CSRF-TOKEN': ' { { csrf_token() }}',
'X-HTTP-Method-Override': 'DELETE'
}
}).then(function(r) { return r.json(); }).then(function(data) {
if (data.success) {
location.reload();
} else {
alert('❌ ' + (data.message || 'Errore'));
}
}).catch(function() {
alert('❌ Errore di rete');
});
}
function testCalendario(id, btn) {
btn.disabled = true;
btn.innerHTML = '<i class= " fas fa - spinner fa - spin " ></i> Test...';
$ .ajax( {
url: ' { { route('calendario-connessioni.test', '__ID__') }}'.replace('__ID__', id),
method: 'POST',
headers: { 'X-CSRF-TOKEN': ' { { csrf_token() }}' },
timeout: 30000,
success: function(response) {
btn.disabled = false;
btn.innerHTML = '<i class= " fas fa - plug " ></i>';
alert(response.success ? '✅ ' + response.message : '❌ ' + response.message);
},
error: function(xhr) {
btn.disabled = false;
btn.innerHTML = '<i class= " fas fa - plug " ></i>';
const msg = xhr.responseJSON?.message || 'Errore di connessione';
alert('❌ ' + msg);
}
});
}
2026-05-28 09:34:28 +02:00
$ (document).ready(function() {
2026-06-02 22:07:16 +02:00
if (document.getElementById('calendarioSortable')) {
var sortableCalendario = Sortable.create(document.getElementById('calendarioSortable'), {
handle: '.handle',
animation: 150,
onEnd: function(evt) {
var order = [];
$ ('#calendarioSortable tr').each(function() {
order.push( $ (this).data('id'));
});
fetch(' { { route('calendario-connessioni.reorder') }}', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': ' { { csrf_token() }}',
'Content-Type': 'application/json',
},
body: JSON.stringify( { order: order })
});
}
});
}
2026-05-28 09:34:28 +02:00
if (document.getElementById('repoSortable')) {
var sortableRepo = Sortable.create(document.getElementById('repoSortable'), {
handle: '.handle',
animation: 150,
onEnd: function(evt) {
var order = [];
$ ('#repoSortable tr').each(function() {
order.push( $ (this).data('id'));
});
fetch(' { { route('storage-repositories.reorder') }}', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': ' { { csrf_token() }}',
'Content-Type': 'application/json',
},
body: JSON.stringify( { order: order })
});
}
});
}
2026-05-28 13:25:47 +02:00
if (newToken && newToken.refresh_token) {
// Auto-open modal after OAuth callback — preserve nome and other fields
document.getElementById('repoForm').action = ' { { route('storage-repositories.store') }}';
document.getElementById('repoMethod').value = 'POST';
document.getElementById('repoModalTitle').textContent = 'Nuovo Repository Remoto';
document.getElementById('repoForm').reset();
document.getElementById('repoId').value = '';
document.getElementById('repo_nome').value = newToken.nome || '';
document.getElementById('repo_tipo').value = 'google_drive';
document.getElementById('repo_is_active').checked = newToken.is_active !== '0';
document.getElementById('gd_client_id').value = newToken.client_id || '';
document.getElementById('gd_client_secret').value = newToken.client_secret || '';
document.getElementById('gd_refresh_token').value = newToken.refresh_token;
document.getElementById('gd_root_folder_id').value = newToken.root_folder_id || 'root';
setGdAuthStatus(true, newToken.client_id || '');
toggleRepoConfigFields();
$ ('#repoModal').modal('show');
}
2026-05-28 09:34:28 +02:00
});
2026-05-26 08:14:29 +02:00
</script>
2026-05-28 09:34:28 +02:00
{ { -- MODAL: Repository Remoto --}}
<div class= " modal fade " id= " repoModal " tabindex= " - 1 " role= " dialog " >
<div class= " modal - dialog modal - lg " role= " document " >
<div class= " modal - content " >
<div class= " modal - header " >
<h5 class= " modal - title " id= " repoModalTitle " ><i class= " fas fa - cloud mr - 2 " ></i>Nuovo Repository Remoto</h5>
<button type= " button " class= " close " data-dismiss= " modal " ><span>×</span></button>
</div>
<form id= " repoForm " method= " POST " action= " {{ route ( 'storage-repositories.store' ) }} " >
@csrf
<input type= " hidden " name= " _method " id= " repoMethod " value= " POST " >
<input type= " hidden " name= " id " id= " repoId " value= " " >
<div class= " modal - body " >
<div class= " row " >
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " repo_nome " >Nome *</label>
<input type= " text " name= " nome " id= " repo_nome " class= " form - control " placeholder= " es . Server Parrocchia " required>
</div>
</div>
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " repo_tipo " >Tipo *</label>
<select name= " tipo " id= " repo_tipo " class= " form - control " required onchange= " toggleRepoConfigFields () " >
<option value= " webdav " >WebDAV</option>
<option value= " google_drive " >Google Drive</option>
</select>
</div>
</div>
</div>
<div class= " form - group " >
<div class= " custom - control custom - switch " >
<input type= " checkbox " class= " custom - control - input " id= " repo_is_active " name= " is_active " value= " 1 " checked>
<label class= " custom - control - label " for= " repo_is_active " >Repository attivo</label>
</div>
</div>
<hr>
<h6>Configurazione</h6>
{ { -- WebDAV Fields --}}
<div id= " webdavFields " >
<div class= " row " >
<div class= " col - md - 8 " >
<div class= " form - group " >
<label for= " webdav_base_uri " >URL Base WebDAV *</label>
<input type= " url " name= " config [ base_uri ] " id= " webdav_base_uri " class= " form - control " placeholder= " es . https :// nextcloud . parrocchia . it / remote . php / dav / files / utente / " >
</div>
</div>
<div class= " col - md - 4 " >
<div class= " form - group " >
<label for= " webdav_root " >Root path</label>
<input type= " text " name= " config [ root ] " id= " webdav_root " class= " form - control " value= " / " placeholder= " / " >
<small class= " text - muted " >Percorso base nel server</small>
</div>
</div>
</div>
<div class= " row " >
<div class= " col - md - 4 " >
<div class= " form - group " >
<label for= " webdav_username " >Username</label>
<input type= " text " name= " config [ username ] " id= " webdav_username " class= " form - control " >
</div>
</div>
<div class= " col - md - 4 " >
<div class= " form - group " >
<label for= " webdav_password " >Password</label>
<input type= " password " name= " config [ password ] " id= " webdav_password " class= " form - control " >
</div>
</div>
<div class= " col - md - 4 " >
<div class= " form - group " >
<label for= " webdav_auth_type " >Auth Type</label>
<select name= " config [ auth_type ] " id= " webdav_auth_type " class= " form - control " >
<option value= " basic " >Basic</option>
<option value= " digest " >Digest</option>
<option value= " ntlm " >NTLM</option>
</select>
</div>
</div>
</div>
</div>
{ { -- Google Drive Fields --}}
<div id= " googleDriveFields " style= " display : none ; " >
<div class= " row " >
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " gd_client_id " >Client ID *</label>
2026-05-28 13:25:47 +02:00
<input type= " text " name= " config [ client_id ] " id= " gd_client_id " class= " form - control " placeholder= " Google Client ID " oninput= " updateGdAuthUrl () " >
2026-05-28 09:34:28 +02:00
</div>
</div>
<div class= " col - md - 6 " >
<div class= " form - group " >
<label for= " gd_client_secret " >Client Secret *</label>
2026-05-28 13:25:47 +02:00
<input type= " password " name= " config [ client_secret ] " id= " gd_client_secret " class= " form - control " placeholder= " Google Client Secret " oninput= " updateGdAuthUrl () " >
2026-05-28 09:34:28 +02:00
</div>
</div>
</div>
<div class= " row " >
<div class= " col - md - 6 " >
2026-05-28 13:25:47 +02:00
<input type= " hidden " name= " config [ refresh_token ] " id= " gd_refresh_token " value= " " >
<div class= " mb - 3 " >
<label class= " d - block " >Autorizzazione Google</label>
<div id= " gdAuthStatus " class= " mb - 2 " >
<span class= " text - muted " ><i class= " fas fa - circle mr - 1 " ></i> Non autorizzato</span>
</div>
<a id= " gdAuthBtn " href= " #" class="btn btn-danger btn-sm" target="_blank" onclick="return startGdAuth()">
< i class = " fas fa-google mr-1 " ></ i > Autorizza con Google
</ a >
< small class = " d-block text-muted mt-1 " >
Dopo aver cliccato , verrai reindirizzato a Google per autorizzare l 'app.
Al termine, il Refresh Token verrà salvato automaticamente.
</small>
2026-05-28 09:34:28 +02:00
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="gd_root_folder_id">Root Folder ID</label>
2026-05-28 13:25:47 +02:00
<input type="text" name="config[root_folder_id]" id="gd_root_folder_id" class="form-control" value="root" placeholder="root" oninput="updateGdAuthUrl()">
2026-05-28 09:34:28 +02:00
<small class="text-muted">ID della cartella Google Drive, default: root</small>
</div>
</div>
</div>
<div class="alert alert-info">
<i class="fas fa-info-circle mr-2"></i>
2026-05-28 13:25:47 +02:00
<strong>Prima volta?</strong> Crea il progetto in <a href="https://console.cloud.google.com/" target="_blank">Google Cloud Console</a>
→ API & Services → Credentials → Crea OAuth Client ID (Web Application).
Aggiungi <code>{{ url(' / auth / google - drive / callback ' ) }} </ code > come < strong > Authorized Redirect URI </ strong >.
2026-05-28 09:34:28 +02:00
</ div >
</ div >
</ div >
< div class = " modal-footer " >
< button type = " button " class = " btn btn-secondary " data - dismiss = " modal " > Annulla </ button >
< button type = " submit " class = " btn btn-primary " >
< i class = " fas fa-save mr-1 " ></ i > Salva Repository
</ button >
</ div >
</ form >
</ div >
</ div >
</ div >
2026-05-26 14:10:04 +02:00
@ endsection