diff options
| author | historia <[not public]> | 2026-06-30 19:27:37 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-30 19:27:37 -0400 |
| commit | fee376102192dc6f24297a7b11324636ace3a07d (patch) | |
| tree | 6c777cc71208b429eebdbdc5864b353d4af34a09 /internal/admin/static/editor.js | |
| parent | 98bdef072c843fdd8ccdf85a9b54ab9d32d34187 (diff) | |
| download | thehouseoficarus-fee376102192dc6f24297a7b11324636ace3a07d.tar.gz | |
feat: admin gui object CRUD is much nicer
Diffstat (limited to 'internal/admin/static/editor.js')
| -rw-r--r-- | internal/admin/static/editor.js | 66 |
1 files changed, 60 insertions, 6 deletions
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 '<div class="item' + (id === currentID ? ' active' : '') + '" onclick="loadItem(\'' + esc(id) + '\')">' + esc(id) + '</div>'; - }).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 = '<div class="dir-group">'; + if (name) { + h += '<div class="dir-header" onclick="toggleDir(\'' + escAttr(name) + '\')">'; + h += '<span class="dir-arrow">' + (expanded ? '▼' : '▶') + '</span>'; + h += '<span class="dir-name">' + esc(displayName) + '</span>'; + h += '<span class="dir-count">' + (isFiltering ? displayIds.length + '/' + ids.length : ids.length) + '</span>'; + h += '</div>'; + } + h += '<div class="dir-items"' + (name && !expanded ? ' style="display:none"' : '') + '>'; + displayIds.forEach(function(id) { + h += '<div class="item' + (id === currentID ? ' active' : '') + '" onclick="loadItem(\'' + esc(id) + '\')">' + esc(id) + '</div>'; + }); + h += '</div>'; + h += '</div>'; + return h; +} + +function toggleDir(name) { + collapsedDirs[name] = collapsedDirs[name] === false ? true : false; + renderList(''); } function filterList(val) { |
