- /forecast : une ligne par jalon, tous projets, triée par risque (écart décroissant), filtrable, ancres ms-<owner>-<repo> pointées par le bloc jalon des cartes du dashboard ; débit par projet conservé en tableau compact. - /health : tableau trié par sévérité (pastille, zombies, goulot) ; page détail : sélecteur de projet (health.js). - Tri des tableaux mutualisé dans static/js/tablesort.js (dashboard, forecast, health).
55 lines
2.2 KiB
JavaScript
55 lines
2.2 KiB
JavaScript
/**
|
|
* Kanbante — Flow health (issue #9): quick actions on zombie cards.
|
|
* Close/backlog reuse /api/move; the nudge reuses the comments API.
|
|
*/
|
|
(function () {
|
|
var csrf = (document.querySelector('meta[name="csrf-token"]') || {}).content || '';
|
|
|
|
/* Project switcher (0.19.0): jump between projects without
|
|
going back to the health index. */
|
|
var switcher = document.getElementById('health-switch');
|
|
if (switcher) {
|
|
switcher.addEventListener('change', function () {
|
|
window.location.href = '/health/' + switcher.value;
|
|
});
|
|
}
|
|
|
|
function post(url, fields) {
|
|
var data = new FormData();
|
|
Object.keys(fields).forEach(function (k) { data.append(k, fields[k]); });
|
|
data.append('csrf_token', csrf);
|
|
return fetch(url, { method: 'POST', body: data }).then(function (r) {
|
|
return r.json().catch(function () { return {}; }).then(function (body) {
|
|
if (!r.ok || body.ok === false) throw new Error(body.error || ('HTTP ' + r.status));
|
|
return body;
|
|
});
|
|
});
|
|
}
|
|
|
|
document.addEventListener('click', function (e) {
|
|
var btn = e.target.closest('[data-zombie]');
|
|
if (!btn) return;
|
|
var repo = btn.getAttribute('data-repo');
|
|
var number = btn.getAttribute('data-number');
|
|
var column = btn.getAttribute('data-column');
|
|
var action = btn.getAttribute('data-zombie');
|
|
var parts = repo.split('/');
|
|
btn.disabled = true;
|
|
var done = function () { location.reload(); };
|
|
var fail = function (err) { btn.disabled = false; alert(err.message); };
|
|
if (action === 'comment') {
|
|
post('/api/issues/' + parts[0] + '/' + parts[1] + '/' + number + '/comments', {
|
|
body: '🧟 Cette carte est inactive depuis un moment — toujours pertinent ?'
|
|
}).then(done).catch(fail);
|
|
} else {
|
|
post('/api/move', {
|
|
repo_full_name: repo,
|
|
issue_number: number,
|
|
from_column: column,
|
|
to_column: action === 'close' ? 'done' : 'backlog',
|
|
to_order: number
|
|
}).then(done).catch(fail);
|
|
}
|
|
});
|
|
})();
|