PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 3.2.24
MxChat – AI Chatbot & Content Generation for WordPress v3.2.24
3.2.25 3.2.24 3.2.23 3.2.22 3.2.21 3.2.20 3.2.19 3.2.18 3.2.17 3.2.16 3.2.15 3.2.14 3.2.12 3.2.13 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 3.2.6 3.2.5 3.2.4 3.2.3 3.2.2 3.2.1 All 156 releases
mxchat-basic / js / knowledge-reimport.js

knowledge-reimport.js in MxChat – AI Chatbot & Content Generation for WordPress 3.2.24, at js/knowledge-reimport.js

277 lines 10.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Knowledge screen: "Re-import affected entries" (plan 89739b).
3 *
4 * Check first, rewrite on confirm. Both run as short server steps that save
5 * where they stopped, so this script only has to keep asking for the next
6 * step and draw what comes back. A closed tab loses nothing: the next page
7 * load picks the saved state up from the status call.
8 */
9 (function () {
10 'use strict';
11
12 var card = document.getElementById('mxchat-kb-reimport');
13 if (!card || typeof window.mxchatKbReimport === 'undefined') {
14 return;
15 }
16 var L = window.mxchatKbReimport;
17 var find = function (selector) { return card.querySelector(selector); };
18
19 var before = find('#mxchat-kb-reimport-before');
20 var checkBtn = find('#mxchat-kb-reimport-check');
21 var applyBtn = find('#mxchat-kb-reimport-apply');
22 var clearBtn = find('#mxchat-kb-reimport-clear');
23 var progress = find('.mxch-kb-reimport-progress');
24 var bar = find('.mxch-progress-bar');
25 var fill = find('.mxch-progress-bar-fill');
26 var label = find('.mxch-progress-label');
27 var errorBox = find('.mxch-kb-reimport-error');
28 var errorText = find('.mxch-kb-reimport-error span');
29 var doneBox = find('.mxch-kb-reimport-done');
30 var doneText = find('.mxch-kb-reimport-done span');
31 var results = find('.mxch-kb-reimport-results');
32 var counts = find('.mxch-kb-reimport-counts');
33 var list = find('.mxch-kb-reimport-entries');
34 var more = find('.mxch-kb-reimport-more');
35 var others = find('.mxch-kb-reimport-others');
36 var othersText = find('.mxch-kb-reimport-others .mxch-disclosure-summary-text');
37 var othersList = find('.mxch-kb-reimport-notes');
38 var footer = find('.mxch-kb-reimport-footer');
39 var busy = false;
40 var last = null;
41
42 function fmt(template, a, b) {
43 return String(template).replace('%1$s', a).replace('%2$s', b).replace('%s', a);
44 }
45
46 function post(params) {
47 var body = new URLSearchParams();
48 body.append('action', 'mxchat_kb_reimport');
49 body.append('nonce', card.getAttribute('data-nonce'));
50 body.append('bot_id', card.getAttribute('data-bot') || 'default');
51 Object.keys(params).forEach(function (key) { body.append(key, params[key]); });
52 return fetch(L.ajaxUrl, { method: 'POST', credentials: 'same-origin', body: body }).then(function (response) {
53 return response.json();
54 });
55 }
56
57 /** One step, retried a few times: every step is resumable on the server. */
58 function step(params, attempt) {
59 attempt = attempt || 0;
60 return post(params).catch(function () {
61 if (attempt >= 3) {
62 throw new Error(L.requestFailed);
63 }
64 return new Promise(function (resolve) { setTimeout(resolve, 1500 * (attempt + 1)); }).then(function () {
65 var again = Object.assign({}, params);
66 delete again.restart;
67 return step(again, attempt + 1);
68 });
69 });
70 }
71
72 function badge(text, variant) {
73 var el = document.createElement('span');
74 el.className = 'mxch-badge' + (variant ? ' mxch-badge-' + variant : '');
75 el.textContent = text;
76 return el;
77 }
78
79 function row(labelText, noteText, badges) {
80 var li = document.createElement('li');
81 var source = document.createElement('span');
82 source.className = 'mxch-kb-reimport-source';
83 source.textContent = labelText;
84 if (noteText) {
85 var note = document.createElement('span');
86 note.className = 'mxch-kb-reimport-note';
87 note.textContent = noteText;
88 source.appendChild(note);
89 }
90 li.appendChild(source);
91 if (badges && badges.length) {
92 var wrap = document.createElement('span');
93 wrap.className = 'mxch-kb-reimport-reasons';
94 badges.forEach(function (b) { wrap.appendChild(b); });
95 li.appendChild(wrap);
96 }
97 return li;
98 }
99
100 function showError(message) {
101 errorText.textContent = message;
102 errorBox.hidden = false;
103 }
104
105 function setBusy(state) {
106 busy = state;
107 checkBtn.disabled = state;
108 applyBtn.disabled = state;
109 clearBtn.disabled = state;
110 before.disabled = state;
111 }
112
113 function render(state) {
114 var phase = state.phase || 'idle';
115 last = state;
116 errorBox.hidden = true;
117 doneBox.hidden = true;
118
119 if (phase === 'idle') {
120 progress.hidden = true;
121 results.hidden = true;
122 footer.hidden = true;
123 return;
124 }
125 if (state.before && !busy) {
126 before.value = state.before;
127 }
128
129 // Progress: a check has no total to measure against, a rewrite has.
130 if (phase === 'scan') {
131 progress.hidden = false;
132 bar.hidden = true;
133 label.textContent = fmt(L.checking, state.scanned);
134 } else if (phase === 'apply') {
135 progress.hidden = false;
136 bar.hidden = false;
137 fill.style.width = (state.to_repair ? Math.round(state.pos / state.to_repair * 100) : 0) + '%';
138 label.textContent = fmt(L.rewriting, state.pos, state.to_repair);
139 } else {
140 progress.hidden = true;
141 }
142
143 if (phase === 'scan') {
144 results.hidden = true;
145 footer.hidden = true;
146 return;
147 }
148
149 results.hidden = false;
150 counts.textContent = '';
151 if (phase === 'done') {
152 counts.appendChild(badge(fmt(L.countRewritten, state.repaired), 'success'));
153 if (state.failed > 0) {
154 counts.appendChild(badge(fmt(L.countFailed, state.failed), 'error'));
155 }
156 } else {
157 counts.appendChild(badge(fmt(L.countRepair, state.to_repair), state.to_repair > 0 ? 'warning' : ''));
158 }
159 counts.appendChild(badge(fmt(L.countCorrect, state.unchanged), phase === 'done' ? '' : 'success'));
160 if (state.changed > 0) {
161 counts.appendChild(badge(fmt(L.countChanged, state.changed)));
162 }
163 if (state.skipped > 0) {
164 counts.appendChild(badge(fmt(L.countSkipped, state.skipped)));
165 }
166
167 list.textContent = '';
168 (state.list || []).forEach(function (entry) {
169 var badges = [];
170 if (entry.result === 'repaired') {
171 badges.push(badge(L.rewritten, 'success'));
172 } else if (entry.result === 'failed') {
173 badges.push(badge(L.notRewritten, 'error'));
174 } else if (entry.result) {
175 badges.push(badge(L.noLongerNeeded));
176 } else {
177 (entry.reasons || []).forEach(function (reason) { badges.push(badge(L.reasons[reason] || reason)); });
178 }
179 list.appendChild(row(entry.label, entry.result === 'failed' ? entry.note : '', badges));
180 });
181 list.hidden = !(state.list && state.list.length);
182 var extra = state.to_repair - (state.list ? state.list.length : 0);
183 more.hidden = extra <= 0;
184 more.textContent = extra > 0 ? fmt(L.andMore, extra) : '';
185
186 othersList.textContent = '';
187 (state.notes || []).forEach(function (note) {
188 othersList.appendChild(row(note.label, note.note, [badge(note.kind === 'changed' ? L.leftAlone : L.skipped)]));
189 });
190 others.hidden = !(state.notes && state.notes.length);
191 othersText.textContent = fmt(L.othersTitle, state.changed + state.skipped);
192
193 if (state.error) {
194 showError(fmt(L.scanStopped, state.error));
195 }
196 if (phase === 'done') {
197 doneText.textContent = state.failed > 0 ? fmt(L.doneWithFailures, state.repaired, state.failed) : fmt(L.done, state.repaired);
198 doneBox.hidden = false;
199 } else if (phase === 'scanned' && state.to_repair === 0 && !state.error) {
200 doneText.textContent = L.nothingToDo;
201 doneBox.hidden = false;
202 }
203
204 footer.hidden = false;
205 var canApply = (phase === 'scanned' || phase === 'apply') && state.to_repair > 0 && !state.error;
206 applyBtn.hidden = !canApply;
207 find('.mxch-kb-reimport-cost').hidden = !canApply;
208 applyBtn.textContent = phase === 'apply' && state.pos > 0 ? fmt(L.resume, state.to_repair - state.pos) : fmt(L.apply, state.to_repair);
209 }
210
211 function loop(params, running) {
212 return step(params).then(function (res) {
213 if (!res || !res.success) {
214 throw new Error(res && res.data && res.data.message ? res.data.message : L.requestFailed);
215 }
216 render(res.data.state);
217 if (res.data.state.phase === running) {
218 return loop({ op: params.op }, running);
219 }
220 return res.data.state;
221 });
222 }
223
224 function run(params, running) {
225 if (busy) {
226 return;
227 }
228 setBusy(true);
229 errorBox.hidden = true;
230 loop(params, running).catch(function (error) {
231 progress.hidden = true;
232 showError(error.message);
233 }).then(function () {
234 setBusy(false);
235 });
236 }
237
238 checkBtn.addEventListener('click', function () {
239 results.hidden = true;
240 footer.hidden = true;
241 doneBox.hidden = true;
242 progress.hidden = false;
243 bar.hidden = true;
244 label.textContent = fmt(L.checking, 0);
245 run({ op: 'scan', restart: '1', before: before.value }, 'scan');
246 });
247
248 applyBtn.addEventListener('click', function () {
249 if (last && last.to_repair) {
250 progress.hidden = false;
251 bar.hidden = false;
252 fill.style.width = Math.round(last.pos / last.to_repair * 100) + '%';
253 label.textContent = fmt(L.rewriting, last.pos, last.to_repair);
254 }
255 run({ op: 'apply' }, 'apply');
256 });
257
258 clearBtn.addEventListener('click', function () {
259 if (busy) {
260 return;
261 }
262 post({ op: 'cancel' }).then(function () { render({ phase: 'idle' }); }).catch(function () { showError(L.requestFailed); });
263 });
264
265 // A check or a rewrite left unfinished by a closed tab is shown as it stands.
266 post({ op: 'status' }).then(function (res) {
267 if (!res || !res.success || !res.data.state || res.data.state.phase === 'idle') {
268 return;
269 }
270 if (res.data.state.phase === 'scan') {
271 run({ op: 'scan' }, 'scan');
272 } else {
273 render(res.data.state);
274 }
275 }).catch(function () {});
276 })();
277