aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/static/editor.js
diff options
context:
space:
mode:
Diffstat (limited to 'internal/admin/static/editor.js')
-rw-r--r--internal/admin/static/editor.js108
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();