aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/static/talktree.js
diff options
context:
space:
mode:
Diffstat (limited to 'internal/admin/static/talktree.js')
-rw-r--r--internal/admin/static/talktree.js92
1 files changed, 92 insertions, 0 deletions
diff --git a/internal/admin/static/talktree.js b/internal/admin/static/talktree.js
new file mode 100644
index 0000000..f254c21
--- /dev/null
+++ b/internal/admin/static/talktree.js
@@ -0,0 +1,92 @@
+function renderTalkTree(data) {
+ var container = document.getElementById('talktree');
+ if (!container) return;
+ if (!data || !data.talk || !data.talk.nodes) {
+ container.innerHTML = '<p style="color:#888">No conversation tree defined.</p>';
+ return;
+ }
+ window._talkData = data;
+ var nodes = data.talk.nodes;
+ var html = '<div class="talk-tree">';
+ html += renderTreeNodes(nodes, 'start', {});
+ html += '</div>';
+ container.innerHTML = html;
+}
+
+function renderTreeNodes(nodes, rootKey, seen) {
+ var node = nodes[rootKey];
+ if (!node) return '';
+ if (seen[rootKey]) {
+ return '<div class="node ref"><span class="key">' + esc(rootKey) + '</span> <span class="preview">(already shown)</span></div>';
+ }
+ seen[rootKey] = true;
+
+ var html = '';
+ html += '<div class="node root' + (rootKey === 'start' ? ' open' : '') + '">';
+ html += '<div class="node-header" onclick="this.parentElement.classList.toggle(\'open\')">';
+ html += '<span class="arrow"></span>';
+ html += '<span class="key">' + esc(rootKey) + '</span>';
+ html += '<span class="preview">' + esc((node.message || '').substring(0, 60)) + '</span>';
+ html += '</div>';
+ html += '<div class="node-children">';
+
+ html += '<div style="margin-left:8px;font-size:11px">';
+ if (node.message) html += '<div><b>Message:</b> ' + esc(node.message) + '</div>';
+ if (node.condition) html += '<div><b>Condition:</b> ' + esc(JSON.stringify(node.condition)) + '</div>';
+ if (node.goto) html += '<div><b>Goto:</b> ' + esc(node.goto) + '</div>';
+ html += '</div>';
+
+ html += '<div style="margin-left:10px"><b style="font-size:11px;color:#aaa">Options:</b>';
+ if (node.options && node.options.length > 0) {
+ node.options.forEach(function(opt, idx) {
+ html += '<div class="option">';
+ html += '<span>' + esc(opt.text || '') + '</span> \u2192 <span style="color:#8cf">' + esc(opt.goto || '') + '</span>';
+ if (opt.condition) html += ' <span style="color:#888;font-size:10px">[cond]</span>';
+ if (opt.action) html += ' <span style="color:#888;font-size:10px">[action]</span>';
+ html += ' <button class="btn btn-danger btn-sm" onclick="deleteOption(event,\'' + escAttr(rootKey) + '\',' + idx + ')">Delete Option</button>';
+ html += '</div>';
+ });
+ } else {
+ html += '<div class="option" style="color:#888">No options</div>';
+ }
+ html += '<div style="margin-top:4px"><button class="btn btn-primary btn-sm" onclick="addOption(event,\'' + escAttr(rootKey) + '\')">+ Add Option</button></div>';
+ html += '</div>';
+
+ html += '</div></div>';
+
+ if (node.options) {
+ node.options.forEach(function(opt) {
+ if (opt.goto && nodes[opt.goto]) {
+ html += renderTreeNodes(nodes, opt.goto, seen);
+ }
+ });
+ }
+
+ return html;
+}
+
+function addOption(e, nodeKey) {
+ if (e) e.stopPropagation();
+ var data = window._talkData;
+ if (!data || !data.talk || !data.talk.nodes || !data.talk.nodes[nodeKey]) return;
+ var text = prompt('Option text:');
+ if (text === null) return;
+ var dest = prompt('Goto node key:') || '';
+ var node = data.talk.nodes[nodeKey];
+ if (!node.options) node.options = [];
+ node.options.push({ text: text, goto: dest });
+ renderTalkTree(data);
+ if (typeof window.onTalkTreeChange === 'function') window.onTalkTreeChange(data);
+}
+
+function deleteOption(e, nodeKey, idx) {
+ if (e) e.stopPropagation();
+ var data = window._talkData;
+ if (!data || !data.talk || !data.talk.nodes || !data.talk.nodes[nodeKey]) return;
+ var node = data.talk.nodes[nodeKey];
+ if (!node.options || idx < 0 || idx >= node.options.length) return;
+ if (!confirm('Delete this option?')) return;
+ node.options.splice(idx, 1);
+ renderTalkTree(data);
+ if (typeof window.onTalkTreeChange === 'function') window.onTalkTreeChange(data);
+}