From fee376102192dc6f24297a7b11324636ace3a07d Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Tue, 30 Jun 2026 19:27:37 -0400 Subject: feat: admin gui object CRUD is much nicer --- internal/admin/static/editor.js | 66 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 6 deletions(-) (limited to 'internal/admin/static/editor.js') diff --git a/internal/admin/static/editor.js b/internal/admin/static/editor.js index d9ec36f..1ed0653 100644 --- a/internal/admin/static/editor.js +++ b/internal/admin/static/editor.js @@ -2,6 +2,8 @@ var editorType = ''; var editorFields = []; var currentID = null; var allIDs = []; +var treeData = { root: [], dirs: {} }; +var collapsedDirs = {}; function initEditor(type, fields) { editorType = type; @@ -13,7 +15,16 @@ function initEditor(type, fields) { function loadList() { API.get('/api/' + editorType).then(function(data) { - allIDs = data.ids || data || []; + if (Array.isArray(data)) { + treeData = { root: data, dirs: {} }; + allIDs = data.slice(); + } else { + treeData = { root: data.root || [], dirs: data.dirs || {} }; + allIDs = treeData.root.slice(); + Object.keys(treeData.dirs).sort().forEach(function(dir) { + Array.prototype.push.apply(allIDs, treeData.dirs[dir]); + }); + } renderList(''); }).catch(function(e) { notify('Failed to load list: ' + e.message, 'error'); @@ -22,11 +33,54 @@ function loadList() { function renderList(filter) { var el = $('#listEntries'); - var f = filter.toLowerCase(); - var filtered = allIDs.filter(function(id) { return !f || String(id).toLowerCase().indexOf(f) >= 0; }); - el.innerHTML = filtered.map(function(id) { - return '
' + esc(id) + '
'; - }).join(''); + var f = (filter || '').toLowerCase(); + + var html = ''; + var hasDirs = Object.keys(treeData.dirs).length > 0; + + if (treeData.root.length > 0 || !hasDirs) { + html += renderDirGroup(hasDirs ? 'Root' : '', treeData.root, f); + } + + if (hasDirs) { + Object.keys(treeData.dirs).sort().forEach(function(dir) { + html += renderDirGroup(dir, treeData.dirs[dir], f); + }); + } + + el.innerHTML = html; +} + +function renderDirGroup(name, ids, filter) { + if (ids.length === 0 && !filter) return ''; + var isFiltering = !!filter; + var displayIds = ids; + if (isFiltering) { + displayIds = ids.filter(function(id) { return String(id).toLowerCase().indexOf(filter) >= 0; }); + if (displayIds.length === 0) return ''; + } + var expanded = isFiltering ? true : (collapsedDirs[name] === false || (!name && collapsedDirs[''] === undefined)); + var displayName = name || editorType.charAt(0).toUpperCase() + editorType.slice(1); + var h = '
'; + if (name) { + h += '
'; + h += '' + (expanded ? '▼' : '▶') + ''; + h += '' + esc(displayName) + ''; + h += '' + (isFiltering ? displayIds.length + '/' + ids.length : ids.length) + ''; + h += '
'; + } + h += ''; + h += '
'; + return h; +} + +function toggleDir(name) { + collapsedDirs[name] = collapsedDirs[name] === false ? true : false; + renderList(''); } function filterList(val) { -- cgit v1.2.3