list_starred/set_starred sur /user/starred (vérité dans la
forge), endpoint POST /api/projects/{o}/{r}/star (CSRF), section
Épinglés hors onglets, bouton étoile sur les cartes et bascule
sans rechargement; les épinglés sortent de leur grille d'onglet.
57 lines
2.4 KiB
JavaScript
57 lines
2.4 KiB
JavaScript
/**
|
|
* Kanbante — pin projects via Gitea stars (issue #20).
|
|
* The star lives in Gitea (source of truth); this only toggles it
|
|
* through the API and moves the card between the pinned section
|
|
* and its home tab grid, without a page reload.
|
|
*/
|
|
(function () {
|
|
var pinnedSection = document.getElementById('pinned-section');
|
|
var pinnedGrid = document.getElementById('pinned-grid');
|
|
|
|
function refreshPinnedVisibility() {
|
|
if (!pinnedSection || !pinnedGrid) return;
|
|
pinnedSection.hidden = pinnedGrid.querySelectorAll('.project-card').length === 0;
|
|
}
|
|
|
|
document.querySelectorAll('.star-btn').forEach(function (btn) {
|
|
btn.addEventListener('click', async function (e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
var full = btn.getAttribute('data-full');
|
|
var parts = full.split('/');
|
|
var want = btn.getAttribute('data-starred') !== '1';
|
|
btn.disabled = true;
|
|
try {
|
|
var fd = new FormData();
|
|
fd.append('starred', want ? '1' : '0');
|
|
fd.append('csrf_token', window.KANBANTE_CSRF || '');
|
|
var res = await fetch('/api/projects/' + parts[0] + '/' + parts[1] + '/star', {
|
|
method: 'POST', body: fd,
|
|
});
|
|
var data = await res.json();
|
|
if (!data.ok) throw new Error(data.error || 'échec');
|
|
btn.setAttribute('data-starred', want ? '1' : '0');
|
|
btn.textContent = want ? '⭐' : '☆';
|
|
btn.title = want ? 'Désépingler (étoile Gitea)' : 'Épingler (étoile Gitea)';
|
|
var card = btn.closest('.project-card');
|
|
if (card) {
|
|
if (want && pinnedGrid) {
|
|
pinnedGrid.appendChild(card);
|
|
} else {
|
|
var home = document.getElementById('grid-' + (card.getAttribute('data-home') || 'active'));
|
|
if (home) home.appendChild(card);
|
|
}
|
|
refreshPinnedVisibility();
|
|
}
|
|
} catch (err) {
|
|
btn.textContent = '⚠️';
|
|
setTimeout(function () {
|
|
btn.textContent = btn.getAttribute('data-starred') === '1' ? '⭐' : '☆';
|
|
}, 1600);
|
|
} finally {
|
|
btn.disabled = false;
|
|
}
|
|
});
|
|
});
|
|
})();
|