From 5ea48c1f91298b42924f6865ffc30810cceec2d3 Mon Sep 17 00:00:00 2001
From: historia <[not public]>
Date: Mon, 13 Jul 2026 20:36:26 -0400
Subject: feat(admin): triggers organized by directory, support duplicate and
delete
---
internal/admin/static/triggerseditor.js | 165 ++++++++++++++++++++++++++++----
1 file changed, 146 insertions(+), 19 deletions(-)
(limited to 'internal/admin/static/triggerseditor.js')
diff --git a/internal/admin/static/triggerseditor.js b/internal/admin/static/triggerseditor.js
index 7cb5d9e..0c18ce4 100644
--- a/internal/admin/static/triggerseditor.js
+++ b/internal/admin/static/triggerseditor.js
@@ -19,31 +19,80 @@ function initTriggerEditor() {
}
function loadTriggerList() {
- API.get('/api/triggers').then(function(data) {
- allIDs = (data || []).map(function(e) { return e.id || e; });
- window._triggerEntries = data || [];
- renderTriggerList('');
- }).catch(function(e) {
- notify('Failed to load list: ' + e.message, 'error');
- });
+ loadList();
}
function renderTriggerList(filter) {
+ renderList(filter);
+}
+
+function renderList(filter) {
var el = $('#listEntries');
var f = (filter || '').toLowerCase();
- var entries = window._triggerEntries || [];
+ var t = treeData;
+
+ function filterIDs(ids) {
+ if (!f) return ids;
+ return ids.filter(function(id) { return String(id).toLowerCase().indexOf(f) >= 0; });
+ }
+
+ function renderItems(ids) {
+ var h = '';
+ (ids || []).forEach(function(id) {
+ h += '
' + esc(id) + '
';
+ });
+ return h;
+ }
+
var html = '';
- entries.forEach(function(entry) {
- var id = entry.id || entry;
- if (f && id.toLowerCase().indexOf(f) === -1) return;
- var badge = entry.kind === 'player' ? ' [Player]' : (entry.kind === 'global' ? ' [Global]' : '');
- var badgeClass = entry.kind === 'player' ? 'dc-item' : (entry.kind === 'global' ? 'dc-item' : '');
- html += '';
- html += '' + esc(id) + '';
- html += '' + esc(badge) + '';
- html += '
';
- });
+ var hasDirs = Object.keys(t.dirs).length > 0;
+
+ if (t.root.length > 0 || !hasDirs) {
+ if (hasDirs) {
+ var filtered = filterIDs(t.root);
+ if (filtered.length > 0) {
+ var open = !!f || dirOpenState['Root'] === true;
+ html += '';
+ html += '';
+ html += '' + renderItems(filtered) + '
';
+ html += ' ';
+ }
+ } else {
+ html += renderItems(filterIDs(t.root));
+ }
+ }
+
+ if (hasDirs) {
+ Object.keys(t.dirs).sort().forEach(function(dir) {
+ var ids = t.dirs[dir] || [];
+ if (ids.length === 0 && !f) return;
+ var filtered = filterIDs(ids);
+ if (f && filtered.length === 0) return;
+
+ var open = !!f || dirOpenState[dir] === true;
+ html += '';
+ html += '';
+ html += '' + renderItems(filtered) + '
';
+ html += ' ';
+ });
+ }
+
el.innerHTML = html || 'No triggers
';
+
+ el.querySelectorAll('details.dir-group').forEach(function(d) {
+ d.addEventListener('toggle', function() {
+ var n = d.getAttribute('data-name');
+ if (n) dirOpenState[n] = d.open;
+ });
+ });
}
function loadTriggerItem(id) {
@@ -170,7 +219,8 @@ function renderTriggerEditor(id, data) {
html += '';
html += '';
- html += '';
+ html += '';
+ html += '';
html += '
';
$('#editorMain').innerHTML = html;
@@ -214,6 +264,83 @@ function saveTrigger() {
}).catch(function(e) { notify('Save failed: ' + e.message, 'error'); });
}
+function duplicateTrigger(sourceID) {
+ var src = sourceID || triggerID;
+ if (!src) return;
+
+ var done = function(data) {
+ var allTriggerIDs = (treeData.root || []).slice();
+ var dirs = treeData.dirs || {};
+ Object.keys(dirs).forEach(function(d) {
+ allTriggerIDs = allTriggerIDs.concat(dirs[d] || []);
+ });
+
+ var baseID = src + '_copy';
+ var newID = baseID;
+ var counter = 2;
+ while (allTriggerIDs.indexOf(newID) >= 0) {
+ newID = baseID + '_' + counter;
+ counter++;
+ }
+
+ var copy = JSON.parse(JSON.stringify(data));
+ delete copy._raw;
+ delete copy._path;
+ delete copy._kind;
+ copy.id = newID;
+ ced_cleanOutput(copy);
+
+ API.post('/api/triggers', {id: newID, on_player_flag: '', steps: []}).then(function() {
+ return API.put('/api/triggers/' + encodeURIComponent(newID), copy);
+ }).then(function() {
+ notify('Duplicated as ' + newID, 'success');
+ updateUndoBar();
+ loadTriggerList();
+ loadTrigger(newID);
+ }).catch(function(e) { notify('Duplicate failed: ' + e.message, 'error'); });
+ };
+
+ if (sourceID) {
+ API.get('/api/triggers/' + encodeURIComponent(sourceID)).then(done).catch(function(e) { notify('Duplicate failed: ' + e.message, 'error'); });
+ } else {
+ var flagTypeEl = document.querySelector('input[name="trigFlagType"]:checked');
+ if (flagTypeEl) {
+ delete triggerData.on_player_flag;
+ delete triggerData.on_global_flag;
+ var n = $('#trigFlagName');
+ if (flagTypeEl.value === 'player') triggerData.on_player_flag = n ? n.value.trim() : '';
+ else triggerData.on_global_flag = n ? n.value.trim() : '';
+ }
+ window._ieSyncAll(window._editorData);
+ mergeTriggerFromEditor();
+ done(triggerData);
+ }
+}
+
+function showItemContextMenu(e, id) {
+ var items = [
+ {label: 'Duplicate', handler: function() { duplicateTrigger(id); }},
+ {label: 'Delete Trigger', cls: 'danger', handler: function() { deleteTriggerByID(id); }},
+ ];
+ openContextMenu(e, items);
+}
+
+function deleteTriggerByID(id) {
+ if (!confirm('Delete trigger "' + id + '"?')) return;
+ API.del('/api/triggers/' + encodeURIComponent(id)).then(function() {
+ notify('Trigger ' + id + ' deleted', 'success');
+ updateUndoBar();
+ if (triggerID === id) {
+ triggerID = null;
+ currentID = null;
+ triggerData = null;
+ triggerKind = '';
+ $('#editorMain').innerHTML = 'Deleted
';
+ }
+ loadTriggerList();
+ }).catch(function(e) { notify('Delete failed: ' + e.message, 'error'); });
+}
+
function deleteTrigger() {
if (!confirm('Delete trigger "' + triggerID + '"?')) return;
API.del('/api/triggers/' + encodeURIComponent(triggerID)).then(function() {
--
cgit v1.2.3