fix(admin/dashboard): restore layout BEFORE SortableJS init

- Reorder DOM elements from localStorage BEFORE initializing SortableJS
- Initialize Sortable AFTER layout restoration so it tracks correct DOM
- Add console.log for save/restore debugging
This commit is contained in:
NW
2026-07-06 19:22:22 +01:00
parent bc48334269
commit 1648336511

View File

@@ -435,10 +435,65 @@
// ===== SortableJS: Draggable Panels with localStorage =====
(function() {
var STORAGE_KEY = 'dashboardLayout';
var rows = document.querySelectorAll('.main-content > .row');
rows.forEach(function(row, rowIndex) {
// === STEP 1: Restore saved layout FIRST (before Sortable init) ===
var saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
try {
var layout = JSON.parse(saved);
console.log('[Dashboard] Restoring layout:', layout);
// Build flat map of all panels across all rows
var allCols = [];
rows.forEach(function(row) {
allCols = allCols.concat(Array.from(row.children));
});
var panelMap = {};
allCols.forEach(function(col) {
var panel = col.querySelector('.panel');
if (panel && panel.dataset.panelId) {
panelMap[panel.dataset.panelId] = col;
}
});
// Clear all rows first
rows.forEach(function(row) {
while (row.firstChild) {
row.removeChild(row.firstChild);
}
});
// Re-append columns into correct rows based on saved layout
rows.forEach(function(row, rowIndex) {
var order = layout['row' + rowIndex];
if (!order || !order.length) return;
order.forEach(function(panelId) {
var col = panelMap[panelId];
if (col) {
row.appendChild(col);
delete panelMap[panelId]; // mark as placed
}
});
});
// Any panels not placed (new or removed from layout) go back to first row
Object.values(panelMap).forEach(function(col) {
if (rows[0]) rows[0].appendChild(col);
});
console.log('[Dashboard] Layout restored successfully');
} catch(e) {
console.error('[Dashboard] Failed to restore layout:', e);
}
}
// === STEP 2: Initialize Sortable AFTER layout is restored ===
rows.forEach(function(row) {
new Sortable(row, {
group: 'dashboard-row-' + rowIndex,
group: 'dashboard-panels',
handle: '.panel-hdr',
animation: 150,
ghostClass: 'sortable-ghost',
@@ -450,34 +505,11 @@
return panel ? panel.dataset.panelId : null;
}).filter(Boolean);
});
localStorage.setItem('dashboardLayout', JSON.stringify(layout));
localStorage.setItem(STORAGE_KEY, JSON.stringify(layout));
console.log('[Dashboard] Layout saved:', layout);
}
});
});
// Restore saved layout
var saved = localStorage.getItem('dashboardLayout');
if (saved) {
try {
var layout = JSON.parse(saved);
rows.forEach(function(row, rowIndex) {
var order = layout['row' + rowIndex];
if (!order || !order.length) return;
var children = Array.from(row.children);
var panelMap = {};
children.forEach(function(col) {
var panel = col.querySelector('.panel');
if (panel && panel.dataset.panelId) {
panelMap[panel.dataset.panelId] = col;
}
});
order.forEach(function(panelId) {
var col = panelMap[panelId];
if (col) row.appendChild(col);
});
});
} catch(e) {}
}
})();
})();
</script>