Compare commits
3 Commits
2bc6c8c55d
...
144721585c
| Author | SHA1 | Date | |
|---|---|---|---|
| 144721585c | |||
| 54ecc548bc | |||
| a92b4d0f4c |
+123
-60
@@ -579,39 +579,53 @@ for ($h = $startHour; $h <= $endHour; $h++) {
|
|||||||
default => 'lg:col-span-6'
|
default => 'lg:col-span-6'
|
||||||
};
|
};
|
||||||
?>
|
?>
|
||||||
<div class="<?= $colClass ?> col-span-1 min-w-0 transition-all fociz-widget-wrapper group/widget" data-widget-id="<?= htmlspecialchars($wId) ?>" data-col-span="<?= $span ?>" id="widgetWrapper_<?= htmlspecialchars($wId) ?>">
|
<div class="<?= $colClass ?> col-span-1 min-w-0 transition-all duration-300 fociz-widget-wrapper group/widget" data-widget-id="<?= htmlspecialchars($wId) ?>" data-col-span="<?= $span ?>" id="widgetWrapper_<?= htmlspecialchars($wId) ?>">
|
||||||
<!-- Standardized In-Widget Control Toolbar -->
|
<!-- Bovenste rand van de widget: Prachtig gestyled en direct geïntegreerd in de widget -->
|
||||||
<div class="widget-toolbar flex items-center justify-between px-3 py-1.5 mb-2 rounded-xl bg-slate-100/80 dark:bg-[#0c0f17]/80 border border-slate-200/70 dark:border-slate-800/70 backdrop-blur-xs select-none shadow-2xs">
|
<div class="widget-header-bar flex items-center justify-between px-3.5 py-1.5 bg-slate-50/90 dark:bg-[#0c0f17]/90 border border-b-0 border-slate-200/80 dark:border-slate-800/80 rounded-t-2xl select-none backdrop-blur-xs transition-colors group-hover/widget:border-indigo-400/50 dark:group-hover/widget:border-indigo-500/30">
|
||||||
<div class="flex items-center space-x-2 min-w-0">
|
<!-- Links: Drag Handle Grip + Widget Titel -->
|
||||||
<div class="widget-drag-handle flex items-center space-x-1.5 px-2 py-1 rounded-lg cursor-grab active:cursor-grabbing text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-slate-200/60 dark:hover:bg-slate-800/80 transition" title="Sleep om te verplaatsen" draggable="true" data-widget-id="<?= htmlspecialchars($wId) ?>">
|
<div class="widget-drag-handle flex items-center space-x-1.5 cursor-grab active:cursor-grabbing text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 py-0.5 px-1 -ml-1 rounded-lg hover:bg-slate-200/50 dark:hover:bg-slate-800/50 transition group/drag" draggable="true" data-widget-id="<?= htmlspecialchars($wId) ?>" title="Sleep om te verplaatsen">
|
||||||
<i data-lucide="grip-vertical" class="w-3.5 h-3.5 flex-shrink-0"></i>
|
<i data-lucide="grip-vertical" class="w-3.5 h-3.5 text-slate-400 group-hover/drag:text-indigo-500 transition-colors flex-shrink-0"></i>
|
||||||
<span class="text-xs font-bold text-slate-700 dark:text-slate-200 truncate max-w-[130px] sm:max-w-[200px]"><?= htmlspecialchars($widget['title']) ?></span>
|
<span class="text-xs font-bold text-slate-700 dark:text-slate-300 tracking-wide truncate max-w-[160px] sm:max-w-[240px]"><?= htmlspecialchars($widget['title']) ?></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Rechts: Tandwieltje (Formaat & Verbergen) & Inklappen -->
|
||||||
|
<div class="flex items-center space-x-1 relative">
|
||||||
|
<!-- Tandwieltje Knop met Dropdown -->
|
||||||
|
<div class="relative">
|
||||||
|
<button type="button" onclick="toggleWidgetSettingsMenu('<?= $wId ?>', event)" class="widget-settings-btn p-1 rounded-lg text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 hover:bg-slate-200/60 dark:hover:bg-slate-800/60 transition cursor-pointer" title="Widget instellingen (formaat en verbergen)">
|
||||||
|
<i data-lucide="settings" class="w-3.5 h-3.5"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Dropdown Popover Menu -->
|
||||||
|
<div id="widgetSettingsMenu_<?= htmlspecialchars($wId) ?>" class="widget-settings-dropdown hidden absolute right-0 top-full mt-1.5 z-50 w-52 p-2.5 rounded-2xl bg-white/95 dark:bg-[#111624]/95 backdrop-blur-md border border-slate-200 dark:border-slate-800 shadow-2xl space-y-2.5">
|
||||||
|
<div>
|
||||||
|
<span class="text-[10px] font-bold uppercase tracking-wider text-slate-400 block mb-1.5">Breedte instellen</span>
|
||||||
|
<div class="grid grid-cols-4 gap-1">
|
||||||
|
<button type="button" onclick="setWidgetSpan('<?= $wId ?>', 4)" class="widget-span-btn py-1 text-center text-[11px] font-bold rounded-lg border transition cursor-pointer <?= $span == 4 ? 'bg-indigo-600 border-indigo-600 text-white shadow-2xs' : 'bg-slate-50 dark:bg-slate-800/80 border-slate-200 dark:border-slate-700 text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700' ?>" data-span="4" title="1/3 breedte (4 kolommen)">1/3</button>
|
||||||
|
<button type="button" onclick="setWidgetSpan('<?= $wId ?>', 6)" class="widget-span-btn py-1 text-center text-[11px] font-bold rounded-lg border transition cursor-pointer <?= $span == 6 ? 'bg-indigo-600 border-indigo-600 text-white shadow-2xs' : 'bg-slate-50 dark:bg-slate-800/80 border-slate-200 dark:border-slate-700 text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700' ?>" data-span="6" title="1/2 breedte (6 kolommen)">1/2</button>
|
||||||
|
<button type="button" onclick="setWidgetSpan('<?= $wId ?>', 8)" class="widget-span-btn py-1 text-center text-[11px] font-bold rounded-lg border transition cursor-pointer <?= $span == 8 ? 'bg-indigo-600 border-indigo-600 text-white shadow-2xs' : 'bg-slate-50 dark:bg-slate-800/80 border-slate-200 dark:border-slate-700 text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700' ?>" data-span="8" title="2/3 breedte (8 kolommen)">2/3</button>
|
||||||
|
<button type="button" onclick="setWidgetSpan('<?= $wId ?>', 12)" class="widget-span-btn py-1 text-center text-[11px] font-bold rounded-lg border transition cursor-pointer <?= $span == 12 ? 'bg-indigo-600 border-indigo-600 text-white shadow-2xs' : 'bg-slate-50 dark:bg-slate-800/80 border-slate-200 dark:border-slate-700 text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700' ?>" data-span="12" title="Volledige breedte (12 kolommen)">Vol</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center space-x-1 sm:space-x-1.5 flex-shrink-0">
|
<div class="pt-1.5 border-t border-slate-100 dark:border-slate-800/80">
|
||||||
<!-- Breedte Knoppen (Inline Resizing) -->
|
<button type="button" onclick="hideWidgetOnScreen('<?= $wId ?>')" class="w-full flex items-center space-x-2 px-2 py-1.5 rounded-xl text-slate-600 dark:text-slate-400 hover:text-rose-600 dark:hover:text-rose-400 hover:bg-rose-50 dark:hover:bg-rose-500/10 transition cursor-pointer text-left text-xs font-semibold">
|
||||||
<div class="widget-size-picker inline-flex items-center rounded-lg bg-white dark:bg-[#111624] border border-slate-200 dark:border-slate-800 p-0.5 shadow-2xs">
|
<i data-lucide="eye-off" class="w-3.5 h-3.5 flex-shrink-0"></i>
|
||||||
<button type="button" onclick="setWidgetSpan('<?= $wId ?>', 4)" class="widget-span-btn px-1.5 py-0.5 rounded text-[10px] font-bold transition <?= $span == 4 ? 'bg-indigo-600 text-white shadow-2xs' : 'text-slate-500 hover:text-slate-800 dark:hover:text-slate-200' ?>" data-span="4" title="1/3 breedte (4 kolommen)">1/3</button>
|
<span>Widget verbergen</span>
|
||||||
<button type="button" onclick="setWidgetSpan('<?= $wId ?>', 6)" class="widget-span-btn px-1.5 py-0.5 rounded text-[10px] font-bold transition <?= $span == 6 ? 'bg-indigo-600 text-white shadow-2xs' : 'text-slate-500 hover:text-slate-800 dark:hover:text-slate-200' ?>" data-span="6" title="1/2 breedte (6 kolommen)">1/2</button>
|
</button>
|
||||||
<button type="button" onclick="setWidgetSpan('<?= $wId ?>', 8)" class="widget-span-btn px-1.5 py-0.5 rounded text-[10px] font-bold transition <?= $span == 8 ? 'bg-indigo-600 text-white shadow-2xs' : 'text-slate-500 hover:text-slate-800 dark:hover:text-slate-200' ?>" data-span="8" title="2/3 breedte (8 kolommen)">2/3</button>
|
</div>
|
||||||
<button type="button" onclick="setWidgetSpan('<?= $wId ?>', 12)" class="widget-span-btn px-1.5 py-0.5 rounded text-[10px] font-bold transition <?= $span == 12 ? 'bg-indigo-600 text-white shadow-2xs' : 'text-slate-500 hover:text-slate-800 dark:hover:text-slate-200' ?>" data-span="12" title="Volledige breedte (12 kolommen)">Vol</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Collapse / Expand Toggle -->
|
<!-- Inklappen / Uitklappen Knop -->
|
||||||
<button type="button" onclick="toggleWidgetCollapse('<?= $wId ?>')" class="p-1 rounded-lg text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 hover:bg-slate-200/60 dark:hover:bg-slate-800/60 transition cursor-pointer" title="Inklappen / Uitklappen">
|
<button type="button" onclick="toggleWidgetCollapse('<?= $wId ?>')" class="p-1 rounded-lg text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 hover:bg-slate-200/60 dark:hover:bg-slate-800/60 transition cursor-pointer" title="Inklappen / Uitklappen">
|
||||||
<i data-lucide="chevron-up" class="w-3.5 h-3.5 widget-collapse-icon transition-transform duration-200" id="collapse_icon_<?= htmlspecialchars($wId) ?>"></i>
|
<i data-lucide="chevron-up" class="w-3.5 h-3.5 widget-collapse-icon transition-transform duration-200" id="collapse_icon_<?= htmlspecialchars($wId) ?>"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Verbergen -->
|
|
||||||
<button type="button" onclick="hideWidgetOnScreen('<?= $wId ?>')" class="p-1 rounded-lg text-slate-400 hover:text-rose-600 dark:hover:text-rose-400 hover:bg-rose-50 dark:hover:bg-rose-500/10 transition cursor-pointer" title="Verberg widget van dashboard">
|
|
||||||
<i data-lucide="eye-off" class="w-3.5 h-3.5"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Widget Content Body -->
|
<!-- Widget Content Body: sluit naadloos aan op de bovenste rand -->
|
||||||
<div class="widget-content-body transition-all duration-200" id="widget_body_<?= htmlspecialchars($wId) ?>">
|
<div class="widget-content-body transition-all duration-200 [&>.fociz-card]:rounded-t-none [&>.fociz-card]:border-t-0" id="widget_body_<?= htmlspecialchars($wId) ?>">
|
||||||
|
|
||||||
<?php if ($wId === 'daily_goal'): ?>
|
<?php if ($wId === 'daily_goal'): ?>
|
||||||
<!-- Widget 1: Dagfocus & Hoofddoel -->
|
<!-- Widget 1: Dagfocus & Hoofddoel -->
|
||||||
@@ -1970,14 +1984,14 @@ function setWidgetSpan(wId, span) {
|
|||||||
wrapper.classList.add(`lg:col-span-${span}`);
|
wrapper.classList.add(`lg:col-span-${span}`);
|
||||||
wrapper.setAttribute('data-col-span', span);
|
wrapper.setAttribute('data-col-span', span);
|
||||||
|
|
||||||
// Knoppen styling bijwerken binnen deze widget
|
// Knoppen styling bijwerken binnen het instellingen dropdown menu
|
||||||
const buttons = wrapper.querySelectorAll('.widget-span-btn');
|
const buttons = wrapper.querySelectorAll('.widget-span-btn');
|
||||||
buttons.forEach(btn => {
|
buttons.forEach(btn => {
|
||||||
const bSpan = parseInt(btn.getAttribute('data-span'), 10);
|
const bSpan = parseInt(btn.getAttribute('data-span'), 10);
|
||||||
if (bSpan === span) {
|
if (bSpan === span) {
|
||||||
btn.className = "widget-span-btn px-1.5 py-0.5 rounded text-[10px] font-bold transition bg-indigo-600 text-white shadow-2xs";
|
btn.className = "widget-span-btn py-1 text-center text-[11px] font-bold rounded-lg border transition cursor-pointer bg-indigo-600 border-indigo-600 text-white shadow-2xs";
|
||||||
} else {
|
} else {
|
||||||
btn.className = "widget-span-btn px-1.5 py-0.5 rounded text-[10px] font-bold transition text-slate-500 hover:text-slate-800 dark:hover:text-slate-200";
|
btn.className = "widget-span-btn py-1 text-center text-[11px] font-bold rounded-lg border transition cursor-pointer bg-slate-50 dark:bg-slate-800/80 border-slate-200 dark:border-slate-700 text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1987,6 +2001,9 @@ function setWidgetSpan(wId, span) {
|
|||||||
item.col_span = span;
|
item.col_span = span;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sluit het instellingen menu
|
||||||
|
document.getElementById(`widgetSettingsMenu_${wId}`)?.classList.add('hidden');
|
||||||
|
|
||||||
// Trigger resize voor SVG en diagrammen
|
// Trigger resize voor SVG en diagrammen
|
||||||
window.dispatchEvent(new Event('resize'));
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
|
||||||
@@ -2002,6 +2019,22 @@ function setWidgetSpan(wId, span) {
|
|||||||
showWidgetToast(`Formaat aangepast naar ${spanDescriptions[span] || span + ' kolommen'}`, 'success');
|
showWidgetToast(`Formaat aangepast naar ${spanDescriptions[span] || span + ' kolommen'}`, 'success');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Widget Instellingen Popover Menu (Tandwieltje) ---
|
||||||
|
function toggleWidgetSettingsMenu(wId, event) {
|
||||||
|
if (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
const menu = document.getElementById(`widgetSettingsMenu_${wId}`);
|
||||||
|
if (!menu) return;
|
||||||
|
const isCurrentlyHidden = menu.classList.contains('hidden');
|
||||||
|
// Sluit alle open menu's eerst
|
||||||
|
document.querySelectorAll('.widget-settings-dropdown').forEach(d => d.classList.add('hidden'));
|
||||||
|
if (isCurrentlyHidden) {
|
||||||
|
menu.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- Widget Inklappen / Uitklappen ---
|
// --- Widget Inklappen / Uitklappen ---
|
||||||
function toggleWidgetCollapse(wId) {
|
function toggleWidgetCollapse(wId) {
|
||||||
const body = document.getElementById(`widget_body_${wId}`);
|
const body = document.getElementById(`widget_body_${wId}`);
|
||||||
@@ -2023,6 +2056,7 @@ function toggleWidgetCollapse(wId) {
|
|||||||
|
|
||||||
// --- Widget Verbergen van Scherm met Undo Toast ---
|
// --- Widget Verbergen van Scherm met Undo Toast ---
|
||||||
function hideWidgetOnScreen(wId) {
|
function hideWidgetOnScreen(wId) {
|
||||||
|
document.getElementById(`widgetSettingsMenu_${wId}`)?.classList.add('hidden');
|
||||||
const wrapper = document.getElementById(`widgetWrapper_${wId}`) || document.querySelector(`.fociz-widget-wrapper[data-widget-id="${wId}"]`);
|
const wrapper = document.getElementById(`widgetWrapper_${wId}`) || document.querySelector(`.fociz-widget-wrapper[data-widget-id="${wId}"]`);
|
||||||
const item = focizWidgets.find(x => x.id === wId);
|
const item = focizWidgets.find(x => x.id === wId);
|
||||||
const title = item ? item.title : 'Widget';
|
const title = item ? item.title : 'Widget';
|
||||||
@@ -2056,9 +2090,9 @@ function undoHideWidget(wId) {
|
|||||||
}, 400);
|
}, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Direct On-Screen Drag & Drop Engine (HTML5 Native) ---
|
// --- Direct On-Screen Drag & Drop Engine (Live Shift & Reflow) ---
|
||||||
let draggedWidgetEl = null;
|
let draggedWidgetEl = null;
|
||||||
let dropPlaceholderEl = null;
|
let dragInitialIndex = -1;
|
||||||
|
|
||||||
function initPlannerWidgets() {
|
function initPlannerWidgets() {
|
||||||
const grid = document.getElementById('focizWidgetGrid');
|
const grid = document.getElementById('focizWidgetGrid');
|
||||||
@@ -2077,13 +2111,6 @@ function initPlannerWidgets() {
|
|||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!dropPlaceholderEl) {
|
|
||||||
dropPlaceholderEl = document.createElement('div');
|
|
||||||
dropPlaceholderEl.id = 'widgetDropPlaceholder';
|
|
||||||
dropPlaceholderEl.className = 'col-span-1 min-w-0 border-2 border-dashed border-indigo-400/80 dark:border-indigo-500/80 bg-indigo-50/50 dark:bg-indigo-950/40 rounded-2xl flex items-center justify-center p-8 text-xs font-bold text-indigo-600 dark:text-indigo-400 pointer-events-none transition-all duration-150';
|
|
||||||
dropPlaceholderEl.innerHTML = '<div class="flex items-center space-x-2"><i data-lucide="arrow-down-circle" class="w-4 h-4"></i><span>Laat los om hier te plaatsen</span></div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Luister naar drag handles
|
// Luister naar drag handles
|
||||||
document.querySelectorAll('.widget-drag-handle').forEach(handle => {
|
document.querySelectorAll('.widget-drag-handle').forEach(handle => {
|
||||||
handle.setAttribute('draggable', 'true');
|
handle.setAttribute('draggable', 'true');
|
||||||
@@ -2092,81 +2119,117 @@ function initPlannerWidgets() {
|
|||||||
const wrapper = handle.closest('.fociz-widget-wrapper');
|
const wrapper = handle.closest('.fociz-widget-wrapper');
|
||||||
if (!wrapper) return;
|
if (!wrapper) return;
|
||||||
draggedWidgetEl = wrapper;
|
draggedWidgetEl = wrapper;
|
||||||
|
|
||||||
|
// Bewaar beginpositie om te controleren op wijzigingen
|
||||||
|
const allWrappers = Array.from(grid.querySelectorAll('.fociz-widget-wrapper'));
|
||||||
|
dragInitialIndex = allWrappers.indexOf(draggedWidgetEl);
|
||||||
|
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
e.dataTransfer.effectAllowed = 'move';
|
||||||
e.dataTransfer.setData('text/plain', wrapper.getAttribute('data-widget-id'));
|
e.dataTransfer.setData('text/plain', wrapper.getAttribute('data-widget-id'));
|
||||||
|
|
||||||
// Match column span van dragged widget
|
// Sluit eventuele open popover menu's
|
||||||
const curSpan = wrapper.getAttribute('data-col-span') || '6';
|
document.querySelectorAll('.widget-settings-dropdown').forEach(d => d.classList.add('hidden'));
|
||||||
dropPlaceholderEl.className = `lg:col-span-${curSpan} col-span-1 min-w-0 border-2 border-dashed border-indigo-400/80 dark:border-indigo-500/80 bg-indigo-50/60 dark:bg-indigo-950/50 rounded-2xl flex items-center justify-center p-8 text-xs font-bold text-indigo-600 dark:text-indigo-400 pointer-events-none transition-all`;
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (draggedWidgetEl) {
|
if (draggedWidgetEl) {
|
||||||
draggedWidgetEl.classList.add('opacity-40', 'scale-[0.98]', 'ring-2', 'ring-indigo-500/50');
|
draggedWidgetEl.classList.add('opacity-40', 'scale-[0.98]', 'ring-2', 'ring-indigo-500/70', 'shadow-2xl');
|
||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
handle.ondragend = (e) => {
|
handle.ondragend = (e) => {
|
||||||
if (draggedWidgetEl) {
|
if (draggedWidgetEl) {
|
||||||
draggedWidgetEl.classList.remove('opacity-40', 'scale-[0.98]', 'ring-2', 'ring-indigo-500/50');
|
draggedWidgetEl.classList.remove('opacity-40', 'scale-[0.98]', 'ring-2', 'ring-indigo-500/70', 'shadow-2xl');
|
||||||
}
|
|
||||||
if (dropPlaceholderEl && dropPlaceholderEl.parentNode) {
|
|
||||||
dropPlaceholderEl.remove();
|
|
||||||
}
|
}
|
||||||
|
saveCurrentGridOrderIfChanged();
|
||||||
draggedWidgetEl = null;
|
draggedWidgetEl = null;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Dragover op grid
|
// Dragover op grid: verplaatst de widget live in het DOM zodat andere blokken direct opzij schuiven
|
||||||
grid.ondragover = (e) => {
|
grid.ondragover = (e) => {
|
||||||
if (!draggedWidgetEl) return;
|
if (!draggedWidgetEl) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.dataTransfer.dropEffect = 'move';
|
e.dataTransfer.dropEffect = 'move';
|
||||||
|
|
||||||
|
// Check of cursor onderaan het grid zweeft
|
||||||
|
const gridRect = grid.getBoundingClientRect();
|
||||||
|
if (e.clientY > gridRect.bottom - 40) {
|
||||||
|
if (grid.lastElementChild !== draggedWidgetEl) {
|
||||||
|
grid.appendChild(draggedWidgetEl);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check of cursor bovenaan het grid zweeft
|
||||||
|
if (e.clientY < gridRect.top + 40) {
|
||||||
|
if (grid.firstElementChild !== draggedWidgetEl) {
|
||||||
|
grid.prepend(draggedWidgetEl);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const target = e.target.closest('.fociz-widget-wrapper');
|
const target = e.target.closest('.fociz-widget-wrapper');
|
||||||
if (target && target !== draggedWidgetEl && target !== dropPlaceholderEl) {
|
if (target && target !== draggedWidgetEl && target.parentElement === grid) {
|
||||||
const rect = target.getBoundingClientRect();
|
const rect = target.getBoundingClientRect();
|
||||||
const isAfter = (e.clientY - rect.top) > (rect.height / 2) || (e.clientX - rect.left) > (rect.width / 2);
|
const midY = rect.top + rect.height / 2;
|
||||||
|
const midX = rect.left + rect.width / 2;
|
||||||
|
|
||||||
|
// Bepaal of de muis voorbij het midden is (verticaal of horizontaal in dezelfde rij)
|
||||||
|
const isAfter = (e.clientY > midY) || (Math.abs(e.clientY - midY) < rect.height * 0.35 && e.clientX > midX);
|
||||||
|
|
||||||
if (isAfter) {
|
if (isAfter) {
|
||||||
if (target.nextSibling !== dropPlaceholderEl) {
|
if (target.nextElementSibling !== draggedWidgetEl) {
|
||||||
target.after(dropPlaceholderEl);
|
target.after(draggedWidgetEl);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (target.previousSibling !== dropPlaceholderEl) {
|
if (target.previousElementSibling !== draggedWidgetEl) {
|
||||||
target.before(dropPlaceholderEl);
|
target.before(draggedWidgetEl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
grid.ondrop = (e) => {
|
grid.ondrop = (e) => {
|
||||||
if (!draggedWidgetEl) return;
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (dropPlaceholderEl && dropPlaceholderEl.parentNode) {
|
|
||||||
dropPlaceholderEl.replaceWith(draggedWidgetEl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (draggedWidgetEl) {
|
if (draggedWidgetEl) {
|
||||||
draggedWidgetEl.classList.remove('opacity-40', 'scale-[0.98]', 'ring-2', 'ring-indigo-500/50');
|
draggedWidgetEl.classList.remove('opacity-40', 'scale-[0.98]', 'ring-2', 'ring-indigo-500/70', 'shadow-2xl');
|
||||||
|
}
|
||||||
|
saveCurrentGridOrderIfChanged();
|
||||||
|
draggedWidgetEl = null;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Volgorde bijwerken
|
function saveCurrentGridOrderIfChanged() {
|
||||||
|
const grid = document.getElementById('focizWidgetGrid');
|
||||||
|
if (!grid) return;
|
||||||
const currentWrappers = Array.from(grid.querySelectorAll('.fociz-widget-wrapper'));
|
const currentWrappers = Array.from(grid.querySelectorAll('.fociz-widget-wrapper'));
|
||||||
|
const currentIndex = currentWrappers.indexOf(draggedWidgetEl);
|
||||||
|
|
||||||
|
let hasOrderChanged = false;
|
||||||
currentWrappers.forEach((el, index) => {
|
currentWrappers.forEach((el, index) => {
|
||||||
const wId = el.getAttribute('data-widget-id');
|
const wId = el.getAttribute('data-widget-id');
|
||||||
const item = focizWidgets.find(x => x.id === wId);
|
const item = focizWidgets.find(x => x.id === wId);
|
||||||
if (item) {
|
if (item) {
|
||||||
|
if (item.order !== index + 1) {
|
||||||
item.order = index + 1;
|
item.order = index + 1;
|
||||||
|
hasOrderChanged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (hasOrderChanged || (dragInitialIndex !== -1 && currentIndex !== dragInitialIndex)) {
|
||||||
persistWidgetLayoutAuto();
|
persistWidgetLayoutAuto();
|
||||||
showWidgetToast('Widget verplaatst & indeling opgeslagen', 'success');
|
showWidgetToast('Widget verplaatst & indeling opgeslagen', 'success');
|
||||||
|
|
||||||
draggedWidgetEl = null;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sluit popup menu's als er buiten wordt geklikt
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
if (!e.target.closest('.widget-settings-dropdown') && !e.target.closest('.widget-settings-btn')) {
|
||||||
|
document.querySelectorAll('.widget-settings-dropdown').forEach(d => d.classList.add('hidden'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// --- Jira Queue & Tickets Widget Engine (v2.0) ---
|
// --- Jira Queue & Tickets Widget Engine (v2.0) ---
|
||||||
const plannerJiraAssigned = <?= json_encode($jiraAssignedIssues, JSON_UNESCAPED_UNICODE) ?>;
|
const plannerJiraAssigned = <?= json_encode($jiraAssignedIssues, JSON_UNESCAPED_UNICODE) ?>;
|
||||||
|
|||||||
Reference in New Issue
Block a user