feat(dnd): default cards to sidebar on medium screens when no saved layout
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
## Changes 10/19/2025 (v1.5.2)
|
## Changes 10/19/2025 (v1.5.2)
|
||||||
|
|
||||||
fix(admin): modal bugs; chore(api): update ReDoc SRI; docs(openapi): add annotations + spec
|
fix(admin): modal bugs; chore(api): update ReDoc SRI; docs(openapi): add annotations + spec
|
||||||
|
feat(dnd): default cards to sidebar on medium screens when no saved layout
|
||||||
|
|
||||||
- adminPanel.js
|
- adminPanel.js
|
||||||
- Fix modal open/close reliability and stacking order
|
- Fix modal open/close reliability and stacking order
|
||||||
@@ -22,6 +23,10 @@ fix(admin): modal bugs; chore(api): update ReDoc SRI; docs(openapi): add annotat
|
|||||||
common responses, and shared components
|
common responses, and shared components
|
||||||
- Regenerate and commit openapi.json.dist
|
- Regenerate and commit openapi.json.dist
|
||||||
|
|
||||||
|
- Adds one-time responsive default in loadSidebarOrder() (uses layoutDefaultApplied_v1)
|
||||||
|
- Preserves existing sidebarOrder/headerOrder and small-screen behavior
|
||||||
|
- Keeps user changes persistent; no override once a layout exists
|
||||||
|
|
||||||
- public/js/adminPanel.js
|
- public/js/adminPanel.js
|
||||||
- public/css/style.css
|
- public/css/style.css
|
||||||
- public/api.php
|
- public/api.php
|
||||||
|
|||||||
@@ -5,33 +5,75 @@
|
|||||||
// It also includes functions to handle the drag-and-drop events, including mouse movements and drop zones.
|
// It also includes functions to handle the drag-and-drop events, including mouse movements and drop zones.
|
||||||
// It uses CSS classes to manage the appearance of the sidebar and header drop zones during drag-and-drop operations.
|
// It uses CSS classes to manage the appearance of the sidebar and header drop zones during drag-and-drop operations.
|
||||||
|
|
||||||
|
// ---- responsive defaults ----
|
||||||
|
const MEDIUM_MIN = 1205; // matches your small-screen cutoff
|
||||||
|
const MEDIUM_MAX = 1600; // tweak as you like
|
||||||
|
|
||||||
|
function isMediumScreen() {
|
||||||
|
const w = window.innerWidth;
|
||||||
|
return w >= MEDIUM_MIN && w < MEDIUM_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
// Moves cards into the sidebar based on the saved order in localStorage.
|
// Moves cards into the sidebar based on the saved order in localStorage.
|
||||||
export function loadSidebarOrder() {
|
export function loadSidebarOrder() {
|
||||||
const sidebar = document.getElementById('sidebarDropArea');
|
const sidebar = document.getElementById('sidebarDropArea');
|
||||||
if (!sidebar) return;
|
if (!sidebar) return;
|
||||||
const orderStr = localStorage.getItem('sidebarOrder');
|
|
||||||
if (orderStr) {
|
const orderStr = localStorage.getItem('sidebarOrder');
|
||||||
const order = JSON.parse(orderStr);
|
const headerOrderStr = localStorage.getItem('headerOrder');
|
||||||
if (order.length > 0) {
|
const defaultAppliedKey = 'layoutDefaultApplied_v1'; // bump the suffix if you ever change logic
|
||||||
// Ensure main wrapper is visible.
|
|
||||||
const mainWrapper = document.querySelector('.main-wrapper');
|
// If we have a saved order (sidebar or header), just honor it as before
|
||||||
if (mainWrapper) {
|
if (orderStr) {
|
||||||
mainWrapper.style.display = 'flex';
|
const order = JSON.parse(orderStr || '[]');
|
||||||
|
if (Array.isArray(order) && order.length > 0) {
|
||||||
|
const mainWrapper = document.querySelector('.main-wrapper');
|
||||||
|
if (mainWrapper) mainWrapper.style.display = 'flex';
|
||||||
|
order.forEach(id => {
|
||||||
|
const card = document.getElementById(id);
|
||||||
|
if (card && card.parentNode?.id !== 'sidebarDropArea') {
|
||||||
|
sidebar.appendChild(card);
|
||||||
|
animateVerticalSlide(card);
|
||||||
}
|
}
|
||||||
// For each saved ID, move the card into the sidebar.
|
});
|
||||||
order.forEach(id => {
|
updateSidebarVisibility();
|
||||||
const card = document.getElementById(id);
|
return;
|
||||||
if (card && card.parentNode.id !== 'sidebarDropArea') {
|
|
||||||
sidebar.appendChild(card);
|
|
||||||
// Animate vertical slide for sidebar card
|
|
||||||
animateVerticalSlide(card);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
updateSidebarVisibility();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No sidebar order saved yet: if user has header icons saved, do nothing (they've customized)
|
||||||
|
const headerOrder = JSON.parse(headerOrderStr || '[]');
|
||||||
|
if (Array.isArray(headerOrder) && headerOrder.length > 0) {
|
||||||
|
updateSidebarVisibility();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// One-time default: on medium screens, start cards in the sidebar
|
||||||
|
const alreadyApplied = localStorage.getItem(defaultAppliedKey) === '1';
|
||||||
|
if (!alreadyApplied && isMediumScreen()) {
|
||||||
|
const mainWrapper = document.querySelector('.main-wrapper');
|
||||||
|
if (mainWrapper) mainWrapper.style.display = 'flex';
|
||||||
|
|
||||||
|
const candidates = ['uploadCard', 'folderManagementCard'];
|
||||||
|
const moved = [];
|
||||||
|
candidates.forEach(id => {
|
||||||
|
const card = document.getElementById(id);
|
||||||
|
if (card && card.parentNode?.id !== 'sidebarDropArea') {
|
||||||
|
sidebar.appendChild(card);
|
||||||
|
animateVerticalSlide(card);
|
||||||
|
moved.push(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (moved.length) {
|
||||||
|
localStorage.setItem('sidebarOrder', JSON.stringify(moved));
|
||||||
|
localStorage.setItem(defaultAppliedKey, '1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSidebarVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function loadHeaderOrder() {
|
export function loadHeaderOrder() {
|
||||||
const headerDropArea = document.getElementById('headerDropArea');
|
const headerDropArea = document.getElementById('headerDropArea');
|
||||||
|
|||||||
Reference in New Issue
Block a user