deedrop1140 commited on
Commit
f6d6416
Β·
verified Β·
1 Parent(s): b300d75

Update static/script.js

Browse files
Files changed (1) hide show
  1. static/script.js +57 -172
static/script.js CHANGED
@@ -1,5 +1,3 @@
1
- // static/script.js
2
-
3
  const chatForm = document.getElementById("chat-form");
4
  const userInput = document.getElementById("user-input");
5
  const chatBox = document.getElementById("chat-box");
@@ -10,203 +8,90 @@ const negativeBox = document.getElementById("negative-box");
10
 
11
  let sentimentChart = null;
12
 
13
- // ---------- Helpers ----------
14
-
15
- // Escape HTML to avoid XSS when inserting text from the server
16
- function escapeHtml(str) {
17
- return String(str || "").replace(/[&<>"'`=\/]/g, function (s) {
18
- return {
19
- "&": "&amp;",
20
- "<": "&lt;",
21
- ">": "&gt;",
22
- '"': "&quot;",
23
- "'": "&#39;",
24
- "/": "&#x2F;",
25
- "`": "&#x60;",
26
- "=": "&#x3D;"
27
- }[s];
28
- });
29
- }
30
-
31
- // robustFetch: avoids "Unexpected token '<'" when server returns HTML instead of JSON
32
- async function robustFetch(url, opts = {}) {
33
- const res = await fetch(url, Object.assign({ credentials: "same-origin" }, opts));
34
-
35
- if (!res.ok) {
36
- const ct = res.headers.get("content-type") || "";
37
- const body = await res.text().catch(() => "");
38
- const err = new Error(`HTTP ${res.status} ${res.statusText}`);
39
- err.status = res.status;
40
- err.contentType = ct;
41
- err.body = body;
42
- throw err;
43
- }
44
-
45
- const contentType = res.headers.get("content-type") || "";
46
- if (!contentType.includes("application/json")) {
47
- const text = await res.text();
48
- const err = new Error("Expected JSON response but got: " + contentType);
49
- err.body = text;
50
- throw err;
51
- }
52
-
53
- return res.json();
54
- }
55
-
56
- // ---------- Chat UI helpers ----------
57
-
58
  // 🧠 Append User Message
59
  function appendUser(text) {
60
- chatBox.innerHTML += `<p class="user-msg">πŸ§‘ You: ${escapeHtml(text)}</p>`;
61
  chatBox.scrollTop = chatBox.scrollHeight;
62
  }
63
 
64
  // πŸ€– Append Bot Message
65
  function appendBot(text) {
66
- chatBox.innerHTML += `<p class="bot-msg">πŸ€– Bot: ${escapeHtml(text)}</p>`;
67
  chatBox.scrollTop = chatBox.scrollHeight;
68
  }
69
 
70
- // ---------- Chat submit ----------
71
-
72
- if (chatForm) {
73
- chatForm.addEventListener("submit", async (e) => {
74
- e.preventDefault();
75
-
76
- const text = userInput.value.trim();
77
- const order_id = orderIdEl ? orderIdEl.value.trim() : "";
78
-
79
- if (!text) return;
80
-
81
- appendUser(text);
82
- userInput.value = "";
83
 
84
- try {
85
- const res = await fetch("/chat", {
86
- method: "POST",
87
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
88
- body: new URLSearchParams({ user_input: text, order_id })
89
- });
90
 
91
- const data = await res.json();
 
92
 
93
- if (data.error) {
94
- appendBot("Sorry, could not process your message.");
95
- return;
96
- }
97
-
98
- appendBot(data.reply);
99
 
100
- if (categoryEl) {
101
- categoryEl.textContent = data.category || "β€”";
102
- }
103
- if (sentimentEl) {
104
- sentimentEl.textContent = `${data.sentiment || "β€”"} (${data.confidence || 0}%)`;
105
- }
106
 
107
- await updateAnalytics();
108
- await updateNegatives();
109
- } catch (err) {
110
- console.error(err);
111
- appendBot("Network error β€” try again.");
112
  }
113
- });
114
- }
115
 
116
- // ---------- πŸ“Š Update Analytics Charts ----------
117
 
118
- async function updateAnalytics() {
119
- const canvas = document.getElementById("sentimentChart");
120
- if (!canvas) return; // If chart not on this page, skip
121
-
122
- try {
123
- const res = await fetch("/analytics");
124
- const data = await res.json();
125
 
126
- if (sentimentChart) sentimentChart.destroy();
127
-
128
- sentimentChart = new Chart(canvas, {
129
- type: "pie",
130
- data: {
131
- labels: data.labels,
132
- datasets: [
133
- {
134
- data: data.values,
135
- backgroundColor: ["#2ecc71", "#e74c3c", "#f1c40f"]
136
- }
137
- ]
138
- }
139
- });
140
  } catch (err) {
141
- console.error("updateAnalytics failed:", err);
 
142
  }
143
- }
144
-
145
- // ---------- ⚠️ Update Negative Messages Box ----------
146
-
147
- async function updateNegatives(page = 1, perPage = 50) {
148
- if (!negativeBox) return; // Safety for pages without the box
149
 
150
- try {
151
- // If you implemented /admin/negatives-data with pagination:
152
- // const url = `/admin/negatives-data?page=${page}&per_page=${perPage}`;
153
- // If it's just a simple list endpoint, use this:
154
- const url = "/admin/negatives-data";
155
 
156
- const data = await robustFetch(url, { method: "GET" });
157
 
158
- // Support both:
159
- // - data = [ ...messages ]
160
- // - data = { results: [ ...messages ] }
161
- const list = Array.isArray(data) ? data : (data.results || []);
162
 
163
- if (!list.length) {
164
- negativeBox.innerHTML = "<p>No negative messages yet.</p>";
165
- return;
 
 
 
 
 
166
  }
 
 
167
 
168
- negativeBox.innerHTML = list
169
- .map((msg) => {
170
- const username = escapeHtml(msg.username || "Unknown");
171
- const message = escapeHtml(msg.message || "");
172
- const createdAt = msg.created_at
173
- ? new Date(msg.created_at).toLocaleString()
174
- : "";
175
- const category = escapeHtml(msg.category || "β€”");
176
-
177
- return `
178
- <div class="neg-item">
179
- <div class="neg-meta">
180
- <span class="neg-user"><b>${username}</b></span>
181
- ${createdAt ? `<span class="neg-time">${createdAt}</span>` : ""}
182
- <span class="neg-cat">${category}</span>
183
- </div>
184
- <div class="neg-text">⚠️ ${message}</div>
185
- </div>
186
- `;
187
- })
188
- .join("");
189
 
190
- } catch (err) {
191
- console.error("updateNegatives failed:", err);
192
-
193
- const safeBody =
194
- err.body && err.body.slice ? err.body.slice(0, 500) : (err.body || "");
195
-
196
- negativeBox.innerHTML = `
197
- <p style="color: salmon;">
198
- Error loading negatives-data: ${escapeHtml(err.message || "Unknown error")}<br/>
199
- Status: ${escapeHtml(String(err.status || "N/A"))}
200
- </p>
201
- <pre style="white-space: pre-wrap; max-height: 200px; overflow: auto; font-size: 0.8rem;">
202
- ${escapeHtml(safeBody)}
203
- </pre>
204
- `;
205
- }
206
- }
207
 
208
- // Auto-refresh negative messages every 8 seconds (only if the element exists)
209
- if (negativeBox) {
210
- updateNegatives();
211
- setInterval(updateNegatives, 8000);
 
212
  }
 
 
 
 
 
 
1
  const chatForm = document.getElementById("chat-form");
2
  const userInput = document.getElementById("user-input");
3
  const chatBox = document.getElementById("chat-box");
 
8
 
9
  let sentimentChart = null;
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  // 🧠 Append User Message
12
  function appendUser(text) {
13
+ chatBox.innerHTML += `<p class="user-msg">πŸ§‘ You: ${text}</p>`;
14
  chatBox.scrollTop = chatBox.scrollHeight;
15
  }
16
 
17
  // πŸ€– Append Bot Message
18
  function appendBot(text) {
19
+ chatBox.innerHTML += `<p class="bot-msg">πŸ€– Bot: ${text}</p>`;
20
  chatBox.scrollTop = chatBox.scrollHeight;
21
  }
22
 
23
+ // ⭐ Send chat message
24
+ chatForm.addEventListener("submit", async (e) => {
25
+ e.preventDefault();
 
 
 
 
 
 
 
 
 
 
26
 
27
+ const text = userInput.value.trim();
28
+ const order_id = orderIdEl.value.trim();
29
+ if (!text) return;
 
 
 
30
 
31
+ appendUser(text);
32
+ userInput.value = "";
33
 
34
+ try {
35
+ const res = await fetch("/chat", {
36
+ method: "POST",
37
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
38
+ body: new URLSearchParams({ user_input: text, order_id })
39
+ });
40
 
41
+ const data = await res.json();
 
 
 
 
 
42
 
43
+ if (data.error) {
44
+ appendBot("Sorry, could not process your message.");
45
+ return;
 
 
46
  }
 
 
47
 
48
+ appendBot(data.reply);
49
 
50
+ categoryEl.textContent = data.category || "β€”";
51
+ sentimentEl.textContent = `${data.sentiment || "β€”"} (${data.confidence || 0}%)`;
 
 
 
 
 
52
 
53
+ await updateAnalytics();
54
+ await updateNegatives();
 
 
 
 
 
 
 
 
 
 
 
 
55
  } catch (err) {
56
+ console.error(err);
57
+ appendBot("Network error β€” try again.");
58
  }
59
+ });
 
 
 
 
 
60
 
61
+ // πŸ“Š Update Analytics Charts
62
+ async function updateAnalytics() {
63
+ const res = await fetch("/analytics");
64
+ const data = await res.json();
 
65
 
66
+ const ctx = document.getElementById("sentimentChart");
67
 
68
+ if (sentimentChart) sentimentChart.destroy();
 
 
 
69
 
70
+ sentimentChart = new Chart(ctx, {
71
+ type: "pie",
72
+ data: {
73
+ labels: data.labels,
74
+ datasets: [{
75
+ data: data.values,
76
+ backgroundColor: ["#2ecc71", "#e74c3c", "#f1c40f"]
77
+ }]
78
  }
79
+ });
80
+ }
81
 
82
+ // ⚠️ Update Negative Messages Box
83
+ async function updateNegatives() {
84
+ if (!negativeBox) return; // Safety check
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
+ const res = await fetch("/admin/negatives-data");
87
+ const data = await res.json();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
+ negativeBox.innerHTML = data.length === 0
90
+ ? "<p>No negative messages yet.</p>"
91
+ : data.map(msg =>
92
+ `<p class="neg-item">⚠️ <b>${msg.username}</b>: ${msg.message}</p>`
93
+ ).join("");
94
  }
95
+
96
+ // auto-refresh negative messages
97
+ setInterval(updateNegatives, 8000);