mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
#gzip #extract-inline-js enable gzip in nginx + move ~730 lines of inline JS to 15 external files
This commit is contained in:
@@ -179,40 +179,7 @@
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<script>
|
||||
document.getElementById('open-create-dialog').addEventListener('click', () => {
|
||||
document.getElementById('create-dialog').showModal();
|
||||
});
|
||||
|
||||
let _pendingDeleteLinkId = null;
|
||||
function openDeleteLinkDialog(id) {
|
||||
_pendingDeleteLinkId = id;
|
||||
document.getElementById('delete-link-dialog').showModal();
|
||||
}
|
||||
function _executeDeleteLink() {
|
||||
const form = document.getElementById('delete-link-form-' + _pendingDeleteLinkId);
|
||||
if (form) form.submit();
|
||||
}
|
||||
|
||||
function copyUrl(id) {
|
||||
const input = document.getElementById('url-' + id);
|
||||
navigator.clipboard.writeText(input.value).then(() => {
|
||||
const btn = event.target.closest('button');
|
||||
const orig = btn.textContent;
|
||||
btn.textContent = '✓ Copié';
|
||||
setTimeout(() => { btn.textContent = orig; }, 1200);
|
||||
});
|
||||
}
|
||||
|
||||
function openPasswordDialog(id, hasPassword) {
|
||||
document.getElementById('password-link-id').value = id;
|
||||
const info = document.getElementById('password-current-info');
|
||||
info.textContent = hasPassword
|
||||
? 'Un mot de passe est actuellement configuré. Entrez-en un nouveau ou laissez vide pour le supprimer.'
|
||||
: 'Aucun mot de passe configuré.';
|
||||
document.getElementById('password-dialog').showModal();
|
||||
}
|
||||
</script>
|
||||
<script src="<?= App::assetV('/assets/js/app/admin-acces-sharelink.js') ?>"></script>
|
||||
|
||||
<!-- Delete link confirm -->
|
||||
<dialog id="delete-link-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="delete-link-title">
|
||||
|
||||
@@ -583,76 +583,10 @@
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<script>
|
||||
// ── Forward PHP flash data to JS globals ──────────────────────────────────
|
||||
const BASE_URL = <?= json_encode($baseUrl) ?>;
|
||||
const _newLinkPassword = <?= json_encode($newLinkPassword ?? '') ?>;
|
||||
const _newLinkSlug = <?= json_encode($newLinkSlug ?? '') ?>;
|
||||
|
||||
// ── Show result dialogs after redirect ────────────────────────────────────
|
||||
if (_newLinkSlug && _newLinkPassword) {
|
||||
document.getElementById('create-result-password').value = _newLinkPassword;
|
||||
document.getElementById('create-result-url').value = BASE_URL + '/partage/' + _newLinkSlug;
|
||||
document.getElementById('create-result-dialog').showModal();
|
||||
}
|
||||
|
||||
document.getElementById('open-create-dialog').addEventListener('click', () => {
|
||||
document.getElementById('create-dialog').showModal();
|
||||
});
|
||||
|
||||
function copyUrl(id) {
|
||||
const input = document.getElementById('url-' + id);
|
||||
navigator.clipboard.writeText(input.value).then(() => {
|
||||
const btn = event.target.closest('button');
|
||||
if (btn) { const orig = btn.getAttribute('title') || ''; btn.setAttribute('title', '✓ Copié'); setTimeout(() => btn.setAttribute('title', orig), 1200); }
|
||||
});
|
||||
}
|
||||
|
||||
function copyUrlFrom(el) {
|
||||
navigator.clipboard.writeText(el.value).then(() => {
|
||||
const btn = el.nextElementSibling;
|
||||
if (btn) { const orig = btn.textContent; btn.textContent = '✓ Copié'; setTimeout(() => { btn.textContent = orig; }, 1200); }
|
||||
});
|
||||
}
|
||||
|
||||
function copyTextToClipboard(text) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
const btn = event?.target?.closest('button');
|
||||
if (btn) { const orig = btn.getAttribute('title') || ''; btn.setAttribute('title', '✓ Copié'); setTimeout(() => btn.setAttribute('title', orig), 1200); }
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
function openEditDialog(id, name, hasPassword, expiresVal) {
|
||||
document.getElementById('edit-link-id').value = id;
|
||||
document.getElementById('edit-name').value = name || '';
|
||||
document.getElementById('edit-expires').value = expiresVal || '';
|
||||
document.getElementById('edit-dialog').showModal();
|
||||
}
|
||||
|
||||
function openApproveDialog(requestId) {
|
||||
document.getElementById('approve-request-id').value = requestId;
|
||||
document.getElementById('approve-dialog').showModal();
|
||||
}
|
||||
|
||||
function openRejectDialog(requestId) {
|
||||
document.getElementById('reject-request-id').value = requestId;
|
||||
document.getElementById('reject-dialog').showModal();
|
||||
}
|
||||
|
||||
let _pendingArchiveLinkId = null;
|
||||
function openArchiveLinkDialog(id) {
|
||||
_pendingArchiveLinkId = id;
|
||||
document.getElementById('archive-link-dialog').showModal();
|
||||
}
|
||||
function _executeArchiveLink() {
|
||||
const form = document.getElementById('archive-link-form-' + _pendingArchiveLinkId);
|
||||
if (form) form.submit();
|
||||
}
|
||||
function openDeleteArchivedLinkDialog(id) {
|
||||
document.getElementById('delete-archived-link-id').value = id;
|
||||
document.getElementById('delete-archived-link-dialog').showModal();
|
||||
}
|
||||
</script>
|
||||
<meta name="acces-base-url" content="<?= htmlspecialchars($baseUrl) ?>">
|
||||
<meta name="acces-new-link-password" content="<?= htmlspecialchars($newLinkPassword ?? '') ?>">
|
||||
<meta name="acces-new-link-slug" content="<?= htmlspecialchars($newLinkSlug ?? '') ?>">
|
||||
<script src="<?= App::assetV('/assets/js/app/admin-acces.js') ?>"></script>
|
||||
|
||||
<!-- Archive link confirm -->
|
||||
<dialog id="archive-link-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="archive-link-title">
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
hx-post="/admin/actions/apropos.php"
|
||||
hx-trigger="change delay:1500ms, input delay:1500ms"
|
||||
hx-swap="none"
|
||||
hx-on::after-request="handleAutosaveResponse(event)">
|
||||
hx-on::after-request="handleAutosaveResponse(event)"
|
||||
data-apropos-key="<?= $aproposKey ?>"
|
||||
data-apropos-group-count="<?= count($groups) ?>">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
<input type="hidden" name="apropos_key" value="<?= htmlspecialchars($aproposKey) ?>">
|
||||
|
||||
@@ -93,83 +95,4 @@
|
||||
</fieldset>
|
||||
</template>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var key = '<?= $aproposKey ?>';
|
||||
var form = document.getElementById('apropos-form-' + key);
|
||||
var groupCount = <?= count($groups) ?>;
|
||||
var entryTpl = document.getElementById('entry-template-f-' + key).innerHTML;
|
||||
var groupTpl = document.getElementById('group-template-f-' + key).innerHTML;
|
||||
|
||||
function reindexGroups() {
|
||||
var fieldsets = form.querySelectorAll('fieldset.apropos-group');
|
||||
groupCount = fieldsets.length;
|
||||
fieldsets.forEach(function(fs, i) {
|
||||
var newIdx = i;
|
||||
var legend = fs.querySelector('legend');
|
||||
if (legend) legend.textContent = 'Contact ' + (newIdx + 1);
|
||||
|
||||
// Update name attributes on all inputs
|
||||
fs.querySelectorAll('input').forEach(function(inp) {
|
||||
if (inp.name) {
|
||||
inp.name = inp.name.replace(/groups\[\d+\]/, 'groups[' + newIdx + ']');
|
||||
}
|
||||
if (inp.id) {
|
||||
inp.id = inp.id.replace(/(group_f_contacts_|entry_f_contacts_)\d+/, '$1' + newIdx);
|
||||
}
|
||||
});
|
||||
|
||||
// Update for attributes on labels
|
||||
fs.querySelectorAll('label[for]').forEach(function(lbl) {
|
||||
lbl.setAttribute('for', lbl.getAttribute('for').replace(/(group_f_contacts_|entry_f_contacts_)\d+/, '$1' + newIdx));
|
||||
});
|
||||
|
||||
// Update data-group on add-entry button
|
||||
var addBtn = fs.querySelector('.add-entry-btn-f');
|
||||
if (addBtn) addBtn.dataset.group = newIdx;
|
||||
});
|
||||
}
|
||||
|
||||
function bindAddEntry(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
var gi = parseInt(this.dataset.group);
|
||||
var fieldset = this.closest('fieldset');
|
||||
var entryCount = fieldset.querySelectorAll('.apropos-entry').length;
|
||||
var html = entryTpl.replaceAll('{{gi}}', gi).replaceAll('{{ei}}', entryCount);
|
||||
this.insertAdjacentHTML('beforebegin', html);
|
||||
});
|
||||
}
|
||||
|
||||
function bindDeleteGroup(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
var fieldset = this.closest('fieldset');
|
||||
if (fieldset) {
|
||||
fieldset.remove();
|
||||
reindexGroups();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Bind existing buttons
|
||||
form.querySelectorAll('.add-entry-btn-f').forEach(bindAddEntry);
|
||||
form.querySelectorAll('.delete-group-btn-f').forEach(bindDeleteGroup);
|
||||
|
||||
form.querySelector('.add-group-btn-f').addEventListener('click', function() {
|
||||
groupCount++;
|
||||
var html = groupTpl.replaceAll('{{gi}}', groupCount);
|
||||
this.insertAdjacentHTML('beforebegin', html);
|
||||
|
||||
var newGroup = this.previousElementSibling;
|
||||
if (newGroup && newGroup.classList.contains('apropos-group')) {
|
||||
var addBtn = newGroup.querySelector('.add-entry-btn-f');
|
||||
if (addBtn) {
|
||||
addBtn.dataset.group = groupCount;
|
||||
bindAddEntry(addBtn);
|
||||
}
|
||||
var delBtn = newGroup.querySelector('.delete-group-btn-f');
|
||||
if (delBtn) bindDeleteGroup(delBtn);
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script src="<?= App::assetV('/assets/js/app/admin-contacts-form.js') ?>"></script>
|
||||
|
||||
@@ -92,47 +92,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var form = document.getElementById('sidebar-links-form');
|
||||
var tpl = document.getElementById('sidebar-link-tpl');
|
||||
var tplHtml = tpl.innerHTML;
|
||||
|
||||
function reindexLinks() {
|
||||
var rows = form.querySelectorAll('.sidebar-link-row');
|
||||
rows.forEach(function(row, i) {
|
||||
row.querySelectorAll('input').forEach(function(inp) {
|
||||
if (inp.name) {
|
||||
inp.name = inp.name.replace(/links\[\d+\]/, 'links[' + i + ']');
|
||||
}
|
||||
if (inp.id) {
|
||||
inp.id = inp.id.replace(/sl_\d+/, 'sl_' + i);
|
||||
}
|
||||
});
|
||||
row.querySelectorAll('label[for]').forEach(function(lbl) {
|
||||
lbl.setAttribute('for', lbl.getAttribute('for').replace(/sl_\d+/, 'sl_' + i));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Event delegation for remove buttons (including dynamically added)
|
||||
form.addEventListener('click', function(e) {
|
||||
if (!e.target.closest('.remove-sidebar-link-btn')) return;
|
||||
e.preventDefault();
|
||||
e.target.closest('.sidebar-link-row').remove();
|
||||
reindexLinks();
|
||||
});
|
||||
|
||||
// Add button
|
||||
var addBtn = document.getElementById('add-sidebar-link-btn');
|
||||
addBtn.addEventListener('click', function() {
|
||||
var rows = form.querySelectorAll('.sidebar-link-row');
|
||||
var idx = rows.length;
|
||||
var html = tplHtml.split('{{li}}').join(idx);
|
||||
this.insertAdjacentHTML('beforebegin', html);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script src="<?= App::assetV('/assets/js/app/sidebar-links-editor.js') ?>"></script>
|
||||
|
||||
<?php elseif ($editType === 'page' && $pageSlug !== 'about'): ?>
|
||||
<form action="/admin/actions/page.php" method="post" class="admin-form admin-form--full-editor">
|
||||
|
||||
@@ -289,16 +289,9 @@
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<script src="<?= App::assetV('/assets/js/app/admin-contenus-langues.js') ?>"></script>
|
||||
<script>
|
||||
let _languesPendingForm = null;
|
||||
|
||||
function languesConfirmDelete(btn, name) {
|
||||
_languesPendingForm = btn.closest('form');
|
||||
document.getElementById('langues-delete-name').textContent = name;
|
||||
document.getElementById('langues-delete-dialog').showModal();
|
||||
}
|
||||
|
||||
// ── Inline rename via HTMX ──────────────────────────────────────────────
|
||||
// ── Inline rename via HTMX (needs PHP-generated icon SVGs) ───────────────
|
||||
function languesStartRename(id) {
|
||||
var cell = document.getElementById('lang-name-' + id);
|
||||
var csrf = document.querySelector('input[name="csrf_token"]').value;
|
||||
@@ -324,96 +317,6 @@ function languesCancelRename(id) {
|
||||
+ '<?= icon('pencil-note') ?>'
|
||||
+ '</button>';
|
||||
}
|
||||
|
||||
function languesSubmitPending() {
|
||||
if (_languesPendingForm) _languesPendingForm.submit();
|
||||
}
|
||||
|
||||
function languesToggleAll(src) {
|
||||
document.querySelectorAll('input[name="selected_langs[]"]').forEach(cb => cb.checked = src.checked);
|
||||
languesUpdateBulk();
|
||||
}
|
||||
|
||||
function languesUpdateBulk() {
|
||||
const n = document.querySelectorAll('input[name="selected_langs[]"]:checked').length;
|
||||
document.getElementById('langues-selected-count').textContent = n;
|
||||
const bar = document.getElementById('langues-bulk-actions');
|
||||
const wrap = document.getElementById('langues-table-wrap');
|
||||
const visible = n > 1;
|
||||
bar.style.display = visible ? 'flex' : 'none';
|
||||
// Force reflow then read bar height for sticky th offset
|
||||
if (visible) {
|
||||
requestAnimationFrame(() => {
|
||||
wrap.style.setProperty('--sticky-top', bar.offsetHeight + 'px');
|
||||
});
|
||||
} else {
|
||||
wrap.style.setProperty('--sticky-top', '0px');
|
||||
}
|
||||
}
|
||||
|
||||
function languesCancelSelection() {
|
||||
document.querySelectorAll('input[name="selected_langs[]"]').forEach(cb => cb.checked = false);
|
||||
languesUpdateBulk();
|
||||
}
|
||||
|
||||
function languesConfirmBulkDelete() {
|
||||
const checked = document.querySelectorAll('input[name="selected_langs[]"]:checked');
|
||||
if (checked.length < 1) return;
|
||||
document.getElementById('langues-bulk-delete-count').textContent = checked.length;
|
||||
document.getElementById('langues-bulk-delete-dialog').showModal();
|
||||
}
|
||||
|
||||
function languesExecBulkDelete() {
|
||||
const container = document.getElementById('langues-bulk-checkboxes');
|
||||
container.innerHTML = '';
|
||||
document.querySelectorAll('input[name="selected_langs[]"]:checked').forEach(cb => {
|
||||
const inp = document.createElement('input');
|
||||
inp.type = 'hidden';
|
||||
inp.name = 'selected_langs[]';
|
||||
inp.value = cb.value;
|
||||
container.appendChild(inp);
|
||||
});
|
||||
document.getElementById('langues-bulk-form').querySelector('input[name="action"]').value = 'delete_bulk';
|
||||
document.getElementById('langues-bulk-delete-dialog').close();
|
||||
document.getElementById('langues-bulk-form').submit();
|
||||
}
|
||||
|
||||
function languesConfirmBulkMerge() {
|
||||
const checked = document.querySelectorAll('input[name="selected_langs[]"]:checked');
|
||||
if (checked.length < 2) return;
|
||||
document.getElementById('langues-bulk-merge-count').textContent = checked.length;
|
||||
const sel = document.getElementById('langues-bulk-merge-target-select');
|
||||
sel.innerHTML = '<option value="">— Choisir la destination —</option>';
|
||||
checked.forEach(cb => {
|
||||
const tr = cb.closest('tr');
|
||||
sel.innerHTML += '<option value="' + cb.value + '">' + tr.querySelector('td:nth-child(2)').textContent.trim() + '</option>';
|
||||
});
|
||||
document.getElementById('langues-bulk-merge-dialog').showModal();
|
||||
}
|
||||
|
||||
function languesExecBulkMerge() {
|
||||
const targetId = document.getElementById('langues-bulk-merge-target-select').value;
|
||||
if (!targetId) return;
|
||||
document.getElementById('langues-bulk-target').value = targetId;
|
||||
const container = document.getElementById('langues-bulk-checkboxes');
|
||||
container.innerHTML = '';
|
||||
document.querySelectorAll('input[name="selected_langs[]"]:checked').forEach(cb => {
|
||||
const inp = document.createElement('input');
|
||||
inp.type = 'hidden';
|
||||
inp.name = 'selected_langs[]';
|
||||
inp.value = cb.value;
|
||||
container.appendChild(inp);
|
||||
});
|
||||
document.getElementById('langues-bulk-merge-dialog').close();
|
||||
document.getElementById('langues-bulk-form').submit();
|
||||
}
|
||||
|
||||
document.addEventListener('htmx:afterSwap', function(evt) {
|
||||
if (evt.target.id === 'langues-table-wrap') {
|
||||
document.querySelectorAll('input[name="selected_langs[]"]').forEach(cb => cb.addEventListener('change', languesUpdateBulk));
|
||||
languesUpdateBulk();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
@@ -468,16 +371,9 @@ document.addEventListener('htmx:afterSwap', function(evt) {
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<script src="<?= App::assetV('/assets/js/app/admin-contenus-motscles.js') ?>"></script>
|
||||
<script>
|
||||
let _motsclesPendingForm = null;
|
||||
|
||||
function motsclesConfirmDelete(btn, name) {
|
||||
_motsclesPendingForm = btn.closest('form');
|
||||
document.getElementById('motscles-delete-name').textContent = name;
|
||||
document.getElementById('motscles-delete-dialog').showModal();
|
||||
}
|
||||
|
||||
// ── Inline rename via HTMX ──────────────────────────────────────────────
|
||||
// ── Inline rename via HTMX (needs PHP-generated icon SVGs) ───────────────
|
||||
function motsclesStartRename(id) {
|
||||
var cell = document.getElementById('motscles-name-' + id);
|
||||
var csrf = document.querySelector('input[name="csrf_token"]').value;
|
||||
@@ -503,96 +399,6 @@ function motsclesCancelRename(id) {
|
||||
+ '<?= icon('pencil-note') ?>'
|
||||
+ '</button>';
|
||||
}
|
||||
|
||||
function motsclesSubmitPending() {
|
||||
if (_motsclesPendingForm) _motsclesPendingForm.submit();
|
||||
}
|
||||
|
||||
function motsclesToggleAll(src) {
|
||||
document.querySelectorAll('input[name="selected_tags[]"]').forEach(cb => cb.checked = src.checked);
|
||||
motsclesUpdateBulk();
|
||||
}
|
||||
|
||||
function motsclesUpdateBulk() {
|
||||
const n = document.querySelectorAll('input[name="selected_tags[]"]:checked').length;
|
||||
document.getElementById('motscles-selected-count').textContent = n;
|
||||
const bar = document.getElementById('motscles-bulk-actions');
|
||||
const wrap = document.getElementById('motscles-table-wrap');
|
||||
const visible = n > 1;
|
||||
bar.style.display = visible ? 'flex' : 'none';
|
||||
// Force reflow then read bar height for sticky th offset
|
||||
if (visible) {
|
||||
requestAnimationFrame(() => {
|
||||
wrap.style.setProperty('--sticky-top', bar.offsetHeight + 'px');
|
||||
});
|
||||
} else {
|
||||
wrap.style.setProperty('--sticky-top', '0px');
|
||||
}
|
||||
}
|
||||
|
||||
function motsclesConfirmBulkMerge() {
|
||||
const checked = document.querySelectorAll('input[name="selected_tags[]"]:checked');
|
||||
if (checked.length < 2) return;
|
||||
document.getElementById('motscles-bulk-merge-count').textContent = checked.length;
|
||||
const sel = document.getElementById('motscles-bulk-merge-target-select');
|
||||
sel.innerHTML = '<option value="">— Choisir la destination —</option>';
|
||||
checked.forEach(cb => {
|
||||
const tr = cb.closest('tr');
|
||||
sel.innerHTML += '<option value="' + cb.value + '">' + tr.querySelector('td:nth-child(2)').textContent.trim() + '</option>';
|
||||
});
|
||||
document.getElementById('motscles-bulk-merge-dialog').showModal();
|
||||
}
|
||||
|
||||
function motsclesExecBulkMerge() {
|
||||
const targetId = document.getElementById('motscles-bulk-merge-target-select').value;
|
||||
if (!targetId) return;
|
||||
document.getElementById('motscles-bulk-target').value = targetId;
|
||||
const container = document.getElementById('motscles-bulk-checkboxes');
|
||||
container.innerHTML = '';
|
||||
document.querySelectorAll('input[name="selected_tags[]"]:checked').forEach(cb => {
|
||||
const inp = document.createElement('input');
|
||||
inp.type = 'hidden';
|
||||
inp.name = 'selected_tags[]';
|
||||
inp.value = cb.value;
|
||||
container.appendChild(inp);
|
||||
});
|
||||
document.getElementById('motscles-bulk-merge-dialog').close();
|
||||
document.getElementById('motscles-bulk-form').submit();
|
||||
}
|
||||
|
||||
function motsclesCancelSelection() {
|
||||
document.querySelectorAll('input[name="selected_tags[]"]').forEach(cb => cb.checked = false);
|
||||
motsclesUpdateBulk();
|
||||
}
|
||||
|
||||
function motsclesConfirmBulkDelete() {
|
||||
const checked = document.querySelectorAll('input[name="selected_tags[]"]:checked');
|
||||
if (checked.length < 1) return;
|
||||
document.getElementById('motscles-bulk-delete-count').textContent = checked.length;
|
||||
document.getElementById('motscles-bulk-delete-dialog').showModal();
|
||||
}
|
||||
|
||||
function motsclesExecBulkDelete() {
|
||||
const container = document.getElementById('motscles-bulk-checkboxes');
|
||||
container.innerHTML = '';
|
||||
document.querySelectorAll('input[name="selected_tags[]"]:checked').forEach(cb => {
|
||||
const inp = document.createElement('input');
|
||||
inp.type = 'hidden';
|
||||
inp.name = 'selected_tags[]';
|
||||
inp.value = cb.value;
|
||||
container.appendChild(inp);
|
||||
});
|
||||
document.getElementById('motscles-bulk-form').querySelector('input[name="action"]').value = 'delete_bulk';
|
||||
document.getElementById('motscles-bulk-delete-dialog').close();
|
||||
document.getElementById('motscles-bulk-form').submit();
|
||||
}
|
||||
|
||||
document.addEventListener('htmx:afterSwap', function(evt) {
|
||||
if (evt.target.id === 'motscles-table-wrap') {
|
||||
document.querySelectorAll('input[name="selected_tags[]"]').forEach(cb => cb.addEventListener('change', motsclesUpdateBulk));
|
||||
motsclesUpdateBulk();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -182,16 +182,6 @@
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<script>
|
||||
function openApproveDialog(requestId) {
|
||||
document.getElementById('approve-request-id').value = requestId;
|
||||
document.getElementById('approve-dialog').showModal();
|
||||
}
|
||||
|
||||
function openRejectDialog(requestId) {
|
||||
document.getElementById('reject-request-id').value = requestId;
|
||||
document.getElementById('reject-dialog').showModal();
|
||||
}
|
||||
</script>
|
||||
<script src="<?= App::assetV('/assets/js/app/admin-file-access.js') ?>"></script>
|
||||
|
||||
|
||||
|
||||
@@ -17,35 +17,6 @@
|
||||
<script><?= $extraJsInline ?></script>
|
||||
<?php endif; ?>
|
||||
<script src="/assets/js/vendor/htmx.min.js"></script>
|
||||
<script>
|
||||
// Global HTMX debugging for settings checkboxes
|
||||
document.body.addEventListener('htmx:sendError', function (e) {
|
||||
console.error('[htmx:sendError] target=', e.target.id, 'detail=', e.detail);
|
||||
});
|
||||
document.body.addEventListener('htmx:beforeSend', function (e) {
|
||||
if (e.target.id && (e.target.id.includes('fieldset-') || e.target.name)) {
|
||||
console.log('[htmx:beforeSend] name=' + e.target.name + ' checked=' + e.target.checked);
|
||||
}
|
||||
});
|
||||
document.body.addEventListener('htmx:afterSettle', function (e) {
|
||||
if (e.target && e.target.id === 'toast-region') {
|
||||
var warn = e.target.querySelector('.toast--warning');
|
||||
if (warn) { warn.setAttribute('tabindex', '-1'); warn.focus(); }
|
||||
}
|
||||
});
|
||||
|
||||
// Markdown cheatsheet: close on backdrop click, remove stale dialogs before new one arrives
|
||||
document.body.addEventListener('htmx:beforeRequest', function(e) {
|
||||
if (e.detail.requestConfig && e.detail.requestConfig.path === '/admin/markdown-cheatsheet-fragment.php') {
|
||||
var old = document.getElementById('md-cheatsheet-dialog');
|
||||
if (old) old.remove();
|
||||
}
|
||||
});
|
||||
document.body.addEventListener('click', function(e) {
|
||||
if (e.target.tagName === 'DIALOG' && e.target.id === 'md-cheatsheet-dialog') {
|
||||
e.target.close();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script src="<?= App::assetV('/assets/js/app/htmx-global-setup.js') ?>"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -120,7 +120,4 @@ $sortArrow = function(string $col) use ($sortCol, $sortDir): string {
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
document.querySelectorAll('input[name="selected_theses[]"]').forEach(cb => cb.addEventListener('change', updateBulk));
|
||||
</script>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,4 @@
|
||||
<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';document.getElementById('admin-table-wrap').style.setProperty('--sticky-top',n>0?b.offsetHeight+'px':'0px');}
|
||||
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();});
|
||||
</script>
|
||||
<script src="<?= App::assetV('/assets/js/app/admin-index-bulk.js') ?>"></script>
|
||||
|
||||
<main id="main-content" class="admin-main--list">
|
||||
<!-- Title + filters + stats + import all in one toolbar row -->
|
||||
|
||||
@@ -481,18 +481,7 @@
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// Focus the SMTP field that caused the probe error
|
||||
(function () {
|
||||
var form = document.querySelector('form[data-smtp-error-field]');
|
||||
if (!form) return;
|
||||
var fieldId = form.getAttribute('data-smtp-error-field');
|
||||
var el = fieldId ? document.getElementById(fieldId) : null;
|
||||
if (!el) return;
|
||||
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
el.focus();
|
||||
}());
|
||||
</script>
|
||||
<script src="<?= App::assetV('/assets/js/app/smtp-error-focus.js') ?>"></script>
|
||||
<script src="/assets/js/app/admin-logs.js"></script>
|
||||
|
||||
<!-- Enable maintenance confirm -->
|
||||
|
||||
@@ -12,46 +12,4 @@
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
function build() {
|
||||
var main = document.getElementById('main-content');
|
||||
var nav = document.getElementById('admin-toc-list');
|
||||
var aside = document.getElementById('admin-toc');
|
||||
if (!main || !nav || !aside) return;
|
||||
|
||||
var sections = main.querySelectorAll('section[aria-labelledby]');
|
||||
if (sections.length < 2) { aside.hidden = true; return; }
|
||||
|
||||
var items = [];
|
||||
sections.forEach(function(sec) {
|
||||
var headingId = sec.getAttribute('aria-labelledby');
|
||||
var heading = document.getElementById(headingId);
|
||||
if (!heading) return;
|
||||
if (!sec.id) sec.id = headingId;
|
||||
|
||||
var a = document.createElement('a');
|
||||
a.href = '#' + sec.id;
|
||||
a.textContent = heading.textContent.trim();
|
||||
a.style.display = 'block';
|
||||
nav.appendChild(a);
|
||||
items.push({ section: sec, link: a });
|
||||
});
|
||||
|
||||
var observer = new IntersectionObserver(function(entries) {
|
||||
var best = null, bestRatio = 0;
|
||||
entries.forEach(function(e) {
|
||||
if (e.intersectionRatio > bestRatio) { bestRatio = e.intersectionRatio; best = e.target; }
|
||||
});
|
||||
items.forEach(function(item) {
|
||||
item.link.classList.toggle('admin-toc-active', item.section === best);
|
||||
});
|
||||
}, { rootMargin: '-10% 0px -70% 0px', threshold: [0, 0.25, 0.5, 0.75, 1] });
|
||||
|
||||
items.forEach(function(item) { observer.observe(item.section); });
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', build);
|
||||
else build();
|
||||
})();
|
||||
</script>
|
||||
<script src="<?= App::assetV('/assets/js/app/admin-toc.js') ?>"></script>
|
||||
|
||||
@@ -1,89 +1,30 @@
|
||||
<script src="<?= App::assetV('/assets/js/app/admin-tags.js') ?>"></script>
|
||||
<script>
|
||||
let _pendingTagForm = null;
|
||||
|
||||
function tagsToggleAll(src) {
|
||||
document.querySelectorAll('input[name="selected_tags[]"]').forEach(cb => cb.checked = src.checked);
|
||||
tagsUpdateBulk();
|
||||
}
|
||||
|
||||
function tagsUpdateBulk() {
|
||||
const n = document.querySelectorAll('input[name="selected_tags[]"]:checked').length;
|
||||
document.getElementById('tags-selected-count').textContent = n;
|
||||
document.getElementById('tags-bulk-actions').style.display = n > 1 ? 'flex' : 'none';
|
||||
}
|
||||
|
||||
function tagsConfirmBulkMerge() {
|
||||
const checked = document.querySelectorAll('input[name="selected_tags[]"]:checked');
|
||||
if (checked.length < 2) return;
|
||||
document.getElementById('bulk-merge-count').textContent = checked.length;
|
||||
const sel = document.getElementById('bulk-merge-target-select');
|
||||
sel.innerHTML = '<option value="">— Choisir la destination —</option>';
|
||||
checked.forEach(cb => {
|
||||
const tr = cb.closest('tr');
|
||||
sel.innerHTML += '<option value="' + cb.value + '">' + tr.querySelector('.tag-name-cell').textContent.trim() + '</option>';
|
||||
});
|
||||
document.getElementById('bulk-merge-dialog').showModal();
|
||||
}
|
||||
|
||||
function tagsExecBulkMerge() {
|
||||
const targetId = document.getElementById('bulk-merge-target-select').value;
|
||||
if (!targetId) return;
|
||||
document.getElementById('tags-bulk-target').value = targetId;
|
||||
const container = document.getElementById('tags-bulk-checkboxes');
|
||||
container.innerHTML = '';
|
||||
document.querySelectorAll('input[name="selected_tags[]"]:checked').forEach(cb => {
|
||||
const inp = document.createElement('input');
|
||||
inp.type = 'hidden';
|
||||
inp.name = 'selected_tags[]';
|
||||
inp.value = cb.value;
|
||||
container.appendChild(inp);
|
||||
});
|
||||
document.getElementById('bulk-merge-dialog').close();
|
||||
document.getElementById('tags-bulk-form').submit();
|
||||
}
|
||||
|
||||
// ── Inline rename via HTMX ──────────────────────────────────────────────────
|
||||
// ── Inline rename via HTMX (needs PHP-generated icon SVGs) ───────────────
|
||||
function tagsStartRename(id) {
|
||||
var cell = document.getElementById('tag-name-' + id);
|
||||
var csrf = document.querySelector('input[name="csrf_token"]').value;
|
||||
cell.innerHTML = '<form hx-post=\"/admin/actions/tag.php\" hx-target=\"#tags-table-wrap\" hx-swap=\"innerHTML\" class=\"admin-inline-form\">'
|
||||
+ '<input type=\"hidden\" name=\"csrf_token\" value=\"' + csrf + '\">'
|
||||
+ '<input type=\"hidden\" name=\"action\" value=\"rename\">'
|
||||
+ '<input type=\"hidden\" name=\"tag_id\" value=\"' + id + '\">'
|
||||
+ '<input type=\"text\" name=\"new_name\" value=\"' + cell.getAttribute('data-name') + '\" required class=\"admin-input--inline\">'
|
||||
+ '<button type=\"submit\" class=\"admin-icon-btn admin-icon-btn--edit\" title=\"Valider\">'
|
||||
+ '<?= icon("check-circle") ?>'
|
||||
cell.innerHTML = '<form hx-post="/admin/actions/tag.php" hx-target="#tags-table-wrap" hx-swap="innerHTML" class="admin-inline-form">'
|
||||
+ '<input type="hidden" name="csrf_token" value="' + csrf + '">'
|
||||
+ '<input type="hidden" name="action" value="rename">'
|
||||
+ '<input type="hidden" name="tag_id" value="' + id + '">'
|
||||
+ '<input type="text" name="new_name" value="' + cell.getAttribute('data-name') + '" required class="admin-input--inline">'
|
||||
+ '<button type="submit" class="admin-icon-btn admin-icon-btn--edit" title="Valider">'
|
||||
+ '<?= icon('check-circle') ?>'
|
||||
+ '</button>'
|
||||
+ '<button type=\"button\" class=\"admin-icon-btn admin-icon-btn--delete\" onclick=\"tagsCancelRename(' + id + ')\" title=\"Annuler\">'
|
||||
+ '<?= icon("x-close") ?>'
|
||||
+ '<button type="button" class="admin-icon-btn admin-icon-btn--delete" onclick="tagsCancelRename(' + id + ')" title="Annuler">'
|
||||
+ '<?= icon('x-close') ?>'
|
||||
+ '</button></form>';
|
||||
cell.querySelector('input').focus();
|
||||
}
|
||||
|
||||
function tagsCancelRename(id) {
|
||||
var cell = document.getElementById('tag-name-' + id);
|
||||
cell.innerHTML = '<span class=\"tag-name-cell\">' + cell.getAttribute('data-name') + '</span>'
|
||||
+ '<button type=\"button\" class=\"admin-icon-btn admin-icon-btn--edit\" title=\"Renommer\" onclick=\"tagsStartRename(' + id + ')\">'
|
||||
+ '<?= icon("pencil-note") ?>'
|
||||
cell.innerHTML = '<span class="tag-name-cell">' + cell.getAttribute('data-name') + '</span>'
|
||||
+ '<button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer" onclick="tagsStartRename(' + id + ')">'
|
||||
+ '<?= icon('pencil-note') ?>'
|
||||
+ '</button>';
|
||||
}
|
||||
|
||||
function tagsConfirmDelete(btn, name) {
|
||||
_pendingTagForm = btn.closest('form');
|
||||
document.getElementById('delete-tag-name').textContent = name;
|
||||
document.getElementById('delete-tag-dialog').showModal();
|
||||
}
|
||||
|
||||
function _submitPendingTagForm() {
|
||||
if (_pendingTagForm) _pendingTagForm.submit();
|
||||
}
|
||||
|
||||
document.addEventListener('htmx:afterSwap', function(evt) {
|
||||
if (evt.target.id === 'tags-table-wrap') {
|
||||
document.querySelectorAll('input[name=\"selected_tags[]\"]').forEach(cb => cb.addEventListener('change', tagsUpdateBulk));
|
||||
tagsUpdateBulk();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<main id="main-content" class="admin-main--list">
|
||||
|
||||
Reference in New Issue
Block a user