This commit is contained in:
2026-06-08 22:31:02 +08:00
parent ad6403f3e4
commit 6c09beea43
7 changed files with 210 additions and 14 deletions

View File

@@ -104,6 +104,7 @@ const SharedCSS = `
}
.sidebar .nav-link:hover { background: #2a2d2e; }
.sidebar .nav-link.active { background: #094771; color: #fff; }
.sidebar .nav-link.dragging { opacity: 0.55; }
.nav-icon {
width: 28px;
height: 26px;
@@ -478,7 +479,7 @@ func navInitials(label string) string {
case "Mintegral Checker":
return "MiC"
case "Device Simulator":
return "SIM"
return "DS"
}
words := strings.Fields(label)
if len(words) == 0 {
@@ -512,7 +513,7 @@ func Page(activePath, title, body string) string {
if n.Beta {
label += `<span class="beta-pill">Beta</span>`
}
tabs.WriteString(`<button type="button" class="nav-link` + cls + `" data-path="` + n.Path + `" title="` + n.Label + `"><span class="nav-icon">` + navInitials(n.Label) + `</span><span class="nav-text">` + label + `</span></button>`)
tabs.WriteString(`<button type="button" class="nav-link` + cls + `" data-path="` + n.Path + `" draggable="` + boolAttr(n.Path != "/") + `" title="` + n.Label + `"><span class="nav-icon">` + navInitials(n.Label) + `</span><span class="nav-text">` + label + `</span></button>`)
}
betaButtonLabel := "Show beta"
@@ -552,10 +553,72 @@ document.getElementById('sidebarToggle').addEventListener('click', () => {
});
document.querySelectorAll('[data-path]').forEach((element) => {
element.addEventListener('click', () => {
if (element.dataset.dragging === 'true') {
element.dataset.dragging = 'false';
return;
}
const path = element.dataset.path;
if (path) window.location.href = path;
});
});
const TOOL_ORDER_KEY = 'hplToolbox.toolOrder.v1';
function getToolOrder() {
try {
const parsed = JSON.parse(localStorage.getItem(TOOL_ORDER_KEY) || '[]');
return Array.isArray(parsed) ? parsed.filter(path => typeof path === 'string') : [];
} catch {
return [];
}
}
function setToolOrder(paths) {
localStorage.setItem(TOOL_ORDER_KEY, JSON.stringify(paths));
}
function applyStoredToolOrder(container, selector) {
if (!container) return;
const order = getToolOrder();
if (!order.length) return;
const elements = Array.from(container.querySelectorAll(selector));
const byPath = new Map(elements.map(el => [el.dataset.path, el]));
const home = byPath.get('/');
const ordered = order.map(path => byPath.get(path)).filter(Boolean);
const orderedSet = new Set(ordered);
const remaining = elements.filter(el => el !== home && !orderedSet.has(el));
if (home) container.appendChild(home);
ordered.concat(remaining).forEach(el => container.appendChild(el));
}
function setupToolReorder(container, selector) {
if (!container) return;
applyStoredToolOrder(container, selector);
let dragged = null;
container.querySelectorAll(selector).forEach(element => {
if (element.dataset.path === '/') return;
element.addEventListener('dragstart', event => {
dragged = element;
element.classList.add('dragging');
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setData('text/plain', element.dataset.path || '');
});
element.addEventListener('dragend', () => {
element.classList.remove('dragging');
element.dataset.dragging = 'true';
dragged = null;
const paths = Array.from(container.querySelectorAll(selector))
.map(el => el.dataset.path)
.filter(path => path && path !== '/');
setToolOrder(paths);
setTimeout(() => { element.dataset.dragging = 'false'; }, 0);
});
element.addEventListener('dragover', event => {
event.preventDefault();
if (!dragged || dragged === element || element.dataset.path === '/') return;
const rect = element.getBoundingClientRect();
const after = event.clientY > rect.top + rect.height / 2;
container.insertBefore(dragged, after ? element.nextSibling : element);
});
});
}
setupToolReorder(document.querySelector('.sidebar-nav'), '.nav-link');
setupToolReorder(document.querySelector('.home-tools'), '.home-tool');
document.getElementById('betaToolsToggle').addEventListener('click', async (event) => {
const enabled = event.currentTarget.dataset.enabled === 'true';
await fetch('/api/betaTools', {