From 4385244d39b37d003dbb7a66a2ff3b05079b7047 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Sat, 4 Jul 2026 23:04:00 -0400 Subject: feat: drag/drop files in gui to change directories --- internal/admin/static/editor.js | 82 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 8 deletions(-) (limited to 'internal/admin/static/editor.js') diff --git a/internal/admin/static/editor.js b/internal/admin/static/editor.js index 35bdbe6..5b2d8ef 100644 --- a/internal/admin/static/editor.js +++ b/internal/admin/static/editor.js @@ -52,7 +52,7 @@ function renderList(filter) { } function renderDirGroup(name, ids, filter) { - if (ids.length === 0 && !filter) return ''; + if (ids.length === 0 && !filter && !name) return ''; var isFiltering = !!filter; var displayIds = ids; if (isFiltering) { @@ -63,15 +63,15 @@ function renderDirGroup(name, ids, filter) { var displayName = name || editorType.charAt(0).toUpperCase() + editorType.slice(1); var h = '
'; if (name) { - h += '
'; + h += '
'; h += '' + (expanded ? '▼' : '▶') + ''; h += '' + esc(displayName) + ''; h += '' + (isFiltering ? displayIds.length + '/' + ids.length : ids.length) + ''; h += '
'; } - h += ''; @@ -236,8 +236,7 @@ window.refreshPage = function() { loadList(); if (currentID) loadItem(currentID) function renderMoveBar() { var dirs = Object.keys(treeData.dirs).sort(); - var html = '
'; - html += ''; html += ''; html += ''; dirs.forEach(function(dir) { @@ -245,7 +244,6 @@ function renderMoveBar() { }); html += ''; html += ''; - html += '
'; return html; } @@ -254,7 +252,6 @@ function moveToDirectory() { var idx = sel.selectedIndex; if (idx === 0) return; var dir = sel.value; - if (!confirm('Move ' + currentID + ' to ' + (dir || 'Root') + '?')) return; API.post('/api/' + editorType + '/move', {id: currentID, dir: dir}).then(function() { notify('Moved ' + currentID + ' to ' + (dir || 'Root'), 'success'); updateUndoBar(); @@ -262,3 +259,72 @@ function moveToDirectory() { loadItem(currentID); }).catch(function(e) { notify('Move failed: ' + e.message, 'error'); }); } + +function createNewDir() { + var name = prompt('New directory name:'); + if (!name) return; + API.post('/api/' + editorType + '/dirs', {action: 'create', name: name}).then(function() { + notify('Directory ' + name + ' created', 'success'); + updateUndoBar(); + loadList(); + }).catch(function(e) { notify('Failed to create directory: ' + e.message, 'error'); }); +} + +function showDirContextMenu(e, dir) { + e.preventDefault(); + if (dir === 'Root') return; + var overlay = document.createElement('div'); + overlay.className = 'cm-overlay'; + overlay.onclick = function() { overlay.remove(); menu.remove(); }; + + var menu = document.createElement('div'); + menu.className = 'cm-menu'; + menu.style.left = e.clientX + 'px'; + menu.style.top = e.clientY + 'px'; + + var delBtn = document.createElement('button'); + delBtn.textContent = 'Delete Directory'; + delBtn.className = 'danger'; + delBtn.onclick = function() { + overlay.remove(); menu.remove(); + API.post('/api/' + editorType + '/dirs', {action: 'delete', dir: dir}).then(function(r) { + notify('Deleted directory ' + dir + (r.moved ? ' (' + r.moved + ' files moved to root)' : ''), 'success'); + updateUndoBar(); + loadList(); + }).catch(function(e) { notify('Delete failed: ' + e.message, 'error'); }); + }; + menu.appendChild(delBtn); + + document.body.appendChild(overlay); + document.body.appendChild(menu); +} + +function dirDragOver(e, dir) { + e.preventDefault(); + e.stopPropagation(); + e.currentTarget.classList.add('dir-drop-target'); +} + +function dirDragLeave(e) { + e.currentTarget.classList.remove('dir-drop-target'); +} + +function dirDrop(e, dir) { + e.preventDefault(); + e.stopPropagation(); + e.currentTarget.classList.remove('dir-drop-target'); + if (dir === 'Root') dir = ''; + var id = e.dataTransfer.getData('text/plain'); + if (!id) return; + API.post('/api/' + editorType + '/move', {id: id, dir: dir}).then(function() { + notify('Moved ' + id + ' to ' + (dir || 'Root'), 'success'); + updateUndoBar(); + loadList(); + if (currentID === id) loadItem(id); + }).catch(function(e) { notify('Move failed: ' + e.message, 'error'); }); +} + +function itemDragStart(e, id) { + e.dataTransfer.setData('text/plain', id); + e.dataTransfer.effectAllowed = 'move'; +} -- cgit v1.2.3