From e770ccf22b41643d86a4d491149b242b229feab8 Mon Sep 17 00:00:00 2001 From: perco Date: Tue, 19 May 2026 17:55:35 +0200 Subject: [PATCH] =?UTF-8?q?fix(planka):=20propagation=20erreurs=20Planka?= =?UTF-8?q?=20+=20noms=20=C3=A9tiquettes=20+=20position=20dans=20saveCard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - update_card: transmet position à Planka + retourne erreur réelle si Planka rejette - saveCard: n'envoie listId que si changé (position requise par Planka), sinon nom/desc/dueDate seul - Labels: affiche le nom en texte dans le badge coloré (comme Planka) Co-Authored-By: Claude Sonnet 4.6 --- modules/planka/api.php | 12 +++++++----- modules/planka/assets/planka.css | 16 ++++++++++++++-- planka.php | 23 +++++++++++++++-------- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/modules/planka/api.php b/modules/planka/api.php index 637ed1f..82b2f8c 100644 --- a/modules/planka/api.php +++ b/modules/planka/api.php @@ -127,12 +127,14 @@ if ($action === 'update_card') { $id = $_GET['id'] ?? null; if (!$id) tErr('ID manquant'); $d = tBody(); $payload = []; - if (isset($d['name'])) $payload['name'] = $d['name']; - if (isset($d['description'])) $payload['description'] = $d['description']; - if (array_key_exists('dueDate', $d)) $payload['dueDate'] = $d['dueDate']; - if (isset($d['listId'])) $payload['listId'] = $d['listId']; + if (isset($d['name'])) $payload['name'] = $d['name']; + if (isset($d['description'])) $payload['description'] = $d['description']; + if (array_key_exists('dueDate', $d)) $payload['dueDate'] = $d['dueDate']; + if (isset($d['listId'])) $payload['listId'] = $d['listId']; + if (isset($d['position'])) $payload['position'] = (float)$d['position']; $resp = planka_api('PATCH', '/api/cards/' . $id, $payload, $token); - tOk($resp['item'] ?? []); + if (empty($resp['item'])) tErr($resp['message'] ?? ($resp['problems'][0] ?? 'Planka a rejeté la mise à jour'), 502); + tOk($resp['item']); } if ($action === 'delete_card') { diff --git a/modules/planka/assets/planka.css b/modules/planka/assets/planka.css index 24d4cc2..d768a12 100644 --- a/modules/planka/assets/planka.css +++ b/modules/planka/assets/planka.css @@ -166,10 +166,22 @@ } .pk-label { + display: inline-flex; + align-items: center; + height: 20px; + padding: 0 8px; + border-radius: 4px; + font-size: .72rem; + font-weight: 600; + color: #fff; + white-space: nowrap; + text-shadow: 0 1px 2px rgba(0,0,0,.3); + min-width: 36px; +} +.pk-label:empty { height: 6px; width: 36px; - border-radius: 3px; - display: inline-block; + padding: 0; } .pk-card-name { diff --git a/planka.php b/planka.php index 59ed373..9162fe0 100644 --- a/planka.php +++ b/planka.php @@ -218,7 +218,7 @@ function renderCard(card, prevCard) { const labels = (state.cardLabels || []).filter(cl => cl.cardId === card.id).map(cl => { const lbl = (state.labels || []).find(l => l.id === cl.labelId); if (!lbl) return ''; - return ``; + return `${esc(lbl.name || '')}`; }).join(''); const cardTasks = (state.tasks || []).filter(t => t.cardId === card.id); const doneCount = cardTasks.filter(t => t.isCompleted).length; @@ -296,22 +296,29 @@ function closeCardModal() { async function saveCard() { if (!editingCard) return; - const name = document.getElementById('pk-card-name').value.trim(); + const name = document.getElementById('pk-card-name').value.trim(); if (!name) { showToast('Titre requis', 'error'); return; } - const due = document.getElementById('pk-card-due').value; - const body = { + const due = document.getElementById('pk-card-due').value; + const listId = document.getElementById('pk-card-list').value; + const body = { name, description: document.getElementById('pk-card-desc').value, dueDate: due ? due + 'T00:00:00.000Z' : null, - listId: document.getElementById('pk-card-list').value, }; + // Planka requires position whenever listId is sent — only include if list changed + if (listId !== editingCard.listId) { + body.listId = listId; + const targetCards = state.cards.filter(c => c.listId === listId); + const maxPos = targetCards.reduce((m, c) => Math.max(m, c.position || 0), 0); + body.position = maxPos + 65535; + } const res = await apiFetch('update_card', { id: editingCard.id }, 'PATCH', body); - if (!res.ok) { showToast('Erreur: ' + res.error, 'error'); return; } + if (!res.ok) { showToast('Erreur : ' + (res.error || 'sauvegarde impossible'), 'error'); return; } const idx = state.cards.findIndex(c => c.id === editingCard.id); - if (idx >= 0) state.cards[idx] = { ...state.cards[idx], ...res.data }; + if (idx >= 0) state.cards[idx] = { ...state.cards[idx], ...res.data, listId: listId }; closeCardModal(); renderBoard(); - showToast('Carte enregistrée'); + showToast('Carte enregistrée ✓'); } async function deleteCard() {