Merge branch 'dev'

versione finale 1.2
This commit is contained in:
2026-06-06 23:20:49 +02:00
18 changed files with 72 additions and 7617 deletions
@@ -1,808 +0,0 @@
<?php $__env->startSection('title', 'Modifica Individuo'); ?>
<?php $__env->startSection('page_title', 'Modifica Individuo'); ?>
<?php $__env->startSection('content'); ?>
<form action="/individui/<?php echo e($individuo->id); ?>" method="POST" id="main-form">
<?php echo csrf_field(); ?>
<?php echo method_field('PUT'); ?>
<input type="hidden" name="individuo_id" value="<?php echo e($individuo->id); ?>">
<input type="hidden" name="_avatar_token" value="<?php echo e(csrf_token()); ?>">
<div class="row">
<div class="col-md-6">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-user mr-2"></i>Dati Anagrafici</h3>
</div>
<div class="card-body">
<div class="form-group">
<label>Codice ID</label>
<input type="text" class="form-control" value="<?php echo e($individuo->codice_id); ?>" disabled>
</div>
<div class="form-group">
<label>Cognome *</label>
<input type="text" name="cognome" class="form-control" value="<?php echo e($individuo->cognome); ?>" required>
</div>
<div class="form-group">
<label>Nome *</label>
<input type="text" name="nome" class="form-control" value="<?php echo e($individuo->nome); ?>" required>
</div>
<div class="form-group">
<label>Data di nascita</label>
<input type="date" name="data_nascita" class="form-control" value="<?php echo e($individuo->data_nascita?->format('Y-m-d')); ?>">
</div>
<div class="form-group">
<label>Genere</label>
<select name="genere" class="form-control">
<option value="">Seleziona...</option>
<option value="M" <?php echo e($individuo->genere === 'M' ? 'selected' : ''); ?>>Maschio</option>
<option value="F" <?php echo e($individuo->genere === 'F' ? 'selected' : ''); ?>>Femmina</option>
</select>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card card-secondary">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-camera mr-2"></i>Avatar</h3>
</div>
<div class="card-body text-center">
<?php if($individuo->avatar): ?>
<img src="/individui/<?php echo e($individuo->id); ?>/avatar"
alt="Avatar"
class="img-thumbnail mb-2"
style="max-width: 120px; max-height: 120px; object-fit: cover; border-radius: 50%;">
<br>
<button type="button" class="btn btn-danger btn-sm" onclick="deleteAvatar()">
<i class="fas fa-trash mr-1"></i>Rimuovi
</button>
<?php else: ?>
<div class="bg-secondary d-flex align-items-center justify-content-center mb-3"
style="width: 120px; height: 120px; margin: 0 auto; border-radius: 50%;">
<i class="fas fa-user fa-4x text-white"></i>
</div>
<?php endif; ?>
<div class="custom-file mb-2">
<input type="file" class="custom-file-input" id="avatar-input" name="avatar" accept="image/jpeg,image/png,image/gif">
<label class="custom-file-label" for="avatar-input">Scegli immagine...</label>
</div>
<button type="button" class="btn btn-primary btn-sm" onclick="uploadAvatar()">
<i class="fas fa-upload mr-1"></i>Carica Avatar
</button>
<div id="avatar-message" class="mt-2"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header"><h3 class="card-title"><i class="fas fa-map-marker-alt mr-2"></i>Residenza</h3></div>
<div class="card-body">
<div class="form-group">
<label>Indirizzo</label>
<input type="text" name="indirizzo" class="form-control" value="<?php echo e($individuo->indirizzo); ?>">
</div>
<div class="form-row">
<div class="form-group col-md-4">
<label>CAP</label>
<input type="text" name="cap" class="form-control" value="<?php echo e($individuo->cap); ?>">
</div>
<div class="form-group col-md-5">
<label>Città</label>
<input type="text" name="città" class="form-control" value="<?php echo e($individuo->città); ?>">
</div>
<div class="form-group col-md-3">
<label>Provincia</label>
<input type="text" name="sigla_provincia" class="form-control" maxlength="2" value="<?php echo e($individuo->sigla_provincia); ?>">
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header"><h3 class="card-title"><i class="fas fa-id-card mr-2"></i>Documento di identità</h3></div>
<div class="card-body">
<div class="form-group">
<label>Tipo documento</label>
<select name="tipo_documento" class="form-control">
<option value="">Seleziona...</option>
<option value="carta_identita" <?php echo e($individuo->tipo_documento === 'carta_identita' ? 'selected' : ''); ?>>Carta d'Identità</option>
<option value="patente" <?php echo e($individuo->tipo_documento === 'patente' ? 'selected' : ''); ?>>Patente</option>
</select>
</div>
<div class="form-group">
<label>Numero documento</label>
<input type="text" name="numero_documento" class="form-control" value="<?php echo e($individuo->numero_documento); ?>">
</div>
<div class="form-group">
<label>Scadenza documento</label>
<input type="date" name="scadenza_documento" class="form-control" value="<?php echo e($individuo->scadenza_documento?->format('Y-m-d')); ?>">
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header"><h3 class="card-title"><i class="fas fa-sticky-note mr-2"></i>Note</h3></div>
<div class="card-body">
<div class="form-group mb-0">
<textarea name="note" class="form-control" rows="4"><?php echo e($individuo->note); ?></textarea>
</div>
</div>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-address-book mr-2"></i>Contatti</h3>
<button type="button" class="btn btn-xs btn-success float-right" onclick="aggiungiRigaContatto()">
<i class="fas fa-plus mr-1"></i> Aggiungi
</button>
</div>
<div class="card-body p-0">
<table class="table table-bordered mb-0" id="contatti-table">
<thead class="thead-light">
<tr>
<th style="width: 20%;">Tipo</th>
<th style="width: 30%;">Valore</th>
<th style="width: 20%;">Etichetta</th>
<th style="width: 10%;">Primario</th>
<th style="width: 50px;"></th>
</tr>
</thead>
<tbody id="contatti-tbody">
<?php $__currentLoopData = $individuo->contatti; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $contatto): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td>
<select name="contatti[<?php echo e($loop->index); ?>][tipo]" class="form-control">
<option value="telefono" <?php echo e($contatto->tipo === 'telefono' ? 'selected' : ''); ?>>Telefono</option>
<option value="cellulare" <?php echo e($contatto->tipo === 'cellulare' ? 'selected' : ''); ?>>Cellulare</option>
<option value="email" <?php echo e($contatto->tipo === 'email' ? 'selected' : ''); ?>>Email</option>
<option value="fax" <?php echo e($contatto->tipo === 'fax' ? 'selected' : ''); ?>>Fax</option>
<option value="web" <?php echo e($contatto->tipo === 'web' ? 'selected' : ''); ?>>Web</option>
<option value="telegram" <?php echo e($contatto->tipo === 'telegram' ? 'selected' : ''); ?>>Telegram</option>
<option value="whatsapp" <?php echo e($contatto->tipo === 'whatsapp' ? 'selected' : ''); ?>>WhatsApp</option>
<option value="altro" <?php echo e($contatto->tipo === 'altro' ? 'selected' : ''); ?>>Altro</option>
</select>
</td>
<td><input type="text" name="contatti[<?php echo e($loop->index); ?>][valore]" class="form-control" value="<?php echo e($contatto->valore); ?>"></td>
<td><input type="text" name="contatti[<?php echo e($loop->index); ?>][etichetta]" class="form-control" value="<?php echo e($contatto->etichetta); ?>"></td>
<td class="text-center"><input type="checkbox" name="contatti[<?php echo e($loop->index); ?>][is_primary]" value="1" <?php echo e($contatto->is_primary ? 'checked' : ''); ?>></td>
<td><button type="button" class="btn btn-danger btn-xs" onclick="this.closest('tr').remove()"><i class="fas fa-trash"></i></button></td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<?php if($individuo->contatti->isEmpty()): ?>
<div id="no-contatti-msg" class="text-center text-muted py-4">
<p class="mb-0">Nessun contatto. Clicca su "Aggiungi" per aggiungerne uno.</p>
</div>
<?php endif; ?>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-folder mr-2"></i>Gruppi</h3>
<button type="button" class="btn btn-xs btn-success float-right" onclick="showGruppoForm()">
<i class="fas fa-plus mr-1"></i> Aggiungi
</button>
</div>
<div class="card-body p-0">
<?php if($individuo->gruppi->count() > 0): ?>
<table class="table table-bordered table-hover table-striped mb-0">
<thead class="thead-light">
<tr>
<th>Nome</th>
<th>Diocesi</th>
<th style="width: 130px;">Ruolo</th>
<th style="width: 110px;">Data Adesione</th>
<th style="width: 80px;">Azioni</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $individuo->gruppi; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $gruppo): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr id="gruppo-row-<?php echo e($gruppo->id); ?>">
<td>
<i class="fas fa-folder text-warning mr-1"></i>
<a href="/gruppi/<?php echo e($gruppo->id); ?>"><?php echo e($gruppo->nome); ?></a>
</td>
<td><?php echo e($gruppo->diocesi?->nome ?: '-'); ?></td>
<td>
<?php $ruoliIndividuo = $individuo->getRuoliForGruppo($gruppo->id) ?>
<?php if($ruoliIndividuo->count() > 0): ?>
<?php $__currentLoopData = $ruoliIndividuo; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $ruolo): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<span class="badge badge-info mr-1"><?php echo e($ruolo->nome); ?></span>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
<?php else: ?>
-
<?php endif; ?>
</td>
<td><?php echo e($gruppo->pivot->data_adesione ? \Carbon\Carbon::parse($gruppo->pivot->data_adesione)->format('d/m/Y') : '-'); ?></td>
<td>
<button type="button" class="btn btn-xs btn-warning" onclick="editGruppoInline(<?php echo e($gruppo->id); ?>)" title="Modifica">
<i class="fas fa-edit"></i>
</button>
<button type="button" class="btn btn-xs btn-danger" onclick="deleteGruppoFromEdit(<?php echo e($individuo->id); ?>, <?php echo e($gruppo->id); ?>)" title="Rimuovi">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
<tr id="gruppo-edit-<?php echo e($gruppo->id); ?>" style="display:none;">
<td colspan="5">
<div class="mb-0">
<div class="row">
<div class="col-md-4">
<input type="text" class="form-control form-control-sm" value="<?php echo e($gruppo->nome); ?>" disabled>
</div>
<div class="col-md-3">
<select id="edit-ruoli-<?php echo e($gruppo->id); ?>" class="form-control form-control-sm" multiple size="3">
<?php $selectedRuoliIds = $individuo->getRuoloIdsForGruppo($gruppo->id) ?>
<?php $__currentLoopData = \App\Models\Ruolo::attive(); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $ruolo): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($ruolo->id); ?>" <?php echo e(in_array($ruolo->id, $selectedRuoliIds) ? 'selected' : ''); ?>><?php echo e($ruolo->nome); ?></option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
</div>
<div class="col-md-3">
<input type="date" id="edit-data-<?php echo e($gruppo->id); ?>" class="form-control form-control-sm" value="<?php echo e($gruppo->pivot->data_adesione); ?>">
</div>
<div class="col-md-2">
<button type="button" class="btn btn-xs btn-success" onclick="submitEditGruppo(<?php echo e($gruppo->id); ?>)"><i class="fas fa-check mr-1"></i>Salva</button>
<button type="button" class="btn btn-xs btn-secondary" onclick="cancelEditGruppo(<?php echo e($gruppo->id); ?>)"><i class="fas fa-times"></i></button>
</div>
</div>
</div>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<?php else: ?>
<div class="text-center text-muted py-4">
<i class="fas fa-users fa-2x mb-2"></i>
<p class="mb-0">Nessun gruppo associato</p>
</div>
<?php endif; ?>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-file mr-2"></i>Documenti</h3>
<button type="button" class="btn btn-xs btn-success float-right" onclick="showDocumentoForm()">
<i class="fas fa-plus mr-1"></i> Carica
</button>
</div>
<div class="card-body p-0">
<div id="documento-add-form" style="display:none;" class="p-3 bg-light border-bottom">
<div class="mb-0">
<div class="row">
<div class="col-md-3">
<input type="text" id="doc-nome-file" class="form-control form-control-sm" placeholder="Nome documento">
</div>
<div class="col-md-3">
<select id="doc-tipologia" class="form-control form-control-sm">
<option value="">Tipologia...</option>
<option value="documento">Documento</option>
<option value="avatar">Avatar</option>
<option value="galleria">Galleria</option>
<option value="statuto">Statuto</option>
<option value="altro">Altro</option>
</select>
</div>
<div class="col-md-4">
<input type="file" id="doc-file" class="form-control form-control-sm">
</div>
<div class="col-md-2">
<button type="button" class="btn btn-xs btn-success" onclick="submitUploadDocumentoIndividuo()"><i class="fas fa-upload mr-1"></i>Carica</button>
<button type="button" class="btn btn-xs btn-secondary" onclick="hideDocumentoForm()"><i class="fas fa-times"></i></button>
</div>
</div>
</div>
</div>
<?php if($individuo->documenti->count() > 0): ?>
<table class="table table-bordered table-hover table-striped mb-0">
<thead class="thead-light">
<tr>
<th>Nome</th>
<th style="width: 120px;">Tipologia</th>
<th style="width: 80px;">Dimensione</th>
<th style="width: 130px;">Data Upload</th>
<th style="width: 80px;">Azioni</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $individuo->documenti; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $documento): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td>
<a href="#" onclick="event.preventDefault(); previewDocumento(<?php echo e($documento->id); ?>, '<?php echo e($documento->mime_type); ?>');">
<i class="fas fa-file text-secondary mr-1"></i>
<?php echo e($documento->nome_file); ?>
</a>
</td>
<td><?php echo e(ucfirst(str_replace('_', ' ', $documento->tipologia))); ?></td>
<td><?php echo e(number_format($documento->dimensione / 1024, 1)); ?> KB</td>
<td><?php echo e($documento->created_at->format('d/m/Y')); ?></td>
<td>
<?php if($documento->file_path): ?>
<button type="button" class="btn btn-xs btn-primary" onclick="previewDocumento(<?php echo e($documento->id); ?>, '<?php echo e($documento->mime_type); ?>')" title="Anteprima">
<i class="fas fa-eye"></i>
</button>
<?php endif; ?>
<button type="button" class="btn btn-xs btn-danger" onclick="deleteDocumentoFromEdit(<?php echo e($documento->id); ?>)" title="Elimina">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<?php else: ?>
<div class="text-center text-muted py-4">
<i class="fas fa-file fa-2x mb-2"></i>
<p class="mb-0">Nessun documento</p>
</div>
<?php endif; ?>
</div>
</div>
<div class="mt-3 mb-4">
<button type="button" class="btn btn-success btn-lg" id="save-all-btn" onclick="submitMainForm()">
<i class="fas fa-save mr-2"></i> Salva Tutte le Modifiche
</button>
<a href="/individui/<?php echo e($individuo->id); ?>" class="btn btn-secondary btn-lg ml-2">
<i class="fas fa-times mr-1"></i> Annulla
</a>
</div>
</form>
<div class="card mt-3" id="gruppo-add-card" style="display:none; background-color: #fff3cd; border-color: #ffc107;">
<div class="card-header bg-warning">
<h3 class="card-title"><i class="fas fa-folder-plus mr-2"></i>Aggiungi a Gruppo</h3>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4">
<select id="new-gruppo-id" class="form-control form-control-sm">
<option value="">Seleziona gruppo...</option>
<?php $__currentLoopData = \App\Models\Gruppo::orderBy('nome')->get(); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $g): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php if(!$individuo->gruppi->contains($g->id)): ?>
<option value="<?php echo e($g->id); ?>"><?php echo e($g->full_path); ?></option>
<?php endif; ?>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
</div>
<div class="col-md-3">
<select id="new-gruppo-ruolo" class="form-control form-control-sm" multiple size="3">
<?php $__currentLoopData = \App\Models\Ruolo::attive(); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $ruolo): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($ruolo->id); ?>"><?php echo e($ruolo->nome); ?></option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<small class="text-muted">Ctrl+click per selezionare più ruoli</small>
</div>
<div class="col-md-3">
<input type="date" id="new-gruppo-data" class="form-control form-control-sm">
</div>
<div class="col-md-2">
<button type="button" class="btn btn-success btn-sm" onclick="submitGruppoForm()">
<i class="fas fa-check mr-1"></i> Associa
</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="hideGruppoForm()">
<i class="fas fa-times"></i>
</button>
</div>
</div>
</div>
<div class="modal fade" id="previewModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document" style="max-width: 90vw;">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-file mr-2"></i><span id="previewModalTitle">Anteprima</span></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Chiudi">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body text-center p-0" style="min-height: 400px;">
<iframe id="previewFrame" src="" style="width: 100%; height: 70vh; border: none;"></iframe>
</div>
<div class="modal-footer">
<a id="previewDownloadBtn" href="#" class="btn btn-primary" download>
<i class="fas fa-download mr-1"></i> Scarica
</a>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Chiudi</button>
</div>
</div>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php $__env->startSection('scripts'); ?>
<script>
document.addEventListener('DOMContentLoaded', function() {
console.log('All form fields:');
var form = document.getElementById('main-form');
var fields = form.querySelectorAll('input, textarea, select');
fields.forEach(function(f) {
console.log(f.name + ' [' + f.type + ']: value="' + f.value.substring(0,30) + '" disabled=' + f.disabled);
});
// Debug note field specifically
var noteField = form.querySelector('[name="note"]');
console.log('Note field found:', !!noteField);
if (noteField) {
console.log('Note value:', noteField.value);
}
var saveBtn = document.getElementById('save-btn');
if (saveBtn) {
saveBtn.addEventListener('click', function() {
console.log('=== SAVE CLICKED ===');
var note = form.querySelector('[name="note"]');
console.log('Note at save time:', note ? note.value : 'NOT FOUND');
});
}
form.addEventListener('submit', function(e) {
console.log('=== FORM SUBMIT ===');
var note = form.querySelector('[name="note"]');
console.log('Note at submit:', note ? note.value : 'NOT FOUND');
var contattiFields = form.querySelectorAll('[name^="contatti"]');
console.log('Contatti fields count:', contattiFields.length);
contattiFields.forEach(function(f, i) {
console.log('Contatto field ' + i + ':', f.name, '=', f.value);
});
var formData = new FormData(form);
console.log('FormData contatti:', formData.getAll('contatti'));
});
});
</script>
<script>
function submitMainForm() {
var form = document.getElementById('main-form');
console.log('=== DEBUG SUBMIT ===');
var contattiFields = form.querySelectorAll('[name^="contatti"]');
console.log('Contatti fields found:', contattiFields.length);
contattiFields.forEach(function(f, i) {
console.log('Field ' + i + ': name=' + f.name + ', value=' + f.value);
});
form.action = '/individui/<?php echo e($individuo->id); ?>';
var methodInput = form.querySelector('input[name="_method"]');
if (!methodInput) {
var m = document.createElement('input');
m.type = 'hidden';
m.name = '_method';
m.value = 'PUT';
form.appendChild(m);
}
var csrfInput = form.querySelector('input[name="_token"]');
if (!csrfInput) {
var c = document.createElement('input');
c.type = 'hidden';
c.name = '_token';
c.value = '<?php echo e(csrf_token()); ?>';
form.appendChild(c);
}
var formData = new FormData(form);
console.log('FormData contatti keys:');
for (var pair of formData.entries()) {
if (pair[0].startsWith('contatti')) {
console.log(' ' + pair[0] + ' = ' + pair[1]);
}
}
form.submit();
}
let contattoIndex = <?php echo e($individuo->contatti->count()); ?>;
function aggiungiRigaContatto() {
const tbody = document.getElementById('contatti-tbody');
const noMsg = document.getElementById('no-contatti-msg');
if (noMsg) noMsg.style.display = 'none';
const row = document.createElement('tr');
row.innerHTML = `
<td>
<select name="contatti[${contattoIndex}][tipo]" class="form-control">
<option value="">Seleziona...</option>
<option value="telefono">Telefono</option>
<option value="cellulare">Cellulare</option>
<option value="email">Email</option>
<option value="fax">Fax</option>
<option value="web">Web</option>
<option value="telegram">Telegram</option>
<option value="whatsapp">WhatsApp</option>
<option value="altro">Altro</option>
</select>
</td>
<td><input type="text" name="contatti[${contattoIndex}][valore]" class="form-control" placeholder="Valore"></td>
<td><input type="text" name="contatti[${contattoIndex}][etichetta]" class="form-control" placeholder="Etichetta"></td>
<td class="text-center"><input type="checkbox" name="contatti[${contattoIndex}][is_primary]" value="1"></td>
<td>
<button type="button" class="btn btn-success btn-xs" title="Salva" onclick="submitMainForm()">
<i class="fas fa-save"></i>
</button>
<button type="button" class="btn btn-danger btn-xs" title="Elimina" onclick="this.closest('tr').remove()">
<i class="fas fa-trash"></i>
</button>
</td>
`;
tbody.appendChild(row);
contattoIndex++;
}
function showGruppoForm() {
var card = document.getElementById('gruppo-add-card');
if (card) {
card.style.display = 'block';
card.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
function hideGruppoForm() {
var card = document.getElementById('gruppo-add-card');
if (card) {
card.style.display = 'none';
}
}
function submitGruppoForm() {
var gruppoId = document.getElementById('new-gruppo-id').value;
var ruoloSelect = document.getElementById('new-gruppo-ruolo');
var dataAdesione = document.getElementById('new-gruppo-data').value;
if (!gruppoId) {
alert('Seleziona un gruppo');
return;
}
var formData = new URLSearchParams();
formData.append('gruppo_id', gruppoId);
var selectedRuoli = Array.from(ruoloSelect.selectedOptions).map(opt => opt.value).filter(v => v);
selectedRuoli.forEach(function(ruoloId) {
formData.append('ruolo_ids[]', ruoloId);
});
formData.append('data_adesione', dataAdesione);
fetch('/individui/<?php echo e($individuo->id); ?>/gruppi', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>',
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData
})
.then(response => {
if (!response.ok) {
return response.text().then(text => { throw new Error(text); });
}
return response.json();
})
.then(data => {
if (data.success) {
hideGruppoForm();
window.location.reload();
} else {
alert(data.error || 'Errore');
}
})
.catch(error => {
alert('Errore: ' + error.message);
});
}
function editGruppoInline(id) {
document.getElementById('gruppo-row-' + id).style.display = 'none';
document.getElementById('gruppo-edit-' + id).style.display = 'table-row';
}
function cancelEditGruppo(id) {
document.getElementById('gruppo-row-' + id).style.display = 'table-row';
document.getElementById('gruppo-edit-' + id).style.display = 'none';
}
function showDocumentoForm() {
document.getElementById('documento-add-form').style.display = 'block';
}
function hideDocumentoForm() {
document.getElementById('documento-add-form').style.display = 'none';
}
function previewDocumento(id, mimeType) {
var previewUrl = '/documenti/' + id + '/preview';
var downloadUrl = '/documenti/' + id + '/download';
document.getElementById('previewFrame').src = previewUrl;
document.getElementById('previewDownloadBtn').href = downloadUrl;
document.getElementById('previewModalTitle').textContent = 'Anteprima';
if (mimeType && mimeType.startsWith('image/')) {
document.getElementById('previewDownloadBtn').style.display = 'inline-block';
} else {
document.getElementById('previewDownloadBtn').style.display = 'none';
}
$('#previewModal').modal('show');
}
document.getElementById('avatar-input').addEventListener('change', function(e) {
var fileName = e.target.files[0]?.name || 'Scegli file...';
e.target.nextElementSibling.textContent = fileName;
});
function uploadAvatar() {
var input = document.getElementById('avatar-input');
if (!input.files[0]) {
document.getElementById('avatar-message').innerHTML = '<span class="text-danger">Seleziona un\'immagine</span>';
return;
}
var formData = new FormData();
formData.append('avatar', input.files[0]);
formData.append('_token', '<?php echo e(csrf_token()); ?>');
document.getElementById('avatar-message').innerHTML = '<span class="text-info"><i class="fas fa-spinner fa-spin"></i> Caricamento...</span>';
fetch('/individui/<?php echo e($individuo->id); ?>/avatar', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('avatar-message').innerHTML = '<span class="text-success">Avatar caricato!</span>';
setTimeout(function() { window.location.reload(); }, 500);
} else {
document.getElementById('avatar-message').innerHTML = '<span class="text-danger">' + (data.message || 'Errore') + '</span>';
}
})
.catch(error => {
document.getElementById('avatar-message').innerHTML = '<span class="text-danger">Errore: ' + error + '</span>';
});
}
function deleteAvatar() {
if (!confirm('Rimuovere l\'avatar?')) return;
fetch('/individui/<?php echo e($individuo->id); ?>/avatar', {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>',
'Accept': 'application/json'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
window.location.reload();
} else {
alert(data.message || 'Errore');
}
})
.catch(error => {
alert('Errore: ' + error);
});
}
function deleteGruppoFromEdit(individuoId, gruppoId) {
if (!confirm('Rimuovere da questo gruppo?')) return;
fetch('/individui/' + individuoId + '/gruppi/' + gruppoId, {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>',
'Accept': 'application/json'
}
})
.then(response => {
if (!response.ok) return response.text().then(text => { throw new Error(text); });
return response.json();
})
.then(data => {
if (data.success) window.location.reload();
else alert(data.error || 'Errore');
})
.catch(error => alert('Errore: ' + error.message));
}
function submitEditGruppo(gruppoId) {
var ruoloSelect = document.getElementById('edit-ruoli-' + gruppoId);
var dataInput = document.getElementById('edit-data-' + gruppoId);
var formData = new URLSearchParams();
var selectedRuoli = Array.from(ruoloSelect.selectedOptions).map(opt => opt.value).filter(v => v);
selectedRuoli.forEach(function(ruoloId) {
formData.append('ruolo_ids[]', ruoloId);
});
formData.append('data_adesione', dataInput ? dataInput.value : '');
fetch('/individui/<?php echo e($individuo->id); ?>/gruppi/' + gruppoId, {
method: 'PUT',
headers: {
'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>',
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData.toString()
})
.then(response => {
if (!response.ok) return response.text().then(text => { throw new Error(text); });
return response.json();
})
.then(data => {
if (data.success) window.location.reload();
else alert(data.error || 'Errore');
})
.catch(error => alert('Errore: ' + error.message));
}
function submitUploadDocumentoIndividuo() {
var nomeFile = document.getElementById('doc-nome-file');
var tipologia = document.getElementById('doc-tipologia');
var fileInput = document.getElementById('doc-file');
if (!nomeFile.value || !tipologia.value || !fileInput.files[0]) {
alert('Compila tutti i campi');
return;
}
var formData = new FormData();
formData.append('_token', '<?php echo e(csrf_token()); ?>');
formData.append('_redirect', '<?php echo e(url()->current()); ?>');
formData.append('visibilita', 'individuo');
formData.append('visibilita_target_id', '<?php echo e($individuo->id); ?>');
formData.append('visibilita_target_type', 'App\\Models\\Individuo');
formData.append('nome_file', nomeFile.value);
formData.append('tipologia', tipologia.value);
formData.append('file', fileInput.files[0]);
document.getElementById('documento-add-form').querySelector('.btn-success').disabled = true;
fetch('/documenti', {
method: 'POST',
body: formData,
headers: { 'Accept': 'application/json' }
})
.then(function() { window.location.reload(); })
.catch(function() { window.location.reload(); });
}
function deleteDocumentoFromEdit(documentoId) {
if (!confirm('Eliminare questo documento?')) return;
var formData = new FormData();
formData.append('_token', '<?php echo e(csrf_token()); ?>');
formData.append('_method', 'DELETE');
formData.append('_redirect', '<?php echo e(url()->current()); ?>');
fetch('/documenti/' + documentoId, {
method: 'POST',
body: formData,
headers: { 'Accept': 'application/json' }
})
.then(function() { window.location.reload(); })
.catch(function() { window.location.reload(); });
}
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.adminlte', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/glastree/resources/views/individui/edit.blade.php ENDPATH**/ ?>
@@ -1,5 +0,0 @@
<?php $__env->startSection('title', __('Not Found')); ?>
<?php $__env->startSection('code', '404'); ?>
<?php $__env->startSection('message', __('Not Found')); ?>
<?php echo $__env->make('errors::minimal', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/glastree/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/views/404.blade.php ENDPATH**/ ?>
@@ -139,9 +139,30 @@ $currentFolder = $folders->firstWhere('type', $folder);
</table>
</div>
</div>
<div class="card-footer">
<?php echo e($messages->withQueryString()->links('vendor.pagination.simple-bootstrap-4')); ?>
<div class="card-footer d-flex justify-content-between align-items-center">
<div>
<form method="GET" class="form-inline" id="perPageForm">
<label class="mr-2 small">Righe per pagina:</label>
<select name="perPage" class="form-control form-control-sm" onchange="this.form.submit()" style="width: auto;">
<?php $__currentLoopData = [10, 20, 25, 50, 100]; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $p): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($p); ?>" <?php echo e((int) request('perPage', 20) === $p ? 'selected' : ''); ?>><?php echo e($p); ?></option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<?php $__currentLoopData = request()->except(['perPage', 'page']); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $key => $value): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php if(is_array($value)): ?>
<?php $__currentLoopData = $value; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $v): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<input type="hidden" name="<?php echo e($key); ?>[]" value="<?php echo e($v); ?>">
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
<?php else: ?>
<input type="hidden" name="<?php echo e($key); ?>" value="<?php echo e($value); ?>">
<?php endif; ?>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</form>
</div>
<div>
<?php echo e($messages->links('vendor.pagination.simple-bootstrap-4')); ?>
</div>
</div>
</div>
<?php $__env->stopSection(); ?>
@@ -1,123 +0,0 @@
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php echo $__env->yieldContent('title', 'Admin'); ?> - Glastree</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/admin-lte@3.2/dist/css/adminlte.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<?php echo $__env->yieldContent('styles'); ?>
</head>
<body class="hold-transition sidebar-mini layout-fixed">
<div class="wrapper">
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a>
</li>
</ul>
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="<?php echo e(route('dashboard')); ?>">
<i class="fas fa-home"></i> Torna al Sito
</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link" data-toggle="dropdown" href="#">
<i class="fas fa-user"></i> <?php echo e(Auth::user()->name); ?>
</a>
<div class="dropdown-menu dropdown-menu-right">
<form method="POST" action="<?php echo e(route('logout')); ?>">
<?php echo csrf_field(); ?>
<button type="submit" class="dropdown-item">
<i class="fas fa-sign-out-alt mr-2"></i> Esci
</button>
</form>
</div>
</li>
</ul>
</nav>
<aside class="main-sidebar sidebar-dark-primary elevation-4">
<a href="<?php echo e(route('dashboard')); ?>" class="brand-link">
<i class="fas fa-shield-alt brand-image ml-3 mr-2"></i>
<span class="brand-text font-weight-light">Admin</span>
</a>
<div class="sidebar">
<nav class="mt-2">
<ul class="nav nav-pills nav-sidebar flex-column">
<li class="nav-item">
<a href="/admin/utenti" class="nav-link <?php echo e(request()->is('admin/utenti*') ? 'active' : ''); ?>">
<i class="nav-icon fas fa-users"></i>
<p>Utenti</p>
</a>
</li>
<li class="nav-item">
<a href="/admin/ruoli" class="nav-link <?php echo e(request()->is('admin/ruoli*') ? 'active' : ''); ?>">
<i class="nav-icon fas fa-user-tag"></i>
<p>Ruoli</p>
</a>
</li>
<li class="nav-item">
<a href="/admin/backup" class="nav-link <?php echo e(request()->is('admin/backup*') ? 'active' : ''); ?>">
<i class="nav-icon fas fa-hdd"></i>
<p>Backup</p>
</a>
</li>
<li class="nav-item">
<a href="/admin/activity-logs" class="nav-link <?php echo e(request()->is('admin/activity-logs*') ? 'active' : ''); ?>">
<i class="nav-icon fas fa-history"></i>
<p>Log Attività</p>
</a>
</li>
</ul>
</nav>
</div>
</aside>
<div class="content-wrapper">
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0"><?php echo $__env->yieldContent('page_title', 'Admin'); ?></h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="<?php echo e(route('dashboard')); ?>">Dashboard</a></li>
<?php echo $__env->yieldContent('breadcrumbs'); ?>
</ol>
</div>
</div>
</div>
</div>
<div class="content">
<div class="container-fluid">
<?php if(session('success')): ?>
<div class="alert alert-success"><?php echo e(session('success')); ?></div>
<?php endif; ?>
<?php if(session('error')): ?>
<div class="alert alert-danger"><?php echo e(session('error')); ?></div>
<?php endif; ?>
<?php echo $__env->yieldContent('content'); ?>
</div>
</div>
</div>
<footer class="main-footer">
<strong><?php echo e(\App\Models\AppSetting::getFooterText()); ?></strong>
<?php if(\App\Models\AppSetting::shouldShowVersion() && \App\Models\AppSetting::getAppVersion()): ?>
<span class="ml-2">v<?php echo e(\App\Models\AppSetting::getAppVersion()); ?></span>
<?php endif; ?>
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/admin-lte@3.2/dist/js/adminlte.min.js"></script>
<?php echo $__env->yieldContent('scripts'); ?>
</body>
</html><?php /**PATH /var/www/html/glastree/resources/views/admin/layout.blade.php ENDPATH**/ ?>
@@ -1,78 +0,0 @@
<?php $__env->startSection('title', 'Importa Individui'); ?>
<?php $__env->startSection('page_title', 'Importa Individui da CSV'); ?>
<?php $__env->startSection('content'); ?>
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-upload mr-2"></i>Carica file CSV</h3>
</div>
<div class="card-body">
<form action="<?php echo e(route('individui.import.store')); ?>" method="POST" enctype="multipart/form-data">
<?php echo csrf_field(); ?>
<div class="form-group">
<label for="file">Seleziona file CSV *</label>
<input type="file" name="file" id="file" class="form-control" accept=".csv,.txt" required>
<small class="form-text text-muted">
Il file deve essere in formato CSV con separatore virgola.
</small>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-upload mr-1"></i> Importa
</button>
<a href="<?php echo e(route('individui.index')); ?>" class="btn btn-secondary ml-2">
Annulla
</a>
</form>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header bg-info">
<h3 class="card-title text-white"><i class="fas fa-download mr-2"></i>Template</h3>
</div>
<div class="card-body">
<p>Scarica il template CSV per l'importazione:</p>
<a href="<?php echo e(route('individui.template')); ?>" class="btn btn-success btn-block">
<i class="fas fa-file-csv mr-1"></i> Scarica Template
</a>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-info-circle mr-2"></i>Formato CSV</h3>
</div>
<div class="card-body">
<h6>Campi obbligatori:</h6>
<ul>
<li><code>cognome</code></li>
<li><code>nome</code></li>
</ul>
<h6>Campi opzionali:</h6>
<ul>
<li><code>data_nascita</code> (formato YYYY-MM-DD)</li>
<li><code>indirizzo</code></li>
<li><code>cap</code></li>
<li><code>città</code></li>
<li><code>sigla_provincia</code> (2 lettere)</li>
<li><code>genere</code> (M o F)</li>
<li><code>tipo_documento</code> (carta_identita, patente)</li>
<li><code>numero_documento</code></li>
<li><code>scadenza_documento</code> (YYYY-MM-DD)</li>
<li><code>note</code></li>
</ul>
<h6>Contatti (fino a 2):</h6>
<ul>
<li><code>contatto_1_tipo</code> (email, telefono, cellulare)</li>
<li><code>contatto_1_valore</code></li>
<li><code>contatto_1_etichetta</code> (personale, lavoro)</li>
<li><code>contatto_2_*</code> (secondo contatto)</li>
</ul>
</div>
</div>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.adminlte', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/glastree/resources/views/individui/import.blade.php ENDPATH**/ ?>
@@ -1,248 +0,0 @@
<?php $appName = \App\Models\AppSetting::getAppName() ?? 'Glastree'; ?>
<?php $__env->startSection('title', 'Backup - ' . $appName); ?>
<?php $__env->startSection('page_title', 'Backup e Migrazione'); ?>
<?php $__env->startSection('breadcrumbs'); ?>
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item"><a href="/admin/utenti">Admin</a></li>
<li class="breadcrumb-item active">Backup</li>
<?php $__env->stopSection(); ?>
<?php $__env->startSection('content'); ?>
<div class="row">
<div class="col-md-8">
<div class="card card-outline card-primary">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-hdd mr-2"></i>Backup Disponibili</h3>
<div class="card-tools">
<form method="POST" action="<?php echo e(route('admin.backup.run')); ?>" style="display:inline">
<?php echo csrf_field(); ?>
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-play mr-1"></i> Esegui Backup Ora
</button>
</form>
</div>
</div>
<div class="card-body p-0">
<?php if(count($backups) > 0): ?>
<div class="table-responsive">
<table class="table table-hover table-striped mb-0">
<thead>
<tr>
<th>File</th>
<th>Data</th>
<th>Dimensione</th>
<th>Contenuto</th>
<th class="text-center">Azioni</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $backups; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $backup): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><code><?php echo e($backup['filename']); ?></code></td>
<td><?php echo e(date('d/m/Y H:i', $backup['last_modified'])); ?></td>
<td><?php echo e($backup['size_formatted']); ?></td>
<td>
<?php if($backup['manifest']): ?>
<span class="badge badge-info" title="PHP <?php echo e($backup['manifest']['php_version'] ?? '?'); ?>, Laravel <?php echo e($backup['manifest']['laravel_version'] ?? '?'); ?>">
<i class="fas fa-database mr-1"></i>DB
</span>
<?php if(isset($backup['manifest']['db_name'])): ?>
<small class="text-muted"><?php echo e($backup['manifest']['db_name']); ?></small>
<?php endif; ?>
<?php else: ?>
<span class="badge badge-secondary">N/A</span>
<?php endif; ?>
</td>
<td class="text-center">
<a href="<?php echo e(route('admin.backup.download', $backup['filename'])); ?>" class="btn btn-success btn-sm" title="Scarica">
<i class="fas fa-download"></i>
</a>
<form method="POST" action="<?php echo e(route('admin.backup.destroy', $backup['filename'])); ?>" style="display:inline" onsubmit="return confirm('Eliminare definitivamente questo backup?')">
<?php echo csrf_field(); ?>
<?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-danger btn-sm" title="Elimina">
<i class="fas fa-trash"></i>
</button>
</form>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
</div>
<?php else: ?>
<div class="text-center py-5">
<i class="fas fa-hdd fa-3x text-muted mb-3"></i>
<p class="text-muted mb-0">Nessun backup disponibile.</p>
<p class="text-muted">Clicca "Esegui Backup Ora" per creare il primo backup.</p>
</div>
<?php endif; ?>
</div>
</div>
<div class="card card-outline card-info">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-info-circle mr-2"></i>Cosa Include il Backup</h3>
</div>
<div class="card-body p-0">
<table class="table table-bordered mb-0">
<thead>
<tr>
<th>Componente</th>
<th>Incluso</th>
<th>Dettagli</th>
</tr>
</thead>
<tbody>
<tr>
<td><i class="fas fa-database text-primary mr-2"></i> Database (MySQL)</td>
<td><span class="badge badge-success">Sempre</span></td>
<td>Struttura, dati, stored procedure, eventi, trigger</td>
</tr>
<tr>
<td><i class="fas fa-file text-warning mr-2"></i> File caricati</td>
<td>
<?php if($config['backup_include_files']): ?>
<span class="badge badge-success">Sì</span>
<?php else: ?>
<span class="badge badge-secondary">No</span>
<?php endif; ?>
</td>
<td>Documenti, avatar, gallerie — dalla cartella storage</td>
</tr>
<tr>
<td><i class="fas fa-cog text-secondary mr-2"></i> Configurazione (.env)</td>
<td>
<?php if($config['backup_include_env']): ?>
<span class="badge badge-success">Sì</span>
<?php else: ?>
<span class="badge badge-secondary">No</span>
<?php endif; ?>
</td>
<td>APP_KEY, DB credentials, SMTP, OAuth token</td>
</tr>
<tr>
<td><i class="fas fa-tag text-info mr-2"></i> Metadati</td>
<td><span class="badge badge-success">Sempre</span></td>
<td>Manifest JSON con versione app, PHP, Laravel</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card card-outline card-secondary">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-sliders-h mr-2"></i>Configurazione Backup</h3>
</div>
<form method="POST" action="<?php echo e(route('admin.backup.config')); ?>">
<?php echo csrf_field(); ?>
<div class="card-body">
<div class="form-group">
<label for="backup_path">Percorso backup</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><code>storage/app/</code></span>
</div>
<input type="text" name="backup_path" id="backup_path" class="form-control" value="<?php echo e($config['backup_path']); ?>">
</div>
<small class="text-muted">Cartella dove salvare i backup (relativa a storage/app/)</small>
</div>
<div class="form-group">
<label for="backup_retention_days">Ritenzione (giorni)</label>
<input type="number" name="backup_retention_days" id="backup_retention_days" class="form-control" value="<?php echo e($config['backup_retention_days']); ?>" min="1" max="365">
<small class="text-muted">I backup più vecchi vengono eliminati automaticamente</small>
</div>
<div class="form-group mb-0">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="backup_include_files" name="backup_include_files" value="1" <?php echo e($config['backup_include_files'] ? 'checked' : ''); ?>>
<label class="custom-control-label" for="backup_include_files">Includi file caricati</label>
</div>
<div class="custom-control custom-switch mt-2">
<input type="checkbox" class="custom-control-input" id="backup_include_env" name="backup_include_env" value="1" <?php echo e($config['backup_include_env'] ? 'checked' : ''); ?>>
<label class="custom-control-label" for="backup_include_env">Includi .env (configurazione)</label>
</div>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-secondary btn-block">
<i class="fas fa-save mr-1"></i> Salva Configurazione
</button>
</div>
</form>
</div>
<div class="card card-outline card-warning">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-clock mr-2"></i>Backup Automatico</h3>
<div class="card-tools">
<?php $autoEnabled = \App\Models\AppSetting::getSetting('backup_auto_enabled', false) ?>
<form method="POST" action="<?php echo e(route('admin.backup.toggle-auto')); ?>" style="display:inline">
<?php echo csrf_field(); ?>
<button type="submit" class="btn btn-sm <?php echo e($autoEnabled ? 'btn-success' : 'btn-secondary'); ?>">
<i class="fas <?php echo e($autoEnabled ? 'fa-check-circle' : 'fa-times-circle'); ?> mr-1"></i>
<?php echo e($autoEnabled ? 'Attivo' : 'Disattivo'); ?>
</button>
</form>
</div>
</div>
<form method="POST" action="<?php echo e(route('admin.backup.save-auto')); ?>">
<?php echo csrf_field(); ?>
<div class="card-body">
<div class="form-group">
<label for="backup_auto_frequency">Frequenza</label>
<select name="backup_auto_frequency" id="backup_auto_frequency" class="form-control">
<option value="daily" <?php echo e(\App\Models\AppSetting::getSetting('backup_auto_frequency', 'daily') === 'daily' ? 'selected' : ''); ?>>Giornaliero</option>
<option value="weekly" <?php echo e(\App\Models\AppSetting::getSetting('backup_auto_frequency', 'daily') === 'weekly' ? 'selected' : ''); ?>>Settimanale</option>
<option value="monthly" <?php echo e(\App\Models\AppSetting::getSetting('backup_auto_frequency', 'daily') === 'monthly' ? 'selected' : ''); ?>>Mensile</option>
</select>
</div>
<div class="form-group mb-0">
<label for="backup_auto_hour">Ora di esecuzione</label>
<select name="backup_auto_hour" id="backup_auto_hour" class="form-control">
<?php for($h = 0; $h <= 23; $h++): ?>
<option value="<?php echo e($h); ?>" <?php echo e(\App\Models\AppSetting::getSetting('backup_auto_hour', 3) == $h ? 'selected' : ''); ?>><?php echo e(sprintf('%02d:00', $h)); ?></option>
<?php endfor; ?>
</select>
<small class="text-muted">Ora del giorno (formato 24h). Consigliato: 03:00 (notte)</small>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-warning btn-block">
<i class="fas fa-save mr-1"></i> Salva Automatico
</button>
</div>
</form>
</div>
<div class="card card-outline card-danger">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-truck mr-2"></i>Migrazione Server</h3>
</div>
<div class="card-body">
<p class="text-muted">Scarica il backup, poi esegui lo script di setup sul nuovo server per una migrazione completa.</p>
<a href="<?php echo e(route('help')); ?>#help-backup" class="btn btn-danger btn-block" target="_blank">
<i class="fas fa-book mr-1"></i> Guida alla Migrazione
</a>
</div>
</div>
</div>
</div>
<div class="alert alert-info">
<i class="fas fa-info-circle mr-2"></i>
<strong>Importante:</strong> Per il backup automatico, assicurati che il cron di Laravel sia configurato sul server:
<code class="ml-2">* * * * * cd <?php echo e(base_path()); ?> && php artisan schedule:run >> /dev/null 2>&1</code>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('admin.layout', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/glastree/resources/views/admin/backup/index.blade.php ENDPATH**/ ?>
@@ -1,5 +0,0 @@
<?php $__env->startSection('title', __('Page Expired')); ?>
<?php $__env->startSection('code', '419'); ?>
<?php $__env->startSection('message', __('Page Expired')); ?>
<?php echo $__env->make('errors::minimal', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/glastree/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/views/419.blade.php ENDPATH**/ ?>
File diff suppressed because it is too large Load Diff
@@ -1,723 +0,0 @@
<?php $__env->startSection('title', 'Impostazioni Email'); ?>
<?php $__env->startSection('page_title', 'Configurazione Email'); ?>
<?php $__env->startSection('breadcrumbs'); ?>
<li class="breadcrumb-item"><a href="<?php echo e(route('dashboard')); ?>">Dashboard</a></li>
<li class="breadcrumb-item"><a href="/impostazioni">Impostazioni</a></li>
<li class="breadcrumb-item active">Email Settings</li>
<?php $__env->stopSection(); ?>
<?php $__env->startSection('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="#imap" class="list-group-item list-group-item-action active" data-toggle="tab">
<i class="nav-icon fas fa-server"></i> Server IMAP
</a>
<a href="#smtp" class="list-group-item list-group-item-action" data-toggle="tab">
<i class="nav-icon fas fa-paper-plane"></i> Server SMTP (Invio)
</a>
<a href="#account" class="list-group-item list-group-item-action" data-toggle="tab">
<i class="nav-icon fas fa-user"></i> Account
</a>
<a href="#sync" class="list-group-item list-group-item-action" data-toggle="tab">
<i class="nav-icon fas fa-sync"></i> Sincronizzazione
</a>
<a href="#signature" class="list-group-item list-group-item-action" data-toggle="tab">
<i class="nav-icon fas fa-signature"></i> Firma
</a>
<a href="#mittenti" class="list-group-item list-group-item-action" data-toggle="tab">
<i class="nav-icon fas fa-user-plus"></i> Mittenti Aggiuntivi
</a>
</div>
</div>
</div>
<div class="col-md-9">
<form method="POST" action="<?php echo e(route('impostazioni.email.save')); ?>">
<?php echo csrf_field(); ?>
<input type="hidden" name="id" value="<?php echo e($settings->id ?? 1); ?>">
<div class="tab-content">
<div class="tab-pane active" id="imap">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">Configurazione Server IMAP</h3>
</div>
<div class="card-body">
<?php if(session('success')): ?>
<div class="alert alert-success"><?php echo e(session('success')); ?></div>
<?php endif; ?>
<?php if(session('error')): ?>
<div class="alert alert-danger"><?php echo e(session('error')); ?></div>
<?php endif; ?>
<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="<?php echo e($settings->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="<?php echo e($settings->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" <?php echo e(($settings->imap_encryption ?? 'ssl') == 'ssl' ? 'selected' : ''); ?>>SSL</option>
<option value="tls" <?php echo e(($settings->imap_encryption ?? '') == 'tls' ? 'selected' : ''); ?>>TLS</option>
<option value="none" <?php echo e(($settings->imap_encryption ?? '') == 'none' ? 'selected' : ''); ?>>Nessuna</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="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="<?php echo e($settings->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="<?php echo e($settings->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" <?php echo e(($settings->smtp_encryption ?? 'tls') == 'tls' ? 'selected' : ''); ?>>TLS</option>
<option value="ssl" <?php echo e(($settings->smtp_encryption ?? '') == 'ssl' ? 'selected' : ''); ?>>SSL</option>
<option value="none" <?php echo e(($settings->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="<?php echo e($settings->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="<?php echo e($settings->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="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="<?php echo e($settings->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="<?php echo e($settings->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="<?php echo e($settings->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="<?php echo e($settings->reply_to ?? ''); ?>">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="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" <?php echo e(($settings->sync_interval_minutes ?? 5) == 1 ? 'selected' : ''); ?>>1 minuto</option>
<option value="5" <?php echo e(($settings->sync_interval_minutes ?? 5) == 5 ? 'selected' : ''); ?>>5 minuti</option>
<option value="15" <?php echo e(($settings->sync_interval_minutes ?? 5) == 15 ? 'selected' : ''); ?>>15 minuti</option>
<option value="30" <?php echo e(($settings->sync_interval_minutes ?? 5) == 30 ? 'selected' : ''); ?>>30 minuti</option>
<option value="60" <?php echo e(($settings->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">
<?php if($settings->last_sync_at): ?>
<span class="badge badge-success">
<i class="fas fa-check-circle"></i> Ultimo sync: <?php echo e($settings->last_sync_at->format('d/m/Y H:i')); ?>
</span>
<?php else: ?>
<span class="badge badge-secondary">
<i class="fas fa-clock"></i> Mai sincronizzato
</span>
<?php endif; ?>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="is_active"
name="is_active" value="1" <?php echo e(($settings->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="signature">
<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">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="signature_enabled"
name="signature_enabled" value="1" <?php echo e(($settings->signature_enabled ?? true) ? 'checked' : ''); ?>>
<label class="custom-control-label" for="signature_enabled">Attiva firma automatica</label>
</div>
<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: 200px;"></div>
<input type="hidden" name="signature" id="signature_input" value="<?php echo e($settings->signature ?? ''); ?>">
<small class="text-muted">Usa il riquadro sopra per comporre la tua firma. HTML supportato.</small>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="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">
<?php if(session('success')): ?>
<div class="alert alert-success"><?php echo e(session('success')); ?></div>
<?php endif; ?>
<?php if(session('error')): ?>
<div class="alert alert-danger"><?php echo e(session('error')); ?></div>
<?php endif; ?>
<?php 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>
<?php $__currentLoopData = $senderAccounts; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $sender): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><strong><?php echo e($sender->email_address); ?></strong></td>
<td><?php echo e($sender->email_name ?: '-'); ?></td>
<td><small><?php echo e($sender->smtp_host ?: '-'); ?>:<?php echo e($sender->smtp_port ?: '-'); ?></small></td>
<td><small class="text-muted"><?php echo e($sender->reply_to ?: '-'); ?></small></td>
<td><small class="text-muted"><?php echo e($sender->verify_email ?: '-'); ?></small></td>
<td>
<?php if($sender->is_active): ?>
<span class="badge badge-success">Attivo</span>
<?php else: ?>
<span class="badge badge-secondary">Disattivo</span>
<?php endif; ?>
</td>
<td>
<button type="button" class="btn btn-xs btn-info" onclick="editSender(<?php echo e($sender->id); ?>)" title="Modifica">
<i class="fas fa-edit"></i>
</button>
<button type="button" class="btn btn-xs btn-success" onclick="testSenderSmtp(<?php echo e($sender->id); ?>)" title="Test SMTP">
<i class="fas fa-paper-plane"></i>
</button>
<form action="<?php echo e(route('impostazioni.sender.destroy', $sender->id)); ?>" method="POST" class="d-inline" onsubmit="return confirm('Eliminare il mittente <?php echo e($sender->email_address); ?>?')">
<?php echo csrf_field(); ?> <?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-xs btn-danger" title="Elimina">
<i class="fas fa-trash"></i>
</button>
</form>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
</div>
<?php 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>
<?php endif; ?>
</div>
</div>
<?php 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>
<?php endif; ?>
</div>
</div>
<div class="card-footer d-flex flex-wrap align-items-center gap-2">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save mr-1"></i> Salva Impostazioni
</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="<?php echo e(route('impostazioni.email.sync')); ?>" class="btn btn-warning ml-2">
<i class="fas fa-sync mr-1"></i> Sincronizza Ora
</a>
<form action="<?php echo e(route('impostazioni.email.destroy')); ?>" method="POST" class="ml-auto" onsubmit="return confirm('Eliminare definitivamente la configurazione email? Tutti i dati di connessione verranno rimossi.')">
<?php echo csrf_field(); ?> <?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-danger">
<i class="fas fa-trash mr-1"></i> Elimina Configurazione
</button>
</form>
</div>
</form>
</div>
</div>
<?php $__env->stopSection(); ?>
<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="<?php echo e(route('impostazioni.sender.store')); ?>">
<?php echo csrf_field(); ?>
<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>
<?php $__env->startSection('scripts'); ?>
<script>
let senderAccounts = <?php echo json_encode($senderAccounts, 15, 512) ?>;
function resetSenderForm() {
document.getElementById('senderForm').action = '<?php echo e(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 = '<?php echo e(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 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: '<?php echo e(route('impostazioni.sender.test', '__ID__')); ?>'.replace('__ID__', id),
method: 'POST',
headers: { 'X-CSRF-TOKEN': '<?php echo e(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);
}
});
}
function testConnection() {
$.ajax({
url: '<?php echo e(route('impostazioni.email.test')); ?>',
method: 'POST',
headers: { 'X-CSRF-TOKEN': '<?php echo e(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: '<?php echo e(route('impostazioni.email.testSmtp')); ?>',
method: 'POST',
headers: { 'X-CSRF-TOKEN': '<?php echo e(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);
}
}
});
}
var quillEditorInstance = null;
function createEditor() {
var container = document.querySelector('#signature-editor');
if (!container || quillEditorInstance) return;
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;
}
});
quillEditorInstance = quill;
}
function initSignatureEditor() {
if (quillEditorInstance) return;
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) {
if ($(e.target).attr('href') === '#signature') {
setTimeout(initSignatureEditor, 100);
}
});
if ($('#signature').hasClass('active')) {
initSignatureEditor();
}
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.adminlte', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/glastree/resources/views/admin/email-settings/index.blade.php ENDPATH**/ ?>
@@ -1,70 +0,0 @@
<?php $__env->startSection('title', 'Gestione Ruoli'); ?>
<?php $__env->startSection('page_title', 'Gestione Ruoli'); ?>
<?php $__env->startSection('breadcrumbs'); ?>
<li class="breadcrumb-item active">Admin</li>
<li class="breadcrumb-item active">Ruoli</li>
<?php $__env->stopSection(); ?>
<?php $__env->startSection('content'); ?>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Ruoli Predefiniti</h3>
<a href="/admin/ruoli/create" class="btn btn-success btn-sm float-right">
<i class="fas fa-plus"></i> Nuovo Ruolo
</a>
</div>
<div class="card-body">
<table class="table table-bordered">
<thead>
<tr>
<th>Nome</th>
<th>Descrizione</th>
<th>Utenti</th>
<th>Permessi</th>
<th style="width: 100px;">Azioni</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $ruoli; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $ruolo): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td><strong><?php echo e($ruolo->name); ?></strong></td>
<td><?php echo e($ruolo->description); ?></td>
<td><span class="badge badge-info"><?php echo e($ruolo->users_count); ?></span></td>
<td>
<?php $__currentLoopData = $ruolo->permissions; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $module => $level): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<span class="badge badge-<?php echo e($level == 2 ? 'success' : ($level == 1 ? 'info' : 'secondary')); ?>">
<?php echo e(ucfirst($module)); ?>: <?php echo e($level == 2 ? 'Full' : ($level == 1 ? 'Read' : 'None')); ?>
</span>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</td>
<td>
<a href="<?php echo e(url('/admin/ruoli/' . $ruolo->id . '/edit')); ?>" class="btn btn-xs btn-warning">
<i class="fas fa-edit"></i>
</a>
<?php if($ruolo->users_count == 0): ?>
<form method="POST" action="<?php echo e(url('/admin/ruoli/' . $ruolo->id)); ?>" style="display: inline;">
<?php echo csrf_field(); ?> <?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-xs btn-danger" onclick="return confirm('Eliminare questo ruolo?')">
<i class="fas fa-trash"></i>
</button>
</form>
<?php else: ?>
<button type="button" class="btn btn-xs btn-secondary" disabled title="Utenti associati: <?php echo e($ruolo->users_count); ?>">
<i class="fas fa-trash"></i>
</button>
<?php endif; ?>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('admin.layout', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/glastree/resources/views/admin/ruoli/index.blade.php ENDPATH**/ ?>
File diff suppressed because one or more lines are too long
@@ -1,962 +0,0 @@
<?php $appName = \App\Models\AppSetting::getAppName() ?? 'Glastree'; ?>
<?php $__env->startSection('title', 'Guida - ' . $appName); ?>
<?php $__env->startSection('page_title', 'Guida alla Configurazione'); ?>
<?php $__env->startSection('breadcrumbs'); ?>
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item active">Guida</li>
<?php $__env->stopSection(); ?>
<?php $__env->startSection('content'); ?>
<div class="row">
<div class="col-md-3">
<div class="card card-outline card-primary">
<div class="card-header">
<h3 class="card-title">Argomenti</h3>
</div>
<div class="card-body p-0">
<ul class="nav nav-pills flex-column" id="helpTabs">
<li class="nav-item">
<a class="nav-link active" href="#help-webdav" data-toggle="tab">
<i class="fas fa-cloud mr-2"></i> WebDAV / Nextcloud
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#help-googledrive" data-toggle="tab">
<i class="fab fa-google-drive mr-2"></i> Google Drive
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#help-tipologie" data-toggle="tab">
<i class="fas fa-tags mr-2"></i> Tipologie e Dati
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#help-email" data-toggle="tab">
<i class="fas fa-envelope mr-2"></i> Email / SMTP
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#help-installazione" data-toggle="tab">
<i class="fas fa-terminal mr-2"></i> Installazione
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#help-backup" data-toggle="tab">
<i class="fas fa-hdd mr-2"></i> Backup e Migrazione
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#help-docker" data-toggle="tab">
<i class="fab fa-docker mr-2"></i> Docker
</a>
</li>
</ul>
</div>
<div class="card-footer">
<a href="<?php echo e(route('help.pdf.download')); ?>" class="btn btn-primary btn-block">
<i class="fas fa-file-pdf mr-2"></i> Scarica Guida PDF
</a>
</div>
</div>
</div>
<div class="col-md-9">
<div class="tab-content">
<div class="tab-pane active" id="help-webdav">
<div class="card card-outline card-info">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-cloud mr-2"></i> WebDAV / Nextcloud</h3>
</div>
<div class="card-body">
<h5>Cos'è</h5>
<p>WebDAV è un protocollo che permette di accedere a file su server remoti. Nextcloud lo utilizza per la sincronizzazione dei file.</p>
<h5>Configurazione</h5>
<p>Vai in <strong>Impostazioni → Repository</strong> e crea un nuovo repository di tipo WebDAV.</p>
<div class="callout callout-info">
<h6>Campi obbligatori</h6>
<dl class="row mb-0">
<dt class="col-sm-3">Nome</dt>
<dd class="col-sm-9">Un nome descrittivo (es. "Nextcloud Lavoro")</dd>
<dt class="col-sm-3">Base URI</dt>
<dd class="col-sm-9">L'URL del tuo server WebDAV.
<br><em>Nextcloud:</em> <code>https://tuodominio.it/remote.php/dav/files/utente/</code>
<br><em>Altri:</em> <code>https://server.webdav.it/</code></dd>
<dt class="col-sm-3">Root</dt>
<dd class="col-sm-9">Percorso base all'interno del server (es. <code>/Documenti/</code>). Lascia <code>/</code> per usare la root.</dd>
<dt class="col-sm-3">Username</dt>
<dd class="col-sm-9">Il tuo nome utente</dd>
<dt class="col-sm-3">Password</dt>
<dd class="col-sm-9">La password dell'account</dd>
<dt class="col-sm-3">Auth Type</dt>
<dd class="col-sm-9"><code>Basic</code> per la maggior parte dei server (Nextcloud, ownCloud).</dd>
</dl>
</div>
<h5 class="mt-4">⚠️ Nome utente con @ (chiocciola)</h5>
<p>Se il tuo nome utente contiene il carattere <code>@</code> (es. <code>mario.rossi@azienda.com</code>), segui queste regole:</p>
<ul>
<li><strong>Nel campo "Base URI":</strong> l'indirizzo email deve essere <strong>URL-encoded</strong>:
<br><code>https://server.it/remote.php/dav/files/mario.rossi%40azienda.com/</code>
<br><small>(il carattere <code>@</code> diventa <code>%40</code>)</small></li>
<li><strong>Nel campo "Username":</strong> inserisci l'indirizzo email <strong>normale</strong> con la <code>@</code> vera.</li>
</ul>
<div class="alert alert-info">
<i class="fas fa-info-circle"></i>
Il sistema gestisce automaticamente la differenza tra l'URI (che richiede <code>%40</code>) e l'autenticazione (che usa la <code>@</code> reale).
</div>
<h5 class="mt-4">Test connessione</h5>
<p>Dopo aver salvato, usa il pulsante <span class="badge badge-success"><i class="fas fa-plug"></i> Test</span> nella tabella dei repository per verificare che la connessione funzioni.</p>
<h5 class="mt-4">Importare file</h5>
<p>Apri la sezione <strong>Documenti</strong>, clicca sul pulsante del repository nella toolbar per sfogliare i file remoti, poi clicca <span class="badge badge-success"><i class="fas fa-save"></i> Salva tra i documenti</span> su un file per importarlo come documento locale.</p>
</div>
</div>
</div>
<div class="tab-pane" id="help-googledrive">
<div class="card card-outline card-danger">
<div class="card-header">
<h3 class="card-title"><i class="fab fa-google-drive mr-2"></i> Google Drive</h3>
</div>
<div class="card-body">
<h5>Cos'è</h5>
<p>Integrazione con Google Drive per sfogliare e importare file direttamente dal tuo spazio Google Drive.</p>
<h5>Requisiti</h5>
<ol>
<li>Un account Google / Google Workspace</li>
<li>Un progetto sulla <strong>Google Cloud Console</strong> con l'API Google Drive abilitata</li>
<li>Credenziali OAuth 2.0 (Client ID e Client Secret)</li>
</ol>
<h5>Passo 1: Creare il progetto Google Cloud</h5>
<ol>
<li>Vai su <a href="https://console.developers.google.com/" target="_blank">Google Cloud Console</a></li>
<li>Crea un nuovo progetto o selezionane uno esistente</li>
<li>Vai a <strong>API e servizi → Libreria</strong></li>
<li>Cerca "<strong>Google Drive API</strong>" e <strong>abilitala</strong></li>
<li>Vai a <strong>API e servizi → Credenziali</strong></li>
<li>Clicca "<strong>Crea credenziali → ID client OAuth</strong>"</li>
<li>Tipo applicazione: "<strong>Applicazione Web</strong>"</li>
<li><strong>URI di reindirizzamento autorizzato:</strong> aggiungi <code><?php echo e(url('/auth/google-drive/callback')); ?></code></li>
<li>Completa la creazione e <strong>copia Client ID e Client Secret</strong></li>
</ol>
<h5>Passo 2: Configurazione nell'app</h5>
<ol>
<li>Vai in <strong>Impostazioni → Repository</strong></li>
<li>Clicca "<strong>Nuovo Repository</strong>" e seleziona tipo <strong>Google Drive</strong></li>
<li>Inserisci un nome descrittivo (es. "Drive Lavoro")</li>
<li>Incolla <strong>Client ID</strong> e <strong>Client Secret</strong></li>
<li><strong>Folder ID (opzionale):</strong> se vuoi limitare l'accesso a una cartella specifica, inserisci il suo ID (lo trovi nell'URL quando apri la cartella in Google Drive: <code>https://drive.google.com/drive/folders/<strong>ID_QUI</strong></code>)</li>
<li>Clicca "<strong>Autorizza Google Drive</strong>" — verrai reindirizzato a Google per concedere i permessi</li>
<li>Dopo l'autorizzazione, il refresh token verrà salvato automaticamente</li>
</ol>
<h5>⚠️ Google Drive API non abilitata</h5>
<p>Se vedi l'errore <em>"Google Drive API non abilitata"</em> nel test connessione, significa che l'API Drive non è stata attivata nel tuo progetto Google Cloud.</p>
<div class="callout callout-danger">
<h6>Soluzione</h6>
<p>Vai su <a href="https://console.developers.google.com/apis/api/drive.googleapis.com/overview" target="_blank">
https://console.developers.google.com/apis/api/drive.googleapis.com/overview
</a></p>
<p>Seleziona il progetto corretto dall'header in alto, clicca <strong>"Enable"</strong> e attendi qualche minuto prima di riprovare.</p>
</div>
<h5>Importare file</h5>
<p>Stessa procedura di WebDAV: apri <strong>Documenti</strong>, clicca sul repository Drive, sfoglia i file e usa <span class="badge badge-success"><i class="fas fa-save"></i> Salva tra i documenti</span>.</p>
<h5 class="mt-4">⚠️ File Google (Documenti, Fogli, Presentazioni)</h5>
<p>I file creati con Google Workspace (Documenti Google, Fogli Google, Presentazioni Google, Disegni Google) non possono essere scaricati direttamente perché non hanno un formato binario nativo.</p>
<p>Il sistema li converte automaticamente in formato Office Open XML durante l'import:</p>
<table class="table table-sm table-bordered">
<thead><tr><th>File Google</th><th>Formato convertito</th></tr></thead>
<tbody>
<tr><td>Documento Google</td><td><code>.docx</code> (Word)</td></tr>
<tr><td>Foglio Google</td><td><code>.xlsx</code> (Excel)</td></tr>
<tr><td>Presentazione Google</td><td><code>.pptx</code> (PowerPoint)</td></tr>
<tr><td>Disegno Google</td><td><code>.png</code> (Immagine)</td></tr>
<tr><td>Altri (Moduli, Script)</td><td><code>.pdf</code> (PDF)</td></tr>
</tbody>
</table>
<div class="alert alert-info">
<i class="fas fa-info-circle"></i>
Il nome del file viene automaticamente esteso con l'estensione corretta (es. "Relazione" → "Relazione.docx").
</div>
</div>
</div>
</div>
<div class="tab-pane" id="help-tipologie">
<div class="card card-outline card-success">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-tags mr-2"></i> Tipologie e Gestione Dati</h3>
</div>
<div class="card-body">
<h5>Tipologie Documenti</h5>
<p>Le tipologie classificano i documenti (avatar, galleria, documento, statuto, altro).</p>
<p>Si gestiscono in <strong>Impostazioni → Tipologie Documenti</strong>. Puoi aggiungere, rinominare, riordinare ed eliminare tipologie (tranne quelle con documenti associati).</p>
<h5>Tipologie Individui</h5>
<p>Classificano gli individui (es. socio, volontario, dipendente). Si gestiscono in <strong>Impostazioni → Tipologie</strong>.</p>
<h5>Tipologie Eventi</h5>
<p>Classificano gli eventi (es. riunione, assemblea, formazione). Si gestiscono in <strong>Impostazioni → Tipologie Eventi</strong>.</p>
<h5>Ruoli Individui</h5>
<p>Definiscono il ruolo o la carica di un individuo (es. presidente, segretario, tesoriere). Si gestiscono in <strong>Impostazioni → Ruoli</strong>.</p>
<h5>Visibilità Documenti</h5>
<p>Ogni documento può avere diversi livelli di visibilità:</p>
<ul>
<li><strong>Pubblico</strong> — visibile a tutti gli utenti</li>
<li><strong>Individuo</strong> — visibile solo a uno specifico individuo</li>
<li><strong>Gruppo</strong> — visibile solo ai membri di un gruppo</li>
<li><strong>Evento</strong> — visibile solo ai partecipanti di un evento</li>
<li><strong>Mailing</strong> — visibile solo ai membri di una mailing list</li>
</ul>
</div>
</div>
</div>
<div class="tab-pane" id="help-email">
<div class="card card-outline card-warning">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-envelope mr-2"></i> Email / SMTP</h3>
</div>
<div class="card-body">
<h5>Configurazione Email</h5>
<p>Vai in <strong>Impostazioni → Email</strong> per configurare la posta elettronica.</p>
<h5>Server IMAP (Ricezione)</h5>
<p>Usato per ricevere e leggere le email direttamente nell'app.</p>
<div class="callout callout-info">
<h6>Campi consigliati per provider comuni</h6>
<table class="table table-sm table-bordered">
<thead><tr><th>Provider</th><th>Host</th><th>Porta</th><th>Crittografia</th></tr></thead>
<tbody>
<tr><td>Gmail</td><td><code>imap.gmail.com</code></td><td><code>993</code></td><td>SSL</td></tr>
<tr><td>Outlook/Office 365</td><td><code>outlook.office365.com</code></td><td><code>993</code></td><td>SSL</td></tr>
<tr><td>Libero</td><td><code>imapmail.libero.it</code></td><td><code>993</code></td><td>SSL</td></tr>
<tr><td>Aruba</td><td><code>imap.aruba.it</code></td><td><code>993</code></td><td>SSL</td></tr>
</tbody>
</table>
</div>
<h5>Server SMTP (Invio)</h5>
<p>Usato per inviare email dall'app. Supporta account multipli (mittenti).</p>
<div class="callout callout-info">
<h6>Campi consigliati per provider comuni</h6>
<table class="table table-sm table-bordered">
<thead><tr><th>Provider</th><th>Host</th><th>Porta</th><th>Crittografia</th></tr></thead>
<tbody>
<tr><td>Gmail</td><td><code>smtp.gmail.com</code></td><td><code>587</code></td><td>TLS</td></tr>
<tr><td>Outlook/Office 365</td><td><code>smtp.office365.com</code></td><td><code>587</code></td><td>TLS</td></tr>
<tr><td>Libero</td><td><code>smtp.libero.it</code></td><td><code>465</code></td><td>SSL</td></tr>
<tr><td>Aruba</td><td><code>smtp.aruba.it</code></td><td><code>465</code></td><td>SSL</td></tr>
</tbody>
</table>
</div>
<h5>Gmail / Google Workspace</h5>
<div class="alert alert-warning">
<i class="fas fa-exclamation-triangle"></i>
Gmail richiede una <strong>Password per l'app</strong> (non la password normale) se usi la verifica in due passaggi. Puoi generarla su
<a href="https://myaccount.google.com/apppasswords" target="_blank">https://myaccount.google.com/apppasswords</a>.
</div>
<h5>Mailing</h5>
<p>Le <strong>Mailing List</strong> permettono di inviare email a gruppi predefiniti di destinatari.</p>
<ul>
<li>Crea una mailing list in <strong>Mailing List → Nuova</strong></li>
<li>Puoi popolare la lista da individui, gruppi o manualmente</li>
<li>Invia email alla lista da <strong>Email → Nuova Email</strong>, selezionando la mailing list come destinatario</li>
</ul>
<h5>Test connessione</h5>
<p>Dopo aver configurato i server, usa il pulsante <span class="badge badge-success"><i class="fas fa-vial"></i> Test Connessione</span> per verificare che IMAP e SMTP funzionino correttamente.</p>
</div>
</div>
</div>
<div class="tab-pane" id="help-backup">
<div class="card card-outline card-danger">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-hdd mr-2"></i> Backup e Migrazione Server</h3>
</div>
<div class="card-body">
<h5>Cos'è</h5>
<p>Il sistema di backup crea un archivio ZIP contenente tutto il necessario per ripristinare l'applicazione su un nuovo server. Include database, file caricati e configurazione.</p>
<h5>Cosa include il backup</h5>
<table class="table table-sm table-bordered">
<thead><tr><th>Componente</th><th>Incluso</th><th>Dettagli</th></tr></thead>
<tbody>
<tr><td>Database (MySQL)</td><td><span class="badge badge-success">Sempre</span></td><td>Struttura, dati, stored procedure, eventi, trigger</td></tr>
<tr><td>File caricati</td><td><span class="badge badge-success">Opzionale</span></td><td>Documenti, avatar, gallerie</td></tr>
<tr><td>Configurazione .env</td><td><span class="badge badge-success">Opzionale</span></td><td>APP_KEY, credenziali DB, SMTP, token OAuth</td></tr>
<tr><td>Metadati</td><td><span class="badge badge-success">Sempre</span></td><td>Versione app, PHP, Laravel</td></tr>
</tbody>
</table>
<h5 class="mt-4">Come eseguire un backup</h5>
<div class="row">
<div class="col-md-6">
<div class="callout callout-info">
<h6>Via Interfaccia Web</h6>
<ol class="mb-0">
<li>Vai su <strong>Admin → Backup</strong></li>
<li>Verifica le impostazioni (includi files/.env)</li>
<li>Clicca <span class="badge badge-primary"><i class="fas fa-play"></i> Esegui Backup Ora</span></li>
<li>Scarica il file ZIP generato</li>
</ol>
</div>
</div>
<div class="col-md-6">
<div class="callout callout-success">
<h6>Via Comando</h6>
<pre class="mb-0"><code>php artisan backup:run</code></pre>
<p class="mb-0 mt-2 small">Il file viene creato in <code>storage/app/backups/</code></p>
</div>
</div>
</div>
<h5 class="mt-4">Backup automatico</h5>
<p>Puoi abilitare il backup automatico dalla pagina <strong>Admin → Backup</strong>:</p>
<ul>
<li><strong>Frequenza:</strong> giornaliero, settimanale o mensile</li>
<li><strong>Ora:</strong> consigliata 03:00 (notte)</li>
<li><strong>Requisito:</strong> il cron di Laravel deve essere configurato sul server</li>
</ul>
<div class="alert alert-warning">
<i class="fas fa-clock mr-2"></i>
Per il backup automatico, aggiungi questo cron:
<pre class="mt-2 mb-0"><code>* * * * * cd <?php echo e(base_path()); ?> && php artisan schedule:run >> /dev/null 2>&1</code></pre>
</div>
<hr class="my-4">
<h4><i class="fas fa-truck mr-2"></i> Procedura di Migrazione Completa</h4>
<p>Segui questa procedura per migrare l'applicazione su un nuovo server LAMP (Linux, Apache, MySQL, PHP).</p>
<div class="alert alert-danger">
<i class="fas fa-exclamation-triangle mr-2"></i>
<strong>ATTENZIONE: APP_KEY</strong>
<p class="mb-0 mt-2">L'APP_KEY cripta i dati sensibili (password email SMTP, token OAuth Google Drive, ecc.).</p>
<ul class="mt-2">
<li><strong>Se hai il .env originale dal backup:</strong> NON rigenerare APP_KEY — mantieni i dati criptati accessibili.</li>
<li><strong>Se hai perso il .env:</strong> DEVI rigenerare APP_KEY, ma perderai l'accesso ai dati criptati esistenti. Dovrai riconfigurare SMTP e OAuth.</li>
</ul>
</div>
<h5 class="mt-4">Passo 1: Preparazione del server</h5>
<pre><code>sudo apt update && sudo apt upgrade -y</code></pre>
<h5 class="mt-4">Passo 2: Installa LAMP + PHP 8.4</h5>
<pre><code>sudo apt install -y apache2 mariadb-server php8.4 php8.4-cli \
php8.4-mysql php8.4-xml php8.4-mbstring php8.4-curl \
php8.4-zip php8.4-bcmath php8.4-gd php8.4-intl \
composer git unzip
sudo a2enmod rewrite</code></pre>
<h5 class="mt-4">Passo 3: Ottieni l'applicazione</h5>
<div class="callout callout-info py-2">
<i class="fas fa-info-circle"></i>
Puoi clonare il repository con git oppure estrarre il file ZIP ricevuto nella cartella <code>/var/www/glastree</code>.
</div>
<pre><code>cd /var/www
# Opzione A — Git clone
git clone &lt;URL_REPOSITORY&gt; glastree
# Opzione B — ZIP (se non hai git)
# unzip /percorso/del/glastree.zip -d glastree
cd glastree
composer install --no-dev --optimize-autoloader
npm ci && npm run build</code></pre>
<h5 class="mt-4">Passo 4: Carica il backup</h5>
<p>Copia il file <code>backup.zip</code> sul nuovo server e estrailo:</p>
<pre><code>mkdir -p /tmp/restore
unzip backup.zip -d /tmp/restore/
ls -la /tmp/restore/
# Dovresti vedere: database.sql .env files/ manifest.json</code></pre>
<h5 class="mt-4">Passo 5: Crea database e importa</h5>
<pre><code>sudo mysql -u root &lt;&lt;EOF
CREATE DATABASE glastree CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'glastree'@'localhost' IDENTIFIED BY 'ScegliPasswordFortep4ss!';
GRANT ALL ON glastree.* TO 'glastree'@'localhost';
FLUSH PRIVILEGES;
EOF
mysql -u glastree -p glastree &lt; /tmp/restore/database.sql</code></pre>
<h5 class="mt-4">Passo 6: Configura .env</h5>
<pre><code>cp /tmp/restore/.env .env
# Modifica se necessario:
# APP_URL=https://nuovo-dominio.it
# DB_HOST=localhost
# DB_DATABASE=glastree
# DB_USERNAME=glastree
# DB_PASSWORD=ScegliPasswordFortep4ss!
# DECIDI SULL'APP_KEY (leggi avviso sopra!)
# php artisan key:generate ← SOLO se non hai il .env originale</code></pre>
<h5 class="mt-4">Passo 7: Ripristina file e permessi</h5>
<pre><code>cp -r /tmp/restore/files/* storage/app/documenti/
sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R 755 storage bootstrap/cache
php artisan storage:link</code></pre>
<h5 class="mt-4">Passo 8: Cache</h5>
<pre><code>php artisan optimize:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache</code></pre>
<h5 class="mt-4">Passo 9: Configura Apache</h5>
<pre><code>sudo tee /etc/apache2/sites-available/glastree.conf &lt;&lt;APACHE
&lt;VirtualHost *:80&gt;
ServerName glastree.esempio.it
DocumentRoot /var/www/glastree/public
&lt;Directory /var/www/glastree/public&gt;
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
&lt;/Directory&gt;
ErrorLog \${APACHE_LOG_DIR}/glastree_error.log
CustomLog \${APACHE_LOG_DIR}/glastree_access.log combined
&lt;/VirtualHost&gt;
APACHE
sudo a2dissite 000-default.conf
sudo a2ensite glastree.conf
sudo systemctl reload apache2</code></pre>
<h5 class="mt-4">Passo 10: SSL Let's Encrypt</h5>
<pre><code>sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d glastree.esempio.it</code></pre>
<h5 class="mt-4">Passo 11: Cron per backup automatico</h5>
<pre><code>sudo crontab -u www-data -e
# Inserisci:
* * * * * cd /var/www/glastree && php artisan schedule:run >> /dev/null 2>&1</code></pre>
<h5 class="mt-4">Passo 12: Verifica finale</h5>
<ol>
<li>Apri https://glastree.esempio.it nel browser</li>
<li>Fai login con le credenziali esistenti</li>
<li>Verifica: Dashboard, Documenti, Impostazioni, Email</li>
<li>Se hai rigenerato APP_KEY: riconfigura SMTP e OAuth Google Drive</li>
</ol>
<hr class="my-4">
<h5>Comandi Artisan</h5>
<p>Per installazione e ripristino usa i comandi Artisan da terminale. Vedi la sezione <strong>Installazione</strong> per la guida completa.</p>
</div>
</div>
</div>
<div class="tab-pane" id="help-docker">
<div class="card card-outline card-primary">
<div class="card-header">
<h3 class="card-title"><i class="fab fa-docker mr-2"></i> Docker</h3>
</div>
<div class="card-body">
<h5>Creare un'immagine Docker con dati di base</h5>
<p>Puoi creare un'immagine Docker pronta all'uso che include l'applicazione e i dati di base (tipologie documenti, tipologie eventi, ruoli). Scegli la configurazione in base alle tue esigenze:</p>
<div class="callout callout-info">
<i class="fas fa-info-circle"></i>
<strong>Ottenere il codice:</strong> puoi clonare il repository con <code>git clone &lt;URL&gt; glastree</code> oppure, se non hai git, estrarre il file ZIP ricevuto con <code>unzip glastree.zip -d glastree</code> e posizionarti nella cartella <code>glastree</code> prima di procedere.
</div>
<div class="row mb-4">
<div class="col-md-6">
<div class="callout callout-info">
<h6><i class="fas fa-database"></i> SQLite (Leggero)</h6>
<p class="mb-0 small">Database embedded, nessun servizio aggiuntivo. Ideale per demo, test, sviluppo locale o ambienti con poca concorrenza.</p>
</div>
</div>
<div class="col-md-6">
<div class="callout callout-success">
<h6><i class="fas fa-server"></i> MySQL (Standard)</h6>
<p class="mb-0 small">Database separato in un container MySQL. Configurazione standard, ideale per produzione, staging e ambienti con piu utenti.</p>
</div>
</div>
</div>
<h5 class="mt-4">1. Dockerfile (comune a entrambe le modalita)</h5>
<p>Crea un file <code>Dockerfile</code> nella root del progetto:</p>
<pre><code>FROM php:8.4-apache
# Abilita mod_rewrite
RUN docker-php-ext-enable opcache \
&& a2enmod rewrite
# Installa estensioni PHP (sia SQLite che MySQL)
RUN docker-php-ext-install pdo_mysql pdo_sqlite bcmath gd zip
# Installa Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# Configura DocumentRoot per Laravel
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \
&& sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
# Copia l'applicazione
COPY . /var/www/html/
# Installa dipendenze e compila asset
RUN composer install --no-dev --optimize-autoloader \
&& mkdir -p storage/app/public \
&& mkdir -p storage/framework/cache/data \
&& mkdir -p storage/framework/sessions \
&& mkdir -p storage/framework/views \
&& mkdir -p storage/logs \
&& mkdir -p bootstrap/cache \
&& chown -R www-data:www-data storage bootstrap/cache
# Entrypoint per inizializzazione
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["apache2-foreground"]</code></pre>
<h5 class="mt-4">2. Entrypoint Script (comune)</h5>
<p>Crea <code>docker-entrypoint.sh</code>. Lo script rileva automaticamente la configurazione in base alle variabili d'ambiente:</p>
<pre><code>#!/bin/bash
set -e
# Se .env non esiste, lo genera dalle variabili d'ambiente
if [ ! -f .env ]; then
cp .env.example .env
if [ "$DB_CONNECTION" = "mysql" ]; then
# Configura MySQL
sed -i "s/DB_CONNECTION=mysql/DB_CONNECTION=mysql/" .env
sed -i "s/DB_HOST=.*/DB_HOST=${DB_HOST:-mysql}/" .env
sed -i "s/DB_PORT=.*/DB_PORT=${DB_PORT:-3306}/" .env
sed -i "s/DB_DATABASE=.*/DB_DATABASE=${DB_DATABASE:-glastree}/" .env
sed -i "s/DB_USERNAME=.*/DB_USERNAME=${DB_USERNAME:-glastree}/" .env
sed -i "s/DB_PASSWORD=.*/DB_PASSWORD=${DB_PASSWORD:-secret}/" .env
# Attende che MySQL sia pronto
echo "Attendo MySQL..."
until php -r "new PDO('mysql:host=${DB_HOST:-mysql};dbname=${DB_DATABASE:-glastree}', '${DB_USERNAME:-glastree}', '${DB_PASSWORD:-secret}');" 2>/dev/null; do
sleep 2
done
echo "MySQL pronto."
else
# Configura SQLite
sed -i 's/DB_CONNECTION=mysql/DB_CONNECTION=sqlite/' .env
sed -i 's/DB_HOST=.*//' .env
sed -i 's/DB_PORT=.*//' .env
sed -i 's/DB_DATABASE=.*/DB_DATABASE=\/var\/www\/html\/database\/database.sqlite/' .env
sed -i 's/DB_USERNAME=.*//' .env
sed -i 's/DB_PASSWORD=.*//' .env
touch database/database.sqlite
chmod 664 database/database.sqlite
fi
# Genera APP_KEY
php artisan key:generate --force
fi
# Esegui migration e seed se il database e vuoto
if [ ! -f .db_initialized ]; then
php artisan migrate --force
php artisan db:seed --force
touch .db_initialized
fi
# Configura storage link
php artisan storage:link --force 2>/dev/null || true
exec "$@"</code></pre>
<pre><code>chmod +x docker-entrypoint.sh</code></pre>
<h5 class="mt-4">3. Seed Base Dati (comune)</h5>
<p>Per includere tipologie documenti, tipologie eventi e ruoli, crea un seeder dedicato:</p>
<pre><code>php artisan make:seeder DockerBaseDataSeeder</code></pre>
<p>Contenuto di <code>database/seeders/DockerBaseDataSeeder.php</code>:</p>
<pre><code>&lt;?php
declare(strict_types=1);
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class DockerBaseDataSeeder extends Seeder
{
public function run(): void
{
// Tipologie Documenti
$tipologieDoc = ['documento', 'avatar', 'galleria', 'statuto', 'programma', 'locandina', 'altro'];
foreach ($tipologieDoc as $ord => $nome) {
DB::table('tipologie_documenti')->updateOrInsert(
['nome' => $nome],
['descrizione' => ucfirst($nome), 'ordine' => $ord + 1, 'attiva' => true]
);
}
// Tipologie Eventi
$tipologieEventi = [
['nome' => 'catechesi', 'descrizione' => 'Catechesi'],
['nome' => 'liturgia', 'descrizione' => 'Liturgia'],
['nome' => 'animazione', 'descrizione' => 'Animazione'],
['nome' => 'formazione', 'descrizione' => 'Formazione'],
['nome' => 'incontro', 'descrizione' => 'Incontro'],
['nome' => 'riunione', 'descrizione' => 'Riunione'],
['nome' => 'festa', 'descrizione' => 'Festa'],
['nome' => 'altro', 'descrizione' => 'Altro'],
];
foreach ($tipologieEventi as $ord => $t) {
DB::table('tipologie_eventi')->updateOrInsert(
['nome' => $t['nome']],
['descrizione' => $t['descrizione'], 'ordine' => $ord + 1, 'attiva' => true]
);
}
// Ruoli
$ruoli = ['presidente', 'vicepresidente', 'segretario', 'tesoriere', 'consigliere', 'volontario', 'socio', 'altro'];
foreach ($ruoli as $ord => $nome) {
DB::table('ruoli')->updateOrInsert(
['nome' => $nome],
['descrizione' => ucfirst($nome), 'ordine' => $ord + 1, 'attiva' => true]
);
}
}
}</code></pre>
<p>Registralo in <code>database/seeders/DatabaseSeeder.php</code>:</p>
<pre><code>$this->call([
// ... altri seeder ...
DockerBaseDataSeeder::class,
]);</code></pre>
<h5 class="mt-4">4. Docker Compose</h5>
<h6 class="text-info"><i class="fas fa-database mr-1"></i> Opzione A — SQLite (leggero)</h6>
<pre><code>services:
glastree:
build: .
ports:
- "8080:80"
volumes:
- glastree_storage:/var/www/html/storage
- glastree_db:/var/www/html/database
environment:
- APP_ENV=production
- APP_DEBUG=false
- APP_URL=http://localhost:8080
- DB_CONNECTION=sqlite
volumes:
glastree_storage:
glastree_db:</code></pre>
<h6 class="mt-3 text-success"><i class="fas fa-server mr-1"></i> Opzione B — MySQL (standard)</h6>
<pre><code>services:
glastree:
build: .
ports:
- "8080:80"
volumes:
- glastree_storage:/var/www/html/storage
depends_on:
mysql:
condition: service_healthy
environment:
- APP_ENV=production
- APP_DEBUG=false
- APP_URL=http://localhost:8080
- DB_CONNECTION=mysql
- DB_HOST=mysql
- DB_PORT=3306
- DB_DATABASE=glastree
- DB_USERNAME=glastree
- DB_PASSWORD=secret
mysql:
image: mysql:8.0
volumes:
- mysql_data:/var/lib/mysql
environment:
- MYSQL_DATABASE=glastree
- MYSQL_USER=glastree
- MYSQL_PASSWORD=secret
- MYSQL_ROOT_PASSWORD=root_secret
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 3s
retries: 10
volumes:
glastree_storage:
mysql_data:</code></pre>
<h5 class="mt-4">5. Build e avvio</h5>
<p>Assicurati di essere nella cartella del progetto (ottenuta via <code>git clone</code> o estraendo il ZIP), poi:</p>
<pre><code># Costruisci l'immagine (comune)
docker build -t glastree:latest .
# Avvia con SQLite
docker compose -f docker-compose.yml up -d
# Oppure avvia con MySQL
# docker compose -f docker-compose.mysql.yml up -d
# Apri nel browser
open http://localhost:8080</code></pre>
<h5 class="mt-4">6. Primo accesso</h5>
<p>Al primo avvio, l'entrypoint esegue automaticamente migration e seed. Troverai gia popolati:</p>
<ul>
<li><strong>Tipologie Documenti:</strong> documento, avatar, galleria, statuto, programma, locandina, altro</li>
<li><strong>Tipologie Eventi:</strong> catechesi, liturgia, animazione, formazione, incontro, riunione, festa, altro</li>
<li><strong>Ruoli:</strong> presidente, vicepresidente, segretario, tesoriere, consigliere, volontario, socio, altro</li>
</ul>
<p>Dovrai creare il primo utente amministratore via CLI:</p>
<pre><code>docker exec -it glastree php artisan tinker --execute="
\$u = new \App\Models\User;
\$u->name = 'Amministratore';
\$u->email = 'admin@esempio.it';
\$u->password = bcrypt('password-forte');
\$u->is_admin = true;
\$u->permissions = ['individui' => 2, 'gruppi' => 2, 'eventi' => 2, 'documenti' => 2, 'mailing' => 2, 'viste' => 2, 'report' => 2, 'settings' => 2];
\$u->save();
echo 'Utente creato con successo!';
"</code></pre>
<div class="callout callout-warning mt-4">
<h6><i class="fas fa-exclamation-triangle"></i> Note importanti</h6>
<ul class="mb-0">
<li><strong>Persistenza:</strong> i volumi Docker preservano storage e database tra i riavvii</li>
<li><strong>APP_KEY:</strong> viene generata al primo avvio — se elimini i volumi, la perdi e i dati criptati diventano inaccessibili</li>
<li><strong>MySQL in produzione:</strong> imposta password sicure per <code>MYSQL_PASSWORD</code> e <code>MYSQL_ROOT_PASSWORD</code></li>
<li><strong>File compose separati:</strong> puoi mantenere entrambi i file (<code>docker-compose.yml</code> per SQLite, <code>docker-compose.mysql.yml</code> per MySQL) e scegliere con <code>-f</code></li>
</ul>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="help-installazione">
<div class="card card-outline card-dark">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-terminal mr-2"></i> Guida all'Installazione</h3>
</div>
<div class="card-body">
<h5>Panoramica</h5>
<p>L'installazione avviene tramite l'interattivo <code>install.php</code> che guida passo-passo. Supporta due modalita:</p>
<div class="row">
<div class="col-md-6">
<div class="callout callout-info">
<h6><i class="fas fa-rocket"></i> Fresh Install</h6>
<p class="mb-0">Installa l'applicazione da zero su un nuovo server: crea il database, esegue le migration, popola i dati di base e crea l'amministratore.</p>
</div>
</div>
<div class="col-md-6">
<div class="callout callout-success">
<h6><i class="fas fa-upload"></i> Restore da Backup</h6>
<p class="mb-0">Ripristina un'installazione esistente da un file ZIP di backup: importa il database, ripristina i documenti e la configurazione.</p>
</div>
</div>
</div>
<h5 class="mt-4">Requisiti del Server</h5>
<table class="table table-sm table-bordered">
<thead><tr><th>Componente</th><th>Versione Minima</th><th>Note</th></tr></thead>
<tbody>
<tr><td>Web Server</td><td>Apache 2.4+</td><td>Con mod_rewrite abilitato</td></tr>
<tr><td>PHP</td><td>8.2+ (consigliato 8.4)</td><td>Estensioni: pdo_mysql, mbstring, xml, curl, zip, gd, fileinfo</td></tr>
<tr><td>MySQL / MariaDB</td><td>MySQL 8.0+ / MariaDB 10.5+</td><td>Supporto utf8mb4</td></tr>
<tr><td>Composer</td><td>2.x</td><td>Per gestione dipendenze PHP</td></tr>
<tr><td>Node.js / npm</td><td>Node 20+ / npm 10+</td><td>Per compilazione asset frontend (opzionale se precompilati)</td></tr>
</tbody>
</table>
<h5 class="mt-4">Installazione Passo-Passo</h5>
<h6>Passo 1: Preparare il server LAMP</h6>
<pre><code>sudo apt update && sudo apt upgrade -y
sudo apt install -y apache2 mariadb-server php8.4 php8.4-cli \
php8.4-mysql php8.4-xml php8.4-mbstring php8.4-curl \
php8.4-zip php8.4-bcmath php8.4-gd php8.4-intl \
composer git unzip
sudo a2enmod rewrite
sudo systemctl restart apache2</code></pre>
<h6>Passo 2: Ottenere l'applicazione</h6>
<div class="callout callout-info py-2">
<i class="fas fa-info-circle"></i>
Puoi clonare il repository con git oppure estrarre il file ZIP ricevuto nella cartella <code>/var/www/glastree</code>.
</div>
<pre><code>cd /var/www
# Opzione A — Git clone
git clone &lt;URL_REPOSITORY&gt; glastree
# Opzione B — ZIP (se non hai git)
# unzip /percorso/del/glastree.zip -d glastree
cd glastree</code></pre>
<h6>Passo 3: Eseguire l'installer</h6>
<p>Lancerai l'installer interattivo che ti guidera attraverso tutte le fasi:</p>
<pre><code>php install.php</code></pre>
<p>L'installer ti chiedera:</p>
<ol>
<li><strong>Modalità</strong>: Fresh Install (Apache/Docker) o Restore da Backup</li>
<li><strong>Parametri generali</strong>: nome sito, amministratore (nome, email, password), URL pubblico</li>
<li><strong>Database</strong>: MySQL (host, porta, nome, utente, password) o SQLite</li>
</ol>
<p>L'installer esegue automaticamente:</p>
<ul>
<li>Generazione <code>.env</code> e <code>APP_KEY</code></li>
<li>Creazione del database</li>
<li><code>composer install</code> e registrazione pacchetti</li>
<li>Migration e seed dei dati di base</li>
<li>Creazione dell'utente amministratore</li>
<li>Compilazione asset frontend (se npm disponibile)</li>
<li>Impostazione permessi cartelle</li>
</ul>
<div class="callout callout-info">
<h6><i class="fas fa-info-circle"></i> Docker</h6>
<p>Se scegli la modalita Docker, l'installer builda l'immagine, avvia i container e crea l'admin all'interno del container.</p>
</div>
<div class="callout callout-success">
<h6><i class="fas fa-upload"></i> Restore da Backup</h6>
<p>Se scegli Restore, l'installer ti chiedera il percorso del file ZIP di backup, ripristinera il database, i file e la configurazione.</p>
</div>
<h6 class="mt-4">Passo 4: Configurare Apache (solo modalita Fresh Install)</h6>
<pre><code>sudo tee /etc/apache2/sites-available/glastree.conf &lt;&lt;APACHE
&lt;VirtualHost *:80&gt;
ServerName glastree.esempio.it
DocumentRoot /var/www/glastree/public
&lt;Directory /var/www/glastree/public&gt;
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
&lt;/Directory&gt;
ErrorLog \${APACHE_LOG_DIR}/glastree_error.log
CustomLog \${APACHE_LOG_DIR}/glastree_access.log combined
&lt;/VirtualHost&gt;
APACHE
sudo a2dissite 000-default.conf
sudo a2ensite glastree.conf
sudo systemctl reload apache2</code></pre>
<i class="fas fa-exclamation-triangle"></i>
<strong>Importante:</strong> Il restore da backup richiede che tu abbia un file ZIP generato dalla pagina <strong>Admin → Backup</strong> del server originale. Estrai manualmente il contenuto seguendo la struttura del progetto.
</div>
<h5 class="mt-4">Cosa succede durante l'installazione</h5>
<p>I comandi <code>php artisan migrate --seed</code> eseguono:</p>
<ol>
<li>Genera <code>APP_KEY</code> per la crittografia (gia eseguito al passo 5)</li>
<li>Esegue tutte le migration per creare le tabelle del database</li>
<li>Popola i dati di base (diocesi, comuni, ruoli, preset)</li>
<li>Crea il collegamento <code>storage &rarr; public/storage</code></li>
<li>Crea l'utente amministratore con i permessi completi</li>
</ol>
<h5 class="mt-4">Restore da Backup</h5>
<p>Il backup ZIP generato dalla pagina <strong>Admin &rarr; Backup</strong> contiene un dump SQL e i file dei documenti. Per ripristinare:</p>
<ul>
<li>Estrai il file ZIP in una cartella temporanea</li>
<li>Importa il database dal file SQL (<code>mysql -u root -p glastree &lt; backup/database.sql</code>)</li>
<li>Copia i file in <code>storage/app/</code> per ripristinare i documenti</li>
<li>Copia il file <code>.env</code> dal backup (modifica le credenziali DB per il nuovo server)</li>
<li>Esegui <code>php artisan key:generate</code> se la <code>APP_KEY</code> del backup non è utilizzabile</li>
</ul>
<h5 class="mt-4">Dopo l'Installazione</h5>
<ol>
<li><strong>Configura SSL</strong> con Let's Encrypt:
<pre><code>sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d glastree.esempio.it</code></pre>
</li>
<li><strong>Accedi</strong> con le credenziali amministratore create durante l'installazione</li>
<li><strong>Configura l'applicazione</strong> in Impostazioni:
<ul>
<li>Nome applicazione e logo</li>
<li>Email (SMTP per invio, IMAP per ricezione)</li>
<li>Repository remoti (Google Drive, Nextcloud)</li>
</ul>
</li>
<li><strong>Crea utenti</strong> dal pannello Admin &rarr; Utenti</li>
<li><strong>Configura il cron</strong> per backup automatico e sync email:
<pre><code>sudo crontab -u www-data -e
# Inserisci:
* * * * * cd /var/www/glastree && php artisan schedule:run >> /dev/null 2>&1</code></pre>
</li>
</ol>
<h5 class="mt-4">Risoluzione Problemi</h5>
<div class="callout callout-danger">
<h6>Errore "500 | Server Error" dopo l'installazione</h6>
<p>Probabilmente mancano permessi sulle cartelle <code>storage</code> o <code>bootstrap/cache</code>:</p>
<pre><code>sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cache</code></pre>
</div>
<div class="callout callout-danger">
<h6>Errore "No application encryption key"</h6>
<p>APP_KEY non generata. Nella cartella dell'app:</p>
<pre><code>php artisan key:generate</code></pre>
</div>
<div class="callout callout-warning">
<h6>mod_rewrite non funziona</h6>
<p>Se le rotte restituiscono 404, verifica che Apache abbia AllowOverride:</p>
<pre><code>sudo a2enmod rewrite
# Nel VirtualHost: AllowOverride All
sudo systemctl reload apache2</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.nav-pills .nav-link { border-radius: 0; }
.nav-pills .nav-link.active { background-color: #007bff; }
.callout { border-left: 3px solid; padding: 12px 16px; margin: 16px 0; background: #f8f9fa; }
.callout-info { border-color: #17a2b8; }
.callout-danger { border-color: #dc3545; }
.callout-warning { border-color: #ffc107; }
</style>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.adminlte', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/glastree/resources/views/help/index.blade.php ENDPATH**/ ?>
@@ -1,75 +0,0 @@
<?php
use App\Models\AppSetting;
$appLogo = AppSetting::getLogoUrl();
$appName = AppSetting::getAppName() ?? 'Glastree';
?>
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Reset Password - <?php echo e(e($appName)); ?></title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/admin-lte@3.2/dist/css/adminlte.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body class="hold-transition login-page">
<div class="login-box">
<div class="login-logo">
<a href="/">
<?php if($appLogo): ?>
<img src="<?php echo e($appLogo); ?>" alt="Logo" style="max-height: 80px; max-width: 200px;">
<?php else: ?>
<i class="fas fa-tree text-success"></i> <b><?php echo e(e($appName)); ?></b>
<?php endif; ?>
</a>
</div>
<div class="card">
<div class="card-body login-card-body">
<p class="login-box-msg">Password dimenticata? Inserisci la tua email e ti invieremo il link per reimpostarla.</p>
<?php if(session('success')): ?>
<div class="alert alert-success"><?php echo e(session('success')); ?></div>
<?php endif; ?>
<form action="<?php echo e(route('password.email')); ?>" method="POST">
<?php echo csrf_field(); ?>
<div class="input-group mb-3">
<input type="email" name="email" class="form-control <?php $__errorArgs = ['email'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>" placeholder="Email" required value="<?php echo e(old('email')); ?>">
<div class="input-group-append">
<div class="input-group-text"><span class="fas fa-envelope"></span></div>
</div>
<?php $__errorArgs = ['email'];
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
if ($__bag->has($__errorArgs[0])) :
if (isset($message)) { $__messageOriginal = $message; }
$message = $__bag->first($__errorArgs[0]); ?>
<span class="invalid-feedback"><?php echo e($message); ?></span>
<?php unset($message);
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
endif;
unset($__errorArgs, $__bag); ?>
</div>
<div class="row">
<div class="col-12">
<button type="submit" class="btn btn-success btn-block">Invia link reset</button>
</div>
</div>
</form>
<p class="mb-0 text-center mt-3">
<a href="<?php echo e(route('login')); ?>">Torna al login</a>
</p>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
<?php /**PATH /var/www/html/glastree/resources/views/auth/forgot-password.blade.php ENDPATH**/ ?>
@@ -1,165 +0,0 @@
<?php $__env->startSection('title', 'Dashboard'); ?>
<?php $__env->startSection('page_title', 'Dashboard'); ?>
<?php $__env->startSection('content'); ?>
<div class="row">
<div class="col-lg-3 col-6">
<div class="small-box bg-info">
<div class="inner">
<h3><?php echo e($stats['individui']); ?></h3>
<p>Individui</p>
</div>
<div class="icon">
<i class="fas fa-users"></i>
</div>
<a href="<?php echo e(route('individui.index')); ?>" class="small-box-footer">Visualizza <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<div class="col-lg-3 col-6">
<div class="small-box bg-success">
<div class="inner">
<h3><?php echo e($stats['gruppi']); ?></h3>
<p>Gruppi</p>
</div>
<div class="icon">
<i class="fas fa-folder"></i>
</div>
<a href="<?php echo e(route('gruppi.index')); ?>" class="small-box-footer">Visualizza <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<div class="col-lg-3 col-6">
<div class="small-box bg-primary">
<div class="inner">
<h3><?php echo e($stats['documenti']); ?></h3>
<p>Documenti</p>
</div>
<div class="icon">
<i class="fas fa-file"></i>
</div>
<a href="/documenti" class="small-box-footer">Visualizza <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<div class="col-lg-3 col-6">
<div class="small-box bg-danger">
<div class="inner">
<h3><?php echo e($stats['eventi']); ?></h3>
<p>Eventi</p>
</div>
<div class="icon">
<i class="fas fa-calendar"></i>
</div>
<a href="/eventi" class="small-box-footer">Visualizza <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-3 col-6">
<div class="small-box bg-warning">
<div class="inner">
<h3><?php echo e($stats['notifiche']); ?></h3>
<p>Notifiche</p>
</div>
<div class="icon">
<i class="fas fa-bell"></i>
</div>
<a href="#" class="small-box-footer">Visualizza <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<div class="col-lg-3 col-6">
<div class="small-box bg-secondary">
<div class="inner">
<h3><?php echo e($stats['email_nuove']); ?></h3>
<p>Nuove Email</p>
</div>
<div class="icon">
<i class="fas fa-envelope"></i>
</div>
<a href="/email" class="small-box-footer">Visualizza <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<div class="col-lg-3 col-6">
<div class="small-box bg-dark">
<div class="inner">
<h3><?php echo e($stats['mailing_liste']); ?></h3>
<p>Mailing List</p>
</div>
<div class="icon">
<i class="fas fa-list-alt"></i>
</div>
<a href="/mailing-liste" class="small-box-footer">Visualizza <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<?php if(Auth::user()->canManage('settings')): ?>
<div class="col-lg-3 col-6">
<div class="small-box bg-navy">
<div class="inner">
<h3><?php echo e($stats['backups']); ?></h3>
<p>Backup</p>
</div>
<div class="icon">
<i class="fas fa-hdd"></i>
</div>
<a href="<?php echo e(route('admin.backup.index')); ?>" class="small-box-footer">Visualizza <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<?php endif; ?>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-bell"></i> Ultime Notifiche</h3>
</div>
<div class="card-body">
<?php if($notifiche->count() > 0): ?>
<ul class="todo-list" data-widget="todo-list">
<?php $__currentLoopData = $notifiche; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $notifica): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<li>
<span class="text"><?php echo e($notifica->titolo); ?></span>
<small class="badge badge-info"><i class="far fa-clock"></i> <?php echo e($notifica->created_at->diffForHumans()); ?></small>
</li>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</ul>
<?php else: ?>
<p class="text-muted">Nessuna notifica</p>
<?php endif; ?>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-info-circle"></i> Benvenuto</h3>
</div>
<div class="card-body">
<?php
$appName = \App\Models\AppSetting::getAppName() ?? 'Glastree';
$orgName = \App\Models\AppSetting::getOrgName();
$welcome = \App\Models\AppSetting::getDashboardWelcome();
?>
<?php if($welcome): ?>
<p><?php echo nl2br(e($welcome)); ?></p>
<?php else: ?>
<p>Benvenuto in <strong><?php echo e(e($appName)); ?></strong><?php echo e($orgName ? ', ' . e($orgName) : ''); ?>.</p>
<?php endif; ?>
<p>Dal menu laterale puoi navigare tra le sezioni:</p>
<ul>
<li><strong>Individui</strong>: Gestione delle persone registrate</li>
<li><strong>Gruppi</strong>: Gestione della struttura organizzativa</li>
<li><strong>Documenti</strong>: Archivio documentale</li>
<li><strong>Eventi</strong>: Calendario eventi</li>
<li><strong>Mailing</strong>: Comunicazioni email</li>
</ul>
<?php if(Auth::user()->is_admin): ?>
<div class="alert alert-success mt-3">
<i class="fas fa-crown"></i> <strong>Amministratore</strong>: Hai accesso completo al sistema.
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.adminlte', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/glastree/resources/views/home/dashboard.blade.php ENDPATH**/ ?>
File diff suppressed because it is too large Load Diff
@@ -34,6 +34,9 @@ $canDeleteEventi = Auth::user()->canDelete('eventi');
</div>
<?php endif; ?>
<?php if($canWriteEventi): ?>
<a href="/eventi/import" class="btn btn-sm btn-warning mr-2">
<i class="fas fa-file-import mr-1"></i> Importa ICS
</a>
<a href="/eventi/create" class="btn btn-xs btn-success">
<i class="fas fa-plus mr-1"></i> Nuovo Evento
</a>
@@ -248,9 +251,30 @@ $canDeleteEventi = Auth::user()->canDelete('eventi');
</tbody>
</table>
</div>
<div class="card-footer">
<?php echo e($eventi->withQueryString()->links()); ?>
<div class="card-footer d-flex justify-content-between align-items-center">
<div>
<form method="GET" class="form-inline" id="perPageForm">
<label class="mr-2 small">Righe per pagina:</label>
<select name="perPage" class="form-control form-control-sm" onchange="this.form.submit()" style="width: auto;">
<?php $__currentLoopData = [10, 20, 25, 50, 100]; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $p): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($p); ?>" <?php echo e((int) request('perPage', 20) === $p ? 'selected' : ''); ?>><?php echo e($p); ?></option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<?php $__currentLoopData = request()->except(['perPage', 'page']); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $key => $value): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php if(is_array($value)): ?>
<?php $__currentLoopData = $value; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $v): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<input type="hidden" name="<?php echo e($key); ?>[]" value="<?php echo e($v); ?>">
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
<?php else: ?>
<input type="hidden" name="<?php echo e($key); ?>" value="<?php echo e($value); ?>">
<?php endif; ?>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</form>
</div>
<div>
<?php echo e($eventi->links()); ?>
</div>
</div>
</div>
@@ -219,9 +219,30 @@ $canDeleteIndividui = Auth::user()->canDelete('individui');
<?php endif; ?>
</div>
<?php if($individui->count() > 0): ?>
<div class="card-footer">
<?php echo e($individui->links()); ?>
<div class="card-footer d-flex justify-content-between align-items-center">
<div>
<form method="GET" class="form-inline" id="perPageForm">
<label class="mr-2 small">Righe per pagina:</label>
<select name="perPage" class="form-control form-control-sm" onchange="this.form.submit()" style="width: auto;">
<?php $__currentLoopData = [10, 20, 25, 50, 100]; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $p): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<option value="<?php echo e($p); ?>" <?php echo e((int) request('perPage', 20) === $p ? 'selected' : ''); ?>><?php echo e($p); ?></option>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</select>
<?php $__currentLoopData = request()->except(['perPage', 'page']); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $key => $value): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php if(is_array($value)): ?>
<?php $__currentLoopData = $value; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $v): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<input type="hidden" name="<?php echo e($key); ?>[]" value="<?php echo e($v); ?>">
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
<?php else: ?>
<input type="hidden" name="<?php echo e($key); ?>" value="<?php echo e($value); ?>">
<?php endif; ?>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</form>
</div>
<div>
<?php echo e($individui->links()); ?>
</div>
</div>
<?php endif; ?>
</div>
@@ -1,109 +0,0 @@
<?php $__env->startSection('title', 'Gestione Utenti'); ?>
<?php $__env->startSection('page_title', 'Gestione Utenti'); ?>
<?php $__env->startSection('breadcrumbs'); ?>
<li class="breadcrumb-item active">Admin</li>
<li class="breadcrumb-item active">Utenti</li>
<?php $__env->stopSection(); ?>
<?php $__env->startSection('content'); ?>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Utenti Registrati</h3>
<a href="/admin/utenti/create" class="btn btn-success btn-sm float-right">
<i class="fas fa-plus"></i> Nuovo Utente
</a>
</div>
<div class="card-body">
<form method="GET" class="mb-3">
<div class="row">
<div class="col-md-4">
<input type="text" name="search" class="form-control" placeholder="Cerca nome o email..." value="<?php echo e(request('search')); ?>">
</div>
<div class="col-md-3">
<select name="status" class="form-control">
<option value="">Tutti gli stati</option>
<option value="active" <?php echo e(request('status') == 'active' ? 'selected' : ''); ?>>Attivo</option>
<option value="suspended" <?php echo e(request('status') == 'suspended' ? 'selected' : ''); ?>>Sospeso</option>
<option value="pending" <?php echo e(request('status') == 'pending' ? 'selected' : ''); ?>>In attesa</option>
</select>
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-primary">Filtra</button>
</div>
</div>
</form>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Nome</th>
<th>Email</th>
<th>Stato</th>
<th>Permessi</th>
<th>Creato</th>
<th style="width: 150px;">Azioni</th>
</tr>
</thead>
<tbody>
<?php $__currentLoopData = $utenti; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $utente): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<tr>
<td>
<strong><?php echo e($utente->name); ?></strong>
<?php if($utente->isSuperAdmin()): ?>
<span class="badge badge-danger ml-1">Admin</span>
<?php endif; ?>
</td>
<td><?php echo e($utente->email); ?></td>
<td>
<?php switch($utente->status):
case ('active'): ?>
<span class="badge badge-success">Attivo</span>
<?php break; ?>
<?php case ('suspended'): ?>
<span class="badge badge-secondary">Sospeso</span>
<?php break; ?>
<?php case ('pending'): ?>
<span class="badge badge-warning">In attesa</span>
<?php break; ?>
<?php endswitch; ?>
</td>
<td>
<?php $summary = $utente->getPermissionsSummary(); ?>
<small>
<?php $__currentLoopData = $summary; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $module => $level): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<?php if($level !== 'Nessuno'): ?>
<span class="text-<?php echo e($level === 'Completo' ? 'success' : 'info'); ?>"><?php echo e(ucfirst($module)); ?>: <?php echo e($level); ?></span><br>
<?php endif; ?>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</small>
</td>
<td><?php echo e($utente->created_at->format('d/m/Y')); ?></td>
<td>
<a href="<?php echo e(url('/admin/utenti/' . $utente->id . '/edit')); ?>" class="btn btn-xs btn-warning">
<i class="fas fa-edit"></i>
</a>
<?php if($utente->id !== auth()->id()): ?>
<form method="POST" action="<?php echo e(url('/admin/utenti/' . $utente->id)); ?>" style="display: inline;">
<?php echo csrf_field(); ?> <?php echo method_field('DELETE'); ?>
<button type="submit" class="btn btn-xs btn-danger" onclick="return confirm('Eliminare questo utente?')">
<i class="fas fa-trash"></i>
</button>
</form>
<?php endif; ?>
</td>
</tr>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</tbody>
</table>
<?php echo e($utenti->links()); ?>
</div>
</div>
</div>
</div>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('admin.layout', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH /var/www/html/glastree/resources/views/admin/utenti/index.blade.php ENDPATH**/ ?>