aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/static
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-05 18:52:51 -0400
committerhistoria <[not public]>2026-07-05 18:52:51 -0400
commit6bd5365cc22f84c047c1585e3f54571af46f53e5 (patch)
tree72df0934c72baa1e31817d7db999832c6efb115f /internal/admin/static
parent9b54188970c51070d86f4c87e909ea7836c86f07 (diff)
downloadthehouseoficarus-6bd5365cc22f84c047c1585e3f54571af46f53e5.tar.gz
feat: renameable directories and files in admin gui
Diffstat (limited to 'internal/admin/static')
-rw-r--r--internal/admin/static/admin.css11
-rw-r--r--internal/admin/static/admin.js65
-rw-r--r--internal/admin/static/cardeditor.js6
-rw-r--r--internal/admin/static/dropeditor.js5
-rw-r--r--internal/admin/static/editor.js108
-rw-r--r--internal/admin/static/hazardeditor.js5
-rw-r--r--internal/admin/static/itemeditor.js17
-rw-r--r--internal/admin/static/mobeditor.js8
-rw-r--r--internal/admin/static/moduleeditor.js8
-rw-r--r--internal/admin/static/objecteditor.js23
-rw-r--r--internal/admin/static/techeditor.js2
11 files changed, 221 insertions, 37 deletions
diff --git a/internal/admin/static/admin.css b/internal/admin/static/admin.css
index 3c6aaa4..bef3589 100644
--- a/internal/admin/static/admin.css
+++ b/internal/admin/static/admin.css
@@ -231,6 +231,17 @@ g.ud-hover:hover text{font-weight:bold}
.cm-menu button:hover{background:var(--accent)}
.cm-menu button.danger{color:#f55}
.cm-menu button.danger:hover{background:var(--danger)}
+.rename-header{display:flex;align-items:center;gap:6px}
+.rename-header-text{margin-bottom:0!important;padding-bottom:0!important;border-bottom:none!important}
+.rename-pencil{font-size:14px;cursor:pointer;color:#888;padding:2px 4px;border-radius:3px;transition:color .15s,transform .15s}
+.rename-pencil:hover{color:#fff;transform:scale(1.1)}
+.rename-edit-row{display:flex;align-items:center;gap:4px}
+.rename-input{flex:1;padding:4px 8px;font-size:14px;font-weight:bold;background:var(--input-bg);color:var(--text);border:1px solid var(--accent);border-radius:3px;font-family:monospace}
+.rename-btn-confirm,.rename-btn-cancel{padding:2px 8px;font-size:13px;border-radius:3px;cursor:pointer;font-family:monospace;line-height:1}
+.rename-btn-confirm{background:var(--success);color:#fff;border:none}
+.rename-btn-cancel{background:var(--danger);color:#fff;border:none}
+.item-rename-input{padding:4px 6px;font-size:12px;background:var(--input-bg);color:var(--text);border:1px solid var(--accent);border-radius:3px;font-family:monospace;width:100%}
+
.panel-left{width:200px;background:var(--panel);border-right:1px solid var(--border);overflow-y:auto;display:flex;flex-direction:column;flex-shrink:0}
.panel-left .panel-header{font-size:11px;color:#aaa;text-transform:uppercase;letter-spacing:.5px;padding:12px 12px 8px;border-bottom:1px solid var(--border);flex-shrink:0}
.panel-left .dc-item{display:block;padding:6px 12px;font-size:11px;cursor:pointer;color:var(--text);border-bottom:1px solid rgba(255,255,255,.03);font-family:monospace}
diff --git a/internal/admin/static/admin.js b/internal/admin/static/admin.js
index f8e9d13..a6bb8b2 100644
--- a/internal/admin/static/admin.js
+++ b/internal/admin/static/admin.js
@@ -52,4 +52,69 @@ window.saveForm = function(url, data, msg) {
}).catch(function(e) { notify('Save failed: '+e.message, 'error'); });
};
+window.entityRename = function(type, oldID, newID) {
+ return API.post('/api/' + type + '/rename', {id: oldID, new_id: newID}).then(function(r) {
+ notify('Renamed ' + oldID + ' to ' + newID, 'success');
+ updateUndoBar();
+ return r;
+ });
+};
+
+window.renderRenameableHeader = function(label, id) {
+ var h = '<div class="rename-header">';
+ h += '<h2 class="rename-header-text">' + esc(label) + ': ' + esc(id) + '</h2>';
+ h += '<span class="rename-pencil" onclick="startHeaderRename(this,\'' + escAttr(id) + '\')" title="Rename">\u270E</span>';
+ h += '<div class="rename-edit-row" style="display:none"></div>';
+ h += '</div>';
+ return h;
+};
+
+window.handleHeaderRename = function(oldID, newID) {
+ var type = window.editorType || '';
+ if (!type) return;
+ entityRename(type, oldID, newID).then(function() {
+ window.currentID = newID;
+ var typeSingular = type.slice(0, -1) + 'ID';
+ if (window[typeSingular] !== undefined) window[typeSingular] = newID;
+ if (window.loadList) window.loadList();
+ if (window.loadItem) window.loadItem(newID);
+ }).catch(function(e) { notify('Rename failed: ' + e.message, 'error'); });
+};
+
+window.startHeaderRename = function(pencilEl, oldID) {
+ var header = pencilEl.parentElement;
+ var textSpan = header.querySelector('.rename-header-text');
+ var editRow = header.querySelector('.rename-edit-row');
+
+ textSpan.style.display = 'none';
+ pencilEl.style.display = 'none';
+ editRow.style.display = 'flex';
+ editRow.innerHTML = '<input class="rename-input" value="' + escAttr(oldID) + '" maxlength="128">' +
+ '<button class="btn btn-sm rename-btn-confirm" title="Confirm">\u2713</button>' +
+ '<button class="btn btn-sm rename-btn-cancel" title="Cancel">\u2717</button>';
+
+ var input = editRow.querySelector('.rename-input');
+ var confirmBtn = editRow.querySelector('.rename-btn-confirm');
+ var cancelBtn = editRow.querySelector('.rename-btn-cancel');
+
+ input.focus();
+ input.select();
+
+ function cancel() {
+ textSpan.style.display = '';
+ pencilEl.style.display = '';
+ editRow.style.display = 'none';
+ }
+
+ function confirm() {
+ var newID = input.value.trim();
+ if (!newID || newID === oldID) { cancel(); return; }
+ if (window.handleHeaderRename) handleHeaderRename(oldID, newID);
+ }
+
+ cancelBtn.onclick = cancel;
+ input.onkeydown = function(e) { if (e.key === 'Enter') confirm(); else if (e.key === 'Escape') cancel(); };
+ confirmBtn.onclick = confirm;
+};
+
document.addEventListener('DOMContentLoaded', function() { updateUndoBar(); });
diff --git a/internal/admin/static/cardeditor.js b/internal/admin/static/cardeditor.js
index 8ff5eaf..5e0c7cb 100644
--- a/internal/admin/static/cardeditor.js
+++ b/internal/admin/static/cardeditor.js
@@ -199,13 +199,13 @@ function ced_setPathInData(ed, dataPath, value) {
if (!ed || !dataPath) return;
var m = dataPath.match(/^(.+)\[(\d+)\]\.(.+)$/);
if (m) {
- if (!ed[m[1]]) ed[m[1]] = [];
- if (!ed[m[1]][m[2]]) ed[m[1]][m[2]] = {};
+ if (!ed[m[1]] || !Array.isArray(ed[m[1]])) return;
+ if (!ed[m[1]][m[2]]) return;
ed[m[1]][m[2]][m[3]] = value;
} else {
var m2 = dataPath.match(/^(.+)\.(.+)$/);
if (m2) {
- if (!ed[m2[1]]) ed[m2[1]] = {};
+ if (ed[m2[1]] === undefined || ed[m2[1]] === null) return;
ed[m2[1]][m2[2]] = value;
} else {
ed[dataPath] = value;
diff --git a/internal/admin/static/dropeditor.js b/internal/admin/static/dropeditor.js
index 8e463ec..c5da314 100644
--- a/internal/admin/static/dropeditor.js
+++ b/internal/admin/static/dropeditor.js
@@ -56,7 +56,7 @@ function loadDropEditor(id) {
function loadItem(id) { loadDropEditor(id); }
function renderDropEditor(id, data) {
- var html = '<h2>Drop Table: ' + esc(id) + '</h2>';
+ var html = renderRenameableHeader('Drop Table', id);
html += '<div class="tabs"><button class="tab active" onclick="switchTab(event,\'fields\')">Fields</button>';
html += '<button class="tab" onclick="switchTab(event,\'yaml\')">Raw YAML</button></div>';
@@ -155,9 +155,10 @@ function addArrayItem(cardID) {
function removeArrayItem(cardID, idx) {
var sec = DROP_SECTIONS.find(function(s) { return s.id === cardID; });
if (!sec || !sec.isArray) return;
+ ced_syncDOMToData(dropData);
var arr = dropData[sec.path] || [];
arr.splice(idx, 1);
- renderCurrent();
+ renderDropEditor(dropID, dropData);
}
function saveDrop() {
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();
diff --git a/internal/admin/static/hazardeditor.js b/internal/admin/static/hazardeditor.js
index a0610dc..ff2857d 100644
--- a/internal/admin/static/hazardeditor.js
+++ b/internal/admin/static/hazardeditor.js
@@ -66,7 +66,7 @@ function loadHazardEditor(id) {
function loadItem(id) { loadHazardEditor(id); }
function renderHazardEditor(id, data) {
- var html = '<h2>Hazard: ' + esc(id) + '</h2>';
+ var html = renderRenameableHeader('Hazard', id);
html += '<div class="tabs"><button class="tab active" onclick="switchTab(event,\'fields\')">Fields</button>';
html += '<button class="tab" onclick="switchTab(event,\'yaml\')">Raw YAML</button></div>';
@@ -156,9 +156,10 @@ function toggleCardWidth(id) {
function removeSection(id) {
var sec = HAZARD_SECTIONS.find(function(s) { return s.id === id; });
if (!sec) return;
+ ced_syncDOMToData(hazardData);
if (sec.fields) sec.fields.forEach(function(f) { delete hazardData[f[0]]; });
delete addedSections[id];
- renderCurrent();
+ renderHazardEditor(hazardID, hazardData);
}
function addSection() {
diff --git a/internal/admin/static/itemeditor.js b/internal/admin/static/itemeditor.js
index 5ffb0cb..ac76f94 100644
--- a/internal/admin/static/itemeditor.js
+++ b/internal/admin/static/itemeditor.js
@@ -174,7 +174,7 @@ function loadItemEditor(id) {
}
function renderItemEditor(id, data) {
- var html = '<h2>Item: ' + esc(id) + '</h2>';
+ var html = renderRenameableHeader('Item', id);
html += '<div class="tabs"><button class="tab active" onclick="switchTab(event,\'fields\')">Fields</button>';
html += '<button class="tab" onclick="switchTab(event,\'yaml\')">Raw YAML</button></div>';
@@ -460,8 +460,9 @@ function addEquipBlock(blockKey) {
}
function removeEquipBlock(blockKey) {
+ ced_syncDOMToData(itemData);
if (itemData.equipment) delete itemData.equipment[blockKey];
- renderCurrent();
+ renderItemEditor(itemID, itemData);
}
// =========================================================================
@@ -902,6 +903,7 @@ function toggleCardWidth(id) {
function removeSection(id) {
var sec = SECTIONS.find(function(s) { return s.id === id; });
if (!sec) return;
+ ced_syncDOMToData(itemData);
if (sec.path) {
delete itemData[sec.path];
} else {
@@ -910,7 +912,7 @@ function removeSection(id) {
if (sec.subtables) sec.subtables.forEach(function(st) { delete itemData[st.key]; });
}
delete addedSections[id];
- renderCurrent();
+ renderItemEditor(itemID, itemData);
}
function addSection() {
@@ -952,9 +954,10 @@ function addArrayItem(cardID) {
function removeArrayItem(cardID, idx) {
var sec = SECTIONS.find(function(s) { return s.id === cardID; });
if (!sec || !sec.isArray) return;
+ ced_syncDOMToData(itemData);
var arr = itemData[sec.path] || [];
arr.splice(idx, 1);
- renderCurrent();
+ renderItemEditor(itemID, itemData);
}
// =========================================================================
@@ -991,6 +994,7 @@ function addSubRow(cardID, subKey) {
function removeSubRow(cardID, subKey, idx) {
var sec = SECTIONS.find(function(s) { return s.id === cardID; });
if (!sec) return;
+ ced_syncDOMToData(itemData);
var p = cardPath(sec);
var sectionRoot = p ? (itemData[p] || {}) : itemData;
var raw = sectionRoot[subKey];
@@ -1004,7 +1008,7 @@ function removeSubRow(cardID, subKey, idx) {
}
arr.splice(idx, 1);
sectionRoot[subKey] = arr;
- renderCurrent();
+ renderItemEditor(itemID, itemData);
}
// =========================================================================
@@ -1044,13 +1048,14 @@ function addSubSubRow(cardID, subKey, rowIdx, subSubKey) {
function removeSubSubRow(cardID, subKey, rowIdx, subSubKey, subSubIdx) {
var sec = SECTIONS.find(function(s) { return s.id === cardID; });
if (!sec) return;
+ ced_syncDOMToData(itemData);
var p = cardPath(sec);
var sectionRoot = p ? (itemData[p] || {}) : itemData;
var arr = sectionRoot[subKey] || [];
if (rowIdx >= arr.length) return;
var subArr = arr[rowIdx][subSubKey] || [];
subArr.splice(subSubIdx, 1);
- renderCurrent();
+ renderItemEditor(itemID, itemData);
}
// =========================================================================
diff --git a/internal/admin/static/mobeditor.js b/internal/admin/static/mobeditor.js
index 73dd16b..debe7e0 100644
--- a/internal/admin/static/mobeditor.js
+++ b/internal/admin/static/mobeditor.js
@@ -149,7 +149,7 @@ function loadMob(id) {
}
function renderMobEditor(id, data) {
- var html = '<h2>Mob: ' + esc(id) + '</h2>';
+ var html = renderRenameableHeader('Mob', id);
html += '<div class="tabs"><button class="tab active" onclick="switchTab(event,\'fields\')">Fields</button>';
html += '<button class="tab" onclick="switchTab(event,\'yaml\')">Raw YAML</button></div>';
@@ -574,6 +574,7 @@ function toggleMobCardWidth(id) {
function removeMobSection(id) {
var sec = MOB_SECTIONS.find(function(s) { return s.id === id; });
if (!sec) return;
+ ced_syncDOMToData(mobData);
if (sec.path) {
delete mobData[sec.path];
} else {
@@ -582,7 +583,7 @@ function removeMobSection(id) {
if (sec.subtables) sec.subtables.forEach(function(st) { delete mobData[st.key]; });
}
delete addedSections[id];
- renderCurrent();
+ renderMobEditor(mobID, mobData);
}
function mobAddSection() {
@@ -635,8 +636,9 @@ function addMobSubRow(cardID, subKey) {
function removeMobSubRow(cardID, subKey, idx) {
var sec = MOB_SECTIONS.find(function(s) { return s.id === cardID; });
if (!sec) return;
+ ced_syncDOMToData(mobData);
ced_removeSubRow(sec, subKey, idx, mobData, mobCardPath);
- renderCurrent();
+ renderMobEditor(mobID, mobData);
}
function addMobLootRow(kind) {
diff --git a/internal/admin/static/moduleeditor.js b/internal/admin/static/moduleeditor.js
index f1fb0fd..5bcb7bc 100644
--- a/internal/admin/static/moduleeditor.js
+++ b/internal/admin/static/moduleeditor.js
@@ -67,7 +67,7 @@ function loadModuleEditor(id) {
function loadItem(id) { loadModuleEditor(id); }
function renderModuleEditor(id, data) {
- var html = '<h2>Module: ' + esc(id) + '</h2>';
+ var html = renderRenameableHeader('Module', id);
html += '<div class="tabs"><button class="tab active" onclick="switchTab(event,\'fields\')">Fields</button>';
html += '<button class="tab" onclick="switchTab(event,\'yaml\')">Raw YAML</button></div>';
@@ -187,11 +187,12 @@ function toggleCardWidth(id) {
function removeSection(id) {
var sec = MODULE_SECTIONS.find(function(s) { return s.id === id; });
if (!sec) return;
+ ced_syncDOMToData(moduleData);
if (sec.path) {
delete moduleData[sec.path];
}
delete addedSections[id];
- renderCurrent();
+ renderModuleEditor(moduleID, moduleData);
}
function addSection() {
@@ -227,9 +228,10 @@ function addArrayItem(cardID) {
function removeArrayItem(cardID, idx) {
var sec = MODULE_SECTIONS.find(function(s) { return s.id === cardID; });
if (!sec || !sec.isArray) return;
+ ced_syncDOMToData(moduleData);
var arr = moduleData[sec.path] || [];
arr.splice(idx, 1);
- renderCurrent();
+ renderModuleEditor(moduleID, moduleData);
}
function saveModule() {
diff --git a/internal/admin/static/objecteditor.js b/internal/admin/static/objecteditor.js
index f8ef18a..5444985 100644
--- a/internal/admin/static/objecteditor.js
+++ b/internal/admin/static/objecteditor.js
@@ -157,7 +157,7 @@ function loadObject(id) {
}
function renderObjectEditor(id, data) {
- var html = '<h2>Object: ' + esc(id) + '</h2>';
+ var html = renderRenameableHeader('Object', id);
html += '<div class="tabs"><button class="tab active" onclick="switchTab(event,\'fields\')">Fields</button>';
html += '<button class="tab" onclick="switchTab(event,\'yaml\')">Raw YAML</button></div>';
@@ -729,12 +729,13 @@ function addToolRow(secID, key) {
function removeToolRow(secID, key, idx) {
var sec = SECTIONS.find(function(s) { return s.id === secID; });
if (!sec) return;
+ ced_syncDOMToData(objectData);
var p = cardPath(sec);
var arr = objectData[p] && objectData[p][key];
if (!arr) return;
arr.splice(idx, 1);
if (arr.length === 0) delete objectData[p][key];
- renderCurrent();
+ renderObjectEditor(objectID, objectData);
}
function fetchToolTypes() {
@@ -760,12 +761,13 @@ function toggleCardWidth(id) {
function removeSection(id) {
var sec = SECTIONS.find(function(s) { return s.id === id; });
if (!sec) return;
+ ced_syncDOMToData(objectData);
if (sec.path) {
delete objectData[sec.path];
} else if (id === 'steal') {
delete objectData.steal;
}
- renderCurrent();
+ renderObjectEditor(objectID, objectData);
}
function addSection() {
@@ -812,9 +814,10 @@ function addArrayItem(cardID) {
function removeArrayItem(cardID, idx) {
var sec = SECTIONS.find(function(s) { return s.id === cardID; });
if (!sec || !sec.isArray) return;
+ ced_syncDOMToData(objectData);
var arr = objectData[sec.path] || [];
arr.splice(idx, 1);
- renderCurrent();
+ renderObjectEditor(objectID, objectData);
}
function addSubRow(cardID, subKey) {
@@ -837,10 +840,11 @@ function addSubRow(cardID, subKey) {
function removeSubRow(cardID, subKey, idx) {
var sec = SECTIONS.find(function(s) { return s.id === cardID; });
if (!sec) return;
+ ced_syncDOMToData(objectData);
var sectionRoot = objectData[sec.path || ''] || objectData;
var arr = sectionRoot[subKey] || [];
arr.splice(idx, 1);
- renderCurrent();
+ renderObjectEditor(objectID, objectData);
}
function addKVRow(cardID, subKey) {
@@ -884,10 +888,11 @@ function hideUseInterField(idx, key) {
window._useInterVis = window._useInterVis || {};
if (!window._useInterVis[idx]) window._useInterVis[idx] = {};
window._useInterVis[idx][key] = false;
+ ced_syncDOMToData(objectData);
if (objectData.use_interactions && objectData.use_interactions[idx]) {
objectData.use_interactions[idx][key] = '';
}
- renderCurrent();
+ renderObjectEditor(objectID, objectData);
}
function showCoreField(key) {
@@ -899,6 +904,7 @@ function showCoreField(key) {
function hideCoreField(key) {
window._coreVis = window._coreVis || {};
window._coreVis[key] = false;
+ ced_syncDOMToData(objectData);
if (key === 'aliases') {
objectData.aliases = [];
} else if (key === 'inroom_description') {
@@ -906,7 +912,7 @@ function hideCoreField(key) {
} else if (key === 'removal_item') {
objectData.removal_item = '';
}
- renderCurrent();
+ renderObjectEditor(objectID, objectData);
}
function showGuardMob() {
@@ -918,8 +924,9 @@ function showGuardMob() {
function hideGuardMob() {
window._stealVis = window._stealVis || {};
window._stealVis.guard_mob = false;
+ ced_syncDOMToData(objectData);
if (objectData.steal) objectData.steal.guard_mob = '';
- renderCurrent();
+ renderObjectEditor(objectID, objectData);
}
function toggleUseInterHelp() {
diff --git a/internal/admin/static/techeditor.js b/internal/admin/static/techeditor.js
index 70f881e..ffb2b7b 100644
--- a/internal/admin/static/techeditor.js
+++ b/internal/admin/static/techeditor.js
@@ -70,7 +70,7 @@ function loadTechEditor(id) {
function loadItem(id) { loadTechEditor(id); }
function renderTechEditor(id, data) {
- var html = '<h2>Tech: ' + esc(id) + '</h2>';
+ var html = renderRenameableHeader('Tech', id);
html += '<div class="tabs"><button class="tab active" onclick="switchTab(event,\'fields\')">Fields</button>';
html += '<button class="tab" onclick="switchTab(event,\'yaml\')">Raw YAML</button></div>';