feat: ajouter classes sémantiques pour la page d'ajout de liens avec page-add-link, page-add-actions, page-add-bulk-toggle, batch-add-card, batch-private-wrap/checkbox/label pour meilleur ciblage CSS et suppression des styles inline

This commit is contained in:
Bruno Charest 2026-02-18 15:52:33 -05:00
parent 65dde10291
commit 6b1f4b3e28
4 changed files with 295 additions and 1864 deletions

View File

@ -4,7 +4,7 @@
{$pageName="addlink"} {$pageName="addlink"}
{include="includes"} {include="includes"}
</head> </head>
<body onload="document.addform.post.focus();"> <body class="page-add-link" onload="document.addform.post.focus();">
{include="page.header"} {include="page.header"}
<div id="headerform" class="page-add container"> <div id="headerform" class="page-add container">
<div class="row"> <div class="row">
@ -26,11 +26,11 @@
</div> </div>
<div class="col-md-6 col-md-offset-3"> <div class="col-md-6 col-md-offset-3">
<div style="text-align: right; margin-bottom: 1rem;"> <div class="page-add-actions text-right">
<button type="button" class="btn btn-secondary button-batch-addform"><i class="mdi mdi-playlist-plus" aria-hidden="true"></i>&nbsp;{'BULK CREATION'|t}</button> <button type="button" class="btn btn-secondary button-batch-addform page-add-bulk-toggle"><i class="mdi mdi-playlist-plus" aria-hidden="true"></i>&nbsp;{'BULK CREATION'|t}</button>
</div> </div>
<form class="card batch-addform hidden" method="POST" action="{$base_path}/admin/shaare-batch" name="batch-addform"> <form class="card batch-addform batch-add-card hidden" method="POST" action="{$base_path}/admin/shaare-batch" name="batch-addform">
<div class="card-header">{"Shaare multiple new links"|t}</div> <div class="card-header">{"Shaare multiple new links"|t}</div>
<div class="card-body"> <div class="card-body">
<div class="form-group"> <div class="form-group">
@ -44,9 +44,9 @@
</div> </div>
<input type="hidden" name="private" value="0"> <input type="hidden" name="private" value="0">
<div class="form-group checkbox-wrapper"> <div class="form-group checkbox-wrapper batch-private-wrap">
<input type="checkbox" name="private" {if="$default_private_links"} checked="checked"{/if} id="lf_private" style="width: auto;"/> <input type="checkbox" name="private" {if="$default_private_links"} checked="checked"{/if} id="lf_private" class="batch-private-checkbox" />
<label for="lf_private" style="margin: 0;">{'Private'|t}</label> <label for="lf_private" class="batch-private-label">{'Private'|t}</label>
</div> </div>
</div> </div>

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,8 @@
<div class="container"> <div class="container">
<div class="mbl row"> <div class="mbl row">
<div class="col-md-8 col-md-offset-2"> <div class="col-md-8 col-md-offset-2">
<div class="is-inverted"> <div class="is-inverted batch-progress-card">
<h2 class="batch-progress-title">{'Saving bookmarks'|t}</h2>
<div class="progress-counter"> <div class="progress-counter">
<span class="progress-current">0</span> / <span class="progress-total"></span> <span class="progress-current">0</span> / <span class="progress-total"></span>
</div> </div>
@ -26,8 +27,8 @@
</div> </div>
</div> </div>
<div class="text-center" style="margin: 1.5rem 0;"> <div class="batch-save-all-wrap text-center">
<button type="submit" name="save_edit_batch" class="btn btn-primary">{'Save all'|t}</button> <button type="submit" name="save_edit_batch" class="btn btn-primary batch-save-all-btn">{'Save all'|t}</button>
</div> </div>
{loop="$links"} {loop="$links"}
@ -35,8 +36,8 @@
{include="editlink"} {include="editlink"}
{/loop} {/loop}
<div class="text-center" style="margin: 1.5rem 0;"> <div class="batch-save-all-wrap text-center">
<button type="submit" name="save_edit_batch" class="btn btn-primary">{'Save all'|t}</button> <button type="submit" name="save_edit_batch" class="btn btn-primary batch-save-all-btn">{'Save all'|t}</button>
</div> </div>
{include="page.footer"} {include="page.footer"}

View File

@ -1411,7 +1411,115 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
} }
function initBatchCreationFlow() {
const batchToggleBtn = document.querySelector('.button-batch-addform');
const batchForm = document.querySelector('form.batch-addform');
if (batchToggleBtn && batchForm) {
batchToggleBtn.addEventListener('click', () => {
const isHidden = batchForm.classList.contains('hidden');
batchForm.classList.toggle('hidden');
batchToggleBtn.setAttribute('aria-expanded', isHidden ? 'true' : 'false');
if (isHidden) {
const urlsField = batchForm.querySelector('#urls');
urlsField?.focus();
}
});
}
const batchPage = document.querySelector('.page-edit-link-batch');
if (!batchPage) return;
const progressOverlay = document.getElementById('progress-overlay');
const progressCurrentEl = batchPage.querySelector('.progress-current');
const progressTotalEl = batchPage.querySelector('.progress-total');
const progressActualEl = batchPage.querySelector('.progress-actual');
const saveAllButtons = batchPage.querySelectorAll('button[name="save_edit_batch"]');
const getActiveBatchForms = () => Array.from(
batchPage.querySelectorAll('.bookmark-editor-form[data-batch-mode="1"]')
);
const updateProgress = (current, total) => {
if (progressCurrentEl) {
progressCurrentEl.textContent = String(current);
}
if (progressTotalEl) {
progressTotalEl.textContent = String(total);
}
if (progressActualEl) {
const percentage = total > 0 ? (current * 100) / total : 0;
progressActualEl.style.width = `${percentage}%`;
}
};
const initializeProgressTotal = () => {
const total = getActiveBatchForms().length;
updateProgress(0, total);
};
initializeProgressTotal();
batchPage.addEventListener('click', (event) => {
const cancelBtn = event.target.closest('button[name="cancel-batch-link"]');
if (!cancelBtn) return;
event.preventDefault();
const editForm = cancelBtn.closest('.editlinkform');
editForm?.remove();
initializeProgressTotal();
});
async function saveFormsSequentially(forms) {
const total = forms.length;
let current = 0;
updateProgress(0, total);
progressOverlay?.classList.remove('hidden');
for (const form of forms) {
const formData = new FormData(form);
try {
const response = await fetch(form.action || `${shaarli.basePath}/admin/shaare`, {
method: 'POST',
body: formData,
credentials: 'same-origin',
});
if (!response.ok) {
console.error('Batch save failed with status', response.status);
}
} catch (error) {
console.error('Batch save request failed', error);
}
current += 1;
updateProgress(current, total);
}
window.location.href = `${shaarli.basePath}/`;
}
saveAllButtons.forEach((button) => {
button.addEventListener('click', async (event) => {
event.preventDefault();
const forms = getActiveBatchForms();
if (!forms.length) return;
saveAllButtons.forEach((btn) => {
btn.disabled = true;
});
await saveFormsSequentially(forms);
});
});
}
initBookmarkEditorForms(); initBookmarkEditorForms();
initBatchCreationFlow();
// ===== Persistent Media Player (Popup via Blob URL) ===== // ===== Persistent Media Player (Popup via Blob URL) =====
// Audio plays in a separate popup window that survives page navigation. // Audio plays in a separate popup window that survives page navigation.