98 lines
3.5 KiB
JavaScript
98 lines
3.5 KiB
JavaScript
(function (global) {
|
|
var WIDGET_META = {
|
|
kpis: { title: 'CEO KPI\'s', icon: '📊' },
|
|
executive: { title: 'Alles op een rij', icon: '📋' },
|
|
briefing: { title: 'Herman briefing', icon: '📝' },
|
|
retail: { title: 'Retail operatie', icon: '🏪' },
|
|
analytics: { title: 'Data & analytics', icon: '📈' },
|
|
approvals: { title: 'Agent goedkeuringen', icon: '✓' },
|
|
feed: { title: 'Agent feed', icon: '⚡' },
|
|
};
|
|
|
|
function loadPrefs() {
|
|
return fetch('/api/preferences/ui').then(function (r) { return r.json(); }).catch(function () {
|
|
return { dashboard_layout: Object.keys(WIDGET_META), global_viz_mode: 'neo-bars', viz_modes: {} };
|
|
});
|
|
}
|
|
|
|
function saveLayout(order) {
|
|
return fetch('/api/preferences/ui', {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ dashboard_layout: order }),
|
|
});
|
|
}
|
|
|
|
function saveViz(globalMode, vizModes) {
|
|
return fetch('/api/preferences/ui', {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ global_viz_mode: globalMode, viz_modes: vizModes || {} }),
|
|
});
|
|
}
|
|
|
|
function applyOrder(container, order) {
|
|
if (!container) return;
|
|
var map = {};
|
|
Array.from(container.children).forEach(function (el) {
|
|
if (el.dataset && el.dataset.widget) map[el.dataset.widget] = el;
|
|
});
|
|
order.forEach(function (id) {
|
|
if (map[id]) container.appendChild(map[id]);
|
|
});
|
|
}
|
|
|
|
function initDrag(container, onReorder) {
|
|
if (!container) return;
|
|
var dragEl = null;
|
|
Array.from(container.querySelectorAll('[data-widget]')).forEach(function (el) {
|
|
el.setAttribute('draggable', 'true');
|
|
el.classList.add('hm-widget-draggable');
|
|
el.addEventListener('dragstart', function (ev) {
|
|
dragEl = el;
|
|
el.classList.add('hm-widget-dragging');
|
|
ev.dataTransfer.effectAllowed = 'move';
|
|
});
|
|
el.addEventListener('dragend', function () {
|
|
el.classList.remove('hm-widget-dragging');
|
|
dragEl = null;
|
|
var order = Array.from(container.querySelectorAll('[data-widget]')).map(function (n) { return n.dataset.widget; });
|
|
if (onReorder) onReorder(order);
|
|
});
|
|
el.addEventListener('dragover', function (ev) {
|
|
ev.preventDefault();
|
|
if (!dragEl || dragEl === el) return;
|
|
var rect = el.getBoundingClientRect();
|
|
var after = ev.clientY > rect.top + rect.height / 2;
|
|
if (after) el.after(dragEl); else el.before(dragEl);
|
|
});
|
|
});
|
|
}
|
|
|
|
function buildVizSelector(container, prefs, onChange) {
|
|
if (!container || !global.VizEngine) return;
|
|
container.innerHTML = '<label class="viz-global-label">Visualisatie:</label>' +
|
|
global.VizEngine.MODES.map(function (m) {
|
|
var active = prefs.global_viz_mode === m.id ? ' active' : '';
|
|
return '<button type="button" class="viz-mode-btn' + active + '" data-viz="' + m.id + '">' + m.label + '</button>';
|
|
}).join('');
|
|
container.querySelectorAll('.viz-mode-btn').forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
container.querySelectorAll('.viz-mode-btn').forEach(function (b) { b.classList.remove('active'); });
|
|
btn.classList.add('active');
|
|
if (onChange) onChange(btn.dataset.viz);
|
|
});
|
|
});
|
|
}
|
|
|
|
global.DashboardLayout = {
|
|
WIDGET_META: WIDGET_META,
|
|
loadPrefs: loadPrefs,
|
|
saveLayout: saveLayout,
|
|
saveViz: saveViz,
|
|
applyOrder: applyOrder,
|
|
initDrag: initDrag,
|
|
buildVizSelector: buildVizSelector,
|
|
};
|
|
})(window);
|