Index page: remove Mots-clés button, move export to bulk selection, fix ZipArchive error, move DB export to paramètres, sticky thead

- Remove 'Mots-clés' button from toolbar (redundant with admin sidebar tags)
- Replace export dialog with 'Exporter CSV' + 'Exporter fichiers' buttons in bulk selection bar
- Export dispatcher now accepts ?ids=1,2,3 for per-selection export
- All ExportController/Database methods accept optional thesisIds array
- Graceful error message when ZipArchive extension is missing on server
- Move DB export (SQLite download) to paramètres → Maintenance section
- Sticky table column headers (position: sticky, top: 0, z-index: 5) for index page table
This commit is contained in:
Pontoporeia
2026-05-19 19:05:28 +02:00
parent b484943128
commit 678f9fc804
8 changed files with 148 additions and 86 deletions

View File

@@ -1,8 +1,11 @@
<script>
function toggleAll(src){document.querySelectorAll('input[name="selected_theses[]"]').forEach(cb=>cb.checked=src.checked);updateBulk();}
function updateBulk(){const n=document.querySelectorAll('input[name="selected_theses[]"]:checked').length;const b=document.getElementById('bulk-actions');document.getElementById('selected-count').textContent=n;b.style.display=n>0?'flex':'none';}
function confirmBulk(act){const n=document.querySelectorAll('input[name="selected_theses[]"]:checked').length;if(!n){document.getElementById('no-selection-dialog').showModal();return;}document.getElementById('bulk-action-input').value=act;if(act==='delete'){document.getElementById('bulk-delete-count').textContent=n;document.getElementById('bulk-delete-dialog').showModal();}else{document.getElementById('bulk-confirm-word').textContent=act==='publish'?'Publier':'Dépublier';document.getElementById('bulk-confirm-count').textContent=n;document.getElementById('bulk-confirm-dialog').showModal();}}
function execBulk(){const a=document.getElementById('bulk-action-input').value;const f=document.getElementById('bulk-form');f.action = a==='delete' ? 'actions/delete.php' : 'actions/publish.php';const c=document.getElementById('bulk-checkboxes');c.innerHTML='';document.querySelectorAll('input[name="selected_theses[]"]:checked').forEach(cb=>{const inp=document.createElement('input');inp.type='hidden';inp.name='selected_theses[]';inp.value=cb.value;c.appendChild(inp);});f.submit();}
function getSelectedIds(){return Array.from(document.querySelectorAll('input[name="selected_theses[]"]:checked')).map(cb=>cb.value);}
function confirmBulk(act){const ids=getSelectedIds();if(!ids.length){document.getElementById('no-selection-dialog').showModal();return;}const n=ids.length;document.getElementById('bulk-action-input').value=act;if(act==='delete'){document.getElementById('bulk-delete-count').textContent=n;document.getElementById('bulk-delete-dialog').showModal();}else{document.getElementById('bulk-confirm-word').textContent=act=='publish'?'Publier':'Dépublier';document.getElementById('bulk-confirm-count').textContent=n;document.getElementById('bulk-confirm-dialog').showModal();}}
function execBulk(){const a=document.getElementById('bulk-action-input').value;const f=document.getElementById('bulk-form');f.action = a=='delete' ? 'actions/delete.php' : 'actions/publish.php';const c=document.getElementById('bulk-checkboxes');c.innerHTML='';getSelectedIds().forEach(id=>{const inp=document.createElement('input');inp.type='hidden';inp.name='selected_theses[]';inp.value=id;c.appendChild(inp);});f.submit();}
function confirmExport(){const ids=getSelectedIds();if(!ids.length){document.getElementById('no-selection-dialog').showModal();return;}window.location.href='/admin/actions/export.php?csv=1&ids='+ids.join(',');}
function confirmExportFiles(){const ids=getSelectedIds();if(!ids.length){document.getElementById('no-selection-dialog').showModal();return;}window.location.href='/admin/actions/export.php?files=1&ids='+ids.join(',');}
function confirmDelete(id,title){document.getElementById('delete-thesis-title').textContent=title;document.getElementById('delete-thesis-dialog').showModal();document.getElementById('delete-dialog-confirm').onclick=function(){document.getElementById('delete-form-'+id).submit();};}
document.addEventListener('DOMContentLoaded',()=>{document.querySelectorAll('input[name="selected_theses[]"]').forEach(cb=>cb.addEventListener('change',updateBulk));});
document.addEventListener('htmx:afterSwap',()=>{document.querySelectorAll('input[name="selected_theses[]"]').forEach(cb=>cb.addEventListener('change',updateBulk));updateBulk();});
@@ -31,7 +34,6 @@ document.addEventListener('htmx:afterSwap',()=>{document.querySelectorAll('input
</div>
<div class="admin-btn-group">
<a href="/admin/add.php" class="btn btn--primary btn--sm">+ Ajouter un TFE</a>
<a href="/admin/tags.php" class="btn btn--primary btn--sm">Mots-clés</a>
<?php if ($trashCount > 0): ?>
<a href="/admin/index.php?tab=trash" class="btn btn--sm <?= $tab === 'trash' ? 'btn--primary' : 'btn--secondary' ?>">
Corbeille (<?= $trashCount ?>)
@@ -47,10 +49,6 @@ document.addEventListener('htmx:afterSwap',()=>{document.querySelectorAll('input
onclick="document.getElementById('import-dialog').showModal()">
Importer
</button>
<button type="button" class="btn btn--primary btn--sm" id="export-dialog-btn"
onclick="document.getElementById('export-dialog').showModal()">
Exporter
</button>
</div>
</div>
@@ -244,43 +242,6 @@ document.addEventListener('htmx:afterSwap',()=>{document.querySelectorAll('input
<?php endif; ?>
</dialog>
<!-- ══════════════════════════════════════════════════════════════
EXPORT DIALOG
══════════════════════════════════════════════════════════════ -->
<dialog id="export-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="export-dialog-title">
<div class="admin-dialog__header">
<h2 id="export-dialog-title">Exporter</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="document.getElementById('export-dialog').close()">&#x2715;</button>
</div>
<form method="get" action="/admin/actions/export.php" class="admin-form">
<div class="admin-form-group">
<label class="admin-checkbox-label">
<input type="checkbox" name="csv" value="1" checked>
CSV (tableau des métadonnées)
</label>
</div>
<div class="admin-form-group">
<label class="admin-checkbox-label">
<input type="checkbox" name="files" value="1" checked>
Fichiers (archive ZIP)
</label>
</div>
<div class="admin-form-group">
<label class="admin-checkbox-label">
<input type="checkbox" name="db" value="1">
Base de données (SQLite)
</label>
</div>
<div class="admin-form-footer">
<button type="submit" class="btn btn--primary">Exporter</button>
<button type="button" class="btn btn--secondary"
onclick="document.getElementById('export-dialog').close()">Annuler</button>
</div>
</form>
</dialog>
<!-- ══════════════════════════════════════════════════════════════
TMP CLEANUP DIALOG
══════════════════════════════════════════════════════════════ -->