Ai aanpassingen en slepen in planner blokken
This commit is contained in:
+96
-5
@@ -164,13 +164,18 @@ html.dark #timelineGridWrapper::-webkit-scrollbar-thumb {
|
||||
<!-- LINKERPANEEL: 'Werk' Takenlijst & Snelle Invoer -->
|
||||
<div class="w-80 sm:w-96 border-r border-slate-200 dark:border-slate-800/80 flex flex-col flex-shrink-0 bg-white dark:bg-[#0c0f17]/90 z-20">
|
||||
|
||||
<!-- Werk Paneel Header -->
|
||||
<!-- Werk Paneel Header met Lane Drop Targets -->
|
||||
<div class="h-12 px-4 border-b border-slate-200/80 dark:border-slate-800/80 flex items-center justify-between bg-slate-50/70 dark:bg-slate-900/40">
|
||||
<div class="flex items-center space-x-2">
|
||||
<span class="text-xs font-bold text-slate-800 dark:text-slate-200 uppercase tracking-wider">Werk</span>
|
||||
<span id="workItemsCountBadge" class="px-2 py-0.5 rounded-full text-[10px] font-bold bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-400 border border-slate-200 dark:border-slate-700">0</span>
|
||||
</div>
|
||||
<div class="text-[11px] text-slate-400">Status & Datum</div>
|
||||
<div class="text-[11px] text-slate-400">Sleep taak naar lane / datum</div>
|
||||
</div>
|
||||
|
||||
<!-- Snelle Lane Drop Zone Balk (verschijnt subtiel of is altijd zichtbaar) -->
|
||||
<div id="timelineLaneDropBar" class="px-2.5 py-1.5 bg-slate-100/70 dark:bg-slate-900/60 border-b border-slate-200/60 dark:border-slate-800/60 flex items-center gap-1.5 overflow-x-auto text-[11px]">
|
||||
<!-- Dynamisch gevuld via renderTimelineLaneDropBar() -->
|
||||
</div>
|
||||
|
||||
<!-- Inline Snelle Taakinvoer: ⚡ Wat moet er gedaan worden? (Exact zoals Jira) -->
|
||||
@@ -528,6 +533,53 @@ function populateLaneFilter() {
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
}
|
||||
renderTimelineLaneDropBar();
|
||||
}
|
||||
|
||||
// Render drop targets voor snelle statuswijziging in het werkpaneel
|
||||
function renderTimelineLaneDropBar() {
|
||||
const bar = document.getElementById('timelineLaneDropBar');
|
||||
if (!bar) return;
|
||||
bar.innerHTML = '';
|
||||
|
||||
const lanes = (currentBoardData && currentBoardData.lanes) ? currentBoardData.lanes : [];
|
||||
if (lanes.length === 0) {
|
||||
bar.classList.add('hidden');
|
||||
return;
|
||||
}
|
||||
bar.classList.remove('hidden');
|
||||
|
||||
lanes.forEach(lane => {
|
||||
const dotColor = LANE_COLORS[lane.color] || 'bg-slate-500';
|
||||
const dropBadge = document.createElement('div');
|
||||
dropBadge.className = 'timeline-lane-target px-2.5 py-1 rounded-lg border border-slate-200/80 dark:border-slate-800 bg-white/80 dark:bg-slate-800/70 hover:bg-indigo-50 dark:hover:bg-indigo-950/40 text-slate-700 dark:text-slate-200 font-semibold text-[11px] flex items-center space-x-1.5 cursor-pointer transition flex-shrink-0 select-none shadow-2xs';
|
||||
dropBadge.setAttribute('data-lane-id', lane.id);
|
||||
dropBadge.title = `Sleep een taak hierheen om te verplaatsen naar: ${lane.title}`;
|
||||
dropBadge.innerHTML = `
|
||||
<span class="w-2 h-2 rounded-full ${dotColor}"></span>
|
||||
<span class="truncate max-w-[90px]">${escapeHtml(lane.title)}</span>
|
||||
`;
|
||||
|
||||
dropBadge.ondragover = (e) => {
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
dropBadge.classList.add('ring-2', 'ring-indigo-500', 'bg-indigo-100', 'dark:bg-indigo-900/60');
|
||||
};
|
||||
dropBadge.ondragleave = () => {
|
||||
dropBadge.classList.remove('ring-2', 'ring-indigo-500', 'bg-indigo-100', 'dark:bg-indigo-900/60');
|
||||
};
|
||||
dropBadge.ondrop = async (e) => {
|
||||
e.preventDefault();
|
||||
dropBadge.classList.remove('ring-2', 'ring-indigo-500', 'bg-indigo-100', 'dark:bg-indigo-900/60');
|
||||
const cardIdStr = e.dataTransfer.getData('text/plain');
|
||||
const cardId = parseInt(cardIdStr, 10);
|
||||
if (cardId && lane.id) {
|
||||
await moveTimelineCardToLane(cardId, lane.id);
|
||||
}
|
||||
};
|
||||
|
||||
bar.appendChild(dropBadge);
|
||||
});
|
||||
}
|
||||
|
||||
function populateModalDropdowns() {
|
||||
@@ -668,10 +720,26 @@ function renderTimeline() {
|
||||
const laneDotColor = LANE_COLORS[card.lane_color] || 'bg-slate-500';
|
||||
const hasSchedule = (card.start_date && card.end_date);
|
||||
|
||||
// 1. Linkerpaneel Item
|
||||
// 1. Linkerpaneel Item (draggable naar lane drop zones)
|
||||
const leftItem = document.createElement('div');
|
||||
leftItem.className = 'timeline-row h-12 px-3.5 flex items-center justify-between transition cursor-pointer hover:bg-slate-100/70 dark:hover:bg-slate-800/50';
|
||||
leftItem.onclick = () => openCardModal(card.id);
|
||||
leftItem.className = 'timeline-row h-12 px-3.5 flex items-center justify-between transition cursor-grab active:cursor-grabbing hover:bg-slate-100/70 dark:hover:bg-slate-800/50 group select-none';
|
||||
leftItem.setAttribute('draggable', 'true');
|
||||
leftItem.setAttribute('data-card-id', card.id);
|
||||
|
||||
leftItem.ondragstart = (e) => {
|
||||
e.dataTransfer.setData('text/plain', String(card.id));
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
leftItem.classList.add('opacity-50', 'bg-indigo-50/50', 'dark:bg-indigo-950/30');
|
||||
};
|
||||
leftItem.ondragend = () => {
|
||||
leftItem.classList.remove('opacity-50', 'bg-indigo-50/50', 'dark:bg-indigo-950/30');
|
||||
};
|
||||
|
||||
leftItem.onclick = (e) => {
|
||||
// Voorkom trigger als er net gedragged werd
|
||||
if (e.defaultPrevented) return;
|
||||
openCardModal(card.id);
|
||||
};
|
||||
|
||||
// Date badge
|
||||
let dateBadge = '<span class="text-[10px] text-slate-400 italic">Niet gepland</span>';
|
||||
@@ -858,6 +926,29 @@ async function updateCardDates(cardId, startDate, endDate) {
|
||||
}
|
||||
}
|
||||
|
||||
// API call om een taak direct naar een andere lane / statuscategorie te verplaatsen
|
||||
async function moveTimelineCardToLane(cardId, targetLaneId) {
|
||||
try {
|
||||
const res = await fetch('/api/board.php?action=move_card', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
card_id: cardId,
|
||||
target_lane_id: targetLaneId,
|
||||
target_position: 999
|
||||
})
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
await loadBoardData(currentBoardId);
|
||||
} else {
|
||||
alert(data.error || 'Kon taak niet verplaatsen');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Fout bij verplaatsen naar lane:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Verslepen van tijdlijnbalken
|
||||
function enableBarDragging(barEl, cardId, originalStart, originalEnd) {
|
||||
let isDragging = false;
|
||||
|
||||
Reference in New Issue
Block a user