aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/static/talktree.js
blob: f254c21154c0f9ae1b420382beb5a553e6c1bbb8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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);
}