diff options
Diffstat (limited to 'internal/admin/static/editor.js')
| -rw-r--r-- | internal/admin/static/editor.js | 108 |
1 files changed, 99 insertions, 9 deletions
diff --git a/internal/admin/static/editor.js b/internal/admin/static/editor.js index 5b2d8ef..a9c1e1c 100644 --- a/internal/admin/static/editor.js +++ b/internal/admin/static/editor.js @@ -71,7 +71,7 @@ function renderDirGroup(name, ids, filter) { } h += '<div class="dir-items"' + (name && !expanded ? ' style="display:none"' : '') + ' ondragover="dirDragOver(event,\'' + (name || '') + '\')" ondragleave="dirDragLeave(event)" ondrop="dirDrop(event,\'' + (name || '') + '\')">'; displayIds.forEach(function(id) { - h += '<div class="item' + (id === currentID ? ' active' : '') + '" onclick="loadItem(\'' + esc(id) + '\')" draggable="true" ondragstart="itemDragStart(event,\'' + escAttr(id) + '\')">' + esc(id) + '</div>'; + h += '<div class="item' + (id === currentID ? ' active' : '') + '" onclick="loadItem(\'' + esc(id) + '\')" draggable="true" ondragstart="itemDragStart(event,\'' + escAttr(id) + '\')" oncontextmenu="showItemContextMenu(event,\'' + escAttr(id) + '\')">' + esc(id) + '</div>'; }); h += '</div>'; h += '</div>'; @@ -272,33 +272,123 @@ function createNewDir() { function showDirContextMenu(e, dir) { e.preventDefault(); + closeContextMenu(); if (dir === 'Root') return; var overlay = document.createElement('div'); overlay.className = 'cm-overlay'; - overlay.onclick = function() { overlay.remove(); menu.remove(); }; + overlay.id = '_ctxMenuOverlay'; + overlay.onclick = function() { closeContextMenu(); }; var menu = document.createElement('div'); menu.className = 'cm-menu'; + menu.id = '_ctxMenu'; 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(); + function addBtn(label, cls, handler) { + var btn = document.createElement('button'); + btn.textContent = label; + if (cls) btn.className = cls; + btn.onclick = function() { closeContextMenu(); handler(); }; + menu.appendChild(btn); + } + + addBtn('Rename Directory', '', function() { renameDirInline(dir); }); + addBtn('Delete Directory', 'danger', function() { 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 renameDirInline(dir) { + var name = prompt('New name for directory "' + dir + '":', dir); + if (!name || name === dir) return; + API.post('/api/' + editorType + '/dirs', {action: 'rename_dir', dir: dir, new_name: name}).then(function() { + notify('Renamed directory ' + dir + ' to ' + name, 'success'); + loadList(); + }).catch(function(e) { notify('Rename failed: ' + e.message, 'error'); }); +} + +function showItemContextMenu(e, id) { + e.preventDefault(); + e.stopPropagation(); + closeContextMenu(); + + var overlay = document.createElement('div'); + overlay.className = 'cm-overlay'; + overlay.id = '_ctxMenuOverlay'; + overlay.onclick = function() { closeContextMenu(); }; + + var menu = document.createElement('div'); + menu.className = 'cm-menu'; + menu.id = '_ctxMenu'; + menu.style.left = e.clientX + 'px'; + menu.style.top = e.clientY + 'px'; + + function addBtn(label, cls, handler) { + var btn = document.createElement('button'); + btn.textContent = label; + if (cls) btn.className = cls; + btn.onclick = function() { closeContextMenu(); handler(); }; + menu.appendChild(btn); + } + + addBtn('Rename', '', function() { startInlineItemRename(id); }); + addBtn('Delete', 'danger', function() { deleteItem(id); }); + + document.body.appendChild(overlay); + document.body.appendChild(menu); +} + +function closeContextMenu() { + var o = document.getElementById('_ctxMenuOverlay'); + var m = document.getElementById('_ctxMenu'); + if (o) o.remove(); + if (m) m.remove(); +} + +function startInlineItemRename(id) { + var el = document.querySelector('.item.active'); + if (!el) return; + var origHTML = el.innerHTML; + el.innerHTML = '<input class="item-rename-input" value="' + escAttr(id) + '" maxlength="128">'; + var input = el.querySelector('.item-rename-input'); + input.focus(); + input.select(); + + function finish(newID) { + newID = (newID || '').trim(); + if (!newID || newID === id) { el.innerHTML = origHTML; return; } + if (allIDs.indexOf(newID) >= 0) { + notify('An entity named "' + newID + '" already exists.', 'error'); + el.innerHTML = origHTML; + return; + } + entityRename(editorType, id, newID).then(function() { + if (currentID === id) currentID = newID; + var typeIDVar = editorType.slice(0, -1) + 'ID'; + if (window[typeIDVar] === id) window[typeIDVar] = newID; + loadList(); + if (currentID === newID) loadItem(newID); + }).catch(function(e) { + notify('Rename failed: ' + e.message, 'error'); + el.innerHTML = origHTML; + }); + } + + input.onkeydown = function(e) { + if (e.key === 'Enter') { input.blur(); } + else if (e.key === 'Escape') { el.innerHTML = origHTML; } + }; + input.onblur = function() { finish(input.value); }; +} + function dirDragOver(e, dir) { e.preventDefault(); e.stopPropagation(); |
