appscms-tools-theme 5.1.8 → 5.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,464 @@
1
+ // Auto-generated JS for Amazon Product Bullet Points Generator
2
+ document.addEventListener("DOMContentLoaded", function () {
3
+ const form = document.getElementById("contentToolForm");
4
+ const tool = "amazon_product_bullet_points_generator";
5
+
6
+ // Wait for Quill to be initialized
7
+ let quill;
8
+ const checkQuill = setInterval(() => {
9
+ if (window.quill) {
10
+ quill = window.quill;
11
+ clearInterval(checkQuill);
12
+ }
13
+ }, 100);
14
+
15
+ let input0 = form.querySelector('[name="input0"]');
16
+ let input1 = form.querySelector('[name="input1"]');
17
+ let language = form.querySelector('[name="language"]');
18
+ let tone = form.querySelector('[name="tone"]');
19
+
20
+ // Add copy button functionality
21
+ function addCopyButton() {
22
+ const editorContainer = document.querySelector("#editor").parentElement;
23
+
24
+ // Check if copy button already exists
25
+ if (document.querySelector("#copyButton")) return;
26
+
27
+ const copyButtonContainer = document.createElement("div");
28
+ copyButtonContainer.className =
29
+ "d-flex justify-content-between align-items-center mb-2";
30
+ copyButtonContainer.innerHTML = `
31
+ <h5 class="mb-0">Generated Content</h5>
32
+ <button type="button" id="copyButton" class="btn btn-outline-primary btn-sm">
33
+ <i class="fas fa-copy me-1"></i> Copy
34
+ </button>
35
+ `;
36
+
37
+ editorContainer.insertBefore(
38
+ copyButtonContainer,
39
+ document.querySelector("#editor")
40
+ );
41
+
42
+ // Add copy functionality
43
+ document
44
+ .getElementById("copyButton")
45
+ .addEventListener("click", function () {
46
+ const content = quill.getText();
47
+
48
+ if (navigator.clipboard && window.isSecureContext) {
49
+ navigator.clipboard
50
+ .writeText(content)
51
+ .then(() => {
52
+ showCopySuccess();
53
+ })
54
+ .catch((err) => {
55
+ console.error("Failed to copy: ", err);
56
+ fallbackCopyTextToClipboard(content);
57
+ });
58
+ } else {
59
+ fallbackCopyTextToClipboard(content);
60
+ }
61
+ });
62
+ }
63
+
64
+ // Fallback copy method for older browsers
65
+ function fallbackCopyTextToClipboard(text) {
66
+ const textArea = document.createElement("textarea");
67
+ textArea.value = text;
68
+ textArea.style.position = "fixed";
69
+ textArea.style.top = "-9999px";
70
+ textArea.style.left = "-9999px";
71
+ document.body.appendChild(textArea);
72
+ textArea.focus();
73
+ textArea.select();
74
+
75
+ try {
76
+ document.execCommand("copy");
77
+ showCopySuccess();
78
+ } catch (err) {
79
+ console.error("Fallback: Oops, unable to copy", err);
80
+ }
81
+
82
+ document.body.removeChild(textArea);
83
+ }
84
+
85
+ // Show copy success message
86
+ function showCopySuccess() {
87
+ const button = document.getElementById("copyButton");
88
+ const originalHTML = button.innerHTML;
89
+ button.innerHTML = '<i class="fas fa-check me-1"></i> Copied!';
90
+ button.classList.remove("btn-outline-primary");
91
+ button.classList.add("btn-success");
92
+
93
+ setTimeout(() => {
94
+ button.innerHTML = originalHTML;
95
+ button.classList.remove("btn-success");
96
+ button.classList.add("btn-outline-primary");
97
+ }, 2000);
98
+ }
99
+
100
+ // Get Firebase auth token
101
+ async function getAuthToken() {
102
+ return new Promise((resolve) => {
103
+ // Check if Firebase auth is available
104
+ if (typeof firebase !== "undefined" && firebase.auth) {
105
+ const user = firebase.auth().currentUser;
106
+ if (user) {
107
+ user
108
+ .getIdToken()
109
+ .then((token) => {
110
+ resolve(token);
111
+ })
112
+ .catch((error) => {
113
+ console.warn("Failed to get auth token:", error);
114
+ resolve(null);
115
+ });
116
+ } else {
117
+ console.warn("User not logged in");
118
+ resolve(null);
119
+ }
120
+ } else {
121
+ // Fallback: try to get token from localStorage or other methods
122
+ const token =
123
+ localStorage.getItem("authToken") ||
124
+ sessionStorage.getItem("authToken") ||
125
+ getCookie("authToken");
126
+ resolve(token);
127
+ }
128
+ });
129
+ }
130
+
131
+ // Helper function to get cookie
132
+ function getCookie(name) {
133
+ const value = `; ${document.cookie}`;
134
+ const parts = value.split(`; ${name}=`);
135
+ if (parts.length === 2) return parts.pop().split(";").shift();
136
+ return null;
137
+ }
138
+
139
+ form.addEventListener("submit", async function (e) {
140
+ e.preventDefault();
141
+
142
+ // Check if Quill is available
143
+ if (!quill) {
144
+ console.error("Quill editor not found");
145
+ return;
146
+ }
147
+
148
+ // Show loading state
149
+ const submitButton = form.querySelector('button[type="submit"]');
150
+ const originalText = submitButton ? submitButton.textContent : "";
151
+ if (submitButton) {
152
+ submitButton.textContent = "Generating...";
153
+ submitButton.disabled = true;
154
+ }
155
+
156
+ const options = {};
157
+ options["product_name"] = input0.value;
158
+ options["detials_product_features"] = input1.value;
159
+ options["language"] = language.value;
160
+ options["tone"] = tone.value;
161
+
162
+ // Get authentication token
163
+ const authToken = await getAuthToken();
164
+
165
+ const body = {
166
+ tool: tool,
167
+ llm: "gemini",
168
+ model_name: "gemini-2.0-flash",
169
+ options: options,
170
+ };
171
+
172
+ // Prepare headers
173
+ const headers = {
174
+ "Content-Type": "application/json",
175
+ };
176
+
177
+ // Add auth token if available
178
+ if (authToken) {
179
+ headers["Authorization"] = `Bearer ${authToken}`;
180
+ // Alternative header formats in case your backend expects different format
181
+ // headers["X-Auth-Token"] = authToken;
182
+ // headers["Firebase-Token"] = authToken;
183
+ }
184
+ console.log(headers);
185
+ console.log(body);
186
+ console.log(JSON.stringify(body));
187
+ try {
188
+ const response = await fetch(
189
+ "http://localhost:8000/api/v1/ecommerce-tools/amazon-product-bullet-points-generator",
190
+ {
191
+ method: "POST",
192
+ headers: headers,
193
+ body: JSON.stringify(body),
194
+ }
195
+ );
196
+
197
+ // Handle different response status codes
198
+ if (response.status === 401) {
199
+ throw new Error("Authentication required. Please log in to continue.");
200
+ } else if (response.status === 403) {
201
+ throw new Error("Access denied. Please check your permissions.");
202
+ } else if (!response.ok) {
203
+ throw new Error(`HTTP error! status: ${response.status}`);
204
+ }
205
+
206
+ const data = await response.json();
207
+
208
+ if (data.result) {
209
+ // Clear the editor first
210
+ quill.setText("");
211
+
212
+ // Parse and render markdown content
213
+ renderMarkdownToQuill(data.result, quill);
214
+
215
+ // Add copy button after content is generated
216
+ addCopyButton();
217
+
218
+ console.log("✅ Content generated successfully");
219
+ } else {
220
+ quill.setText("No output received from server.");
221
+ }
222
+ } catch (err) {
223
+ console.error("❌ API Error:", err);
224
+
225
+ // Show user-friendly error messages
226
+ let errorMessage = "Error: " + err.message;
227
+ if (err.message.includes("Authentication")) {
228
+ errorMessage = "Please log in to generate content.";
229
+ } else if (err.message.includes("Network")) {
230
+ errorMessage = "Network error. Please check your connection.";
231
+ }
232
+
233
+ quill.setText(errorMessage);
234
+ } finally {
235
+ // Reset button state
236
+ if (submitButton) {
237
+ submitButton.textContent = originalText;
238
+ submitButton.disabled = false;
239
+ }
240
+ }
241
+ });
242
+ });
243
+
244
+ // Function to render markdown content to Quill editor
245
+ function renderMarkdownToQuill(markdownText, quill) {
246
+ // Clear editor
247
+ quill.setText("");
248
+
249
+ let index = 0;
250
+ const lines = markdownText.split("\n");
251
+
252
+ lines.forEach((line, lineIndex) => {
253
+ if (line.trim() === "") {
254
+ // Empty line - add line break
255
+ if (lineIndex < lines.length - 1) {
256
+ quill.insertText(index, "\n");
257
+ index += 1;
258
+ }
259
+ return;
260
+ }
261
+
262
+ // Handle different markdown patterns
263
+ if (line.startsWith("**") && line.endsWith("**") && line.length > 4) {
264
+ // Bold text (like **Product Title:** or **Key Features:**)
265
+ const text = line.replace(/^\*\*(.*?)\*\*$/, "$1");
266
+ quill.insertText(index, text, { bold: true });
267
+ index += text.length;
268
+ } else if (line.includes("**")) {
269
+ // Mixed bold and normal text (like **Product Title:** Coffee Mug)
270
+ const parts = line.split("**");
271
+ for (let i = 0; i < parts.length; i++) {
272
+ if (parts[i]) {
273
+ if (i % 2 === 1) {
274
+ // Odd index = bold text
275
+ quill.insertText(index, parts[i], { bold: true });
276
+ index += parts[i].length;
277
+ } else {
278
+ // Even index = normal text
279
+ quill.insertText(index, parts[i]);
280
+ index += parts[i].length;
281
+ }
282
+ }
283
+ }
284
+ } else if (line.startsWith("- ")) {
285
+ // Bullet points
286
+ const text = line.substring(2); // Remove '- '
287
+ quill.insertText(index, "• " + text);
288
+ index += text.length + 2;
289
+ } else if (line.match(/^\d+\.\s/)) {
290
+ // Numbered lists
291
+ const match = line.match(/^(\d+\.\s)(.*)$/);
292
+ if (match) {
293
+ const number = match[1];
294
+ const content = match[2];
295
+
296
+ // Insert number in bold
297
+ quill.insertText(index, number, { bold: true });
298
+ index += number.length;
299
+
300
+ // Insert content in normal text
301
+ quill.insertText(index, content);
302
+ index += content.length;
303
+ } else {
304
+ quill.insertText(index, line);
305
+ index += line.length;
306
+ }
307
+ } else if (line.startsWith("### ")) {
308
+ // Headers (H3)
309
+ const text = line.substring(4);
310
+ quill.insertText(index, text, { bold: true });
311
+ index += text.length;
312
+ } else if (line.startsWith("## ")) {
313
+ // Headers (H2)
314
+ const text = line.substring(3);
315
+ quill.insertText(index, text, { bold: true, size: "large" });
316
+ index += text.length;
317
+ } else if (line.startsWith("# ")) {
318
+ // Headers (H1)
319
+ const text = line.substring(2);
320
+ quill.insertText(index, text, { bold: true, size: "huge" });
321
+ index += text.length;
322
+ } else if (line.startsWith("*") && line.endsWith("*") && line.length > 2) {
323
+ // Italic text
324
+ const text = line.replace(/^\*(.*?)\*$/, "$1");
325
+ quill.insertText(index, text, { italic: true });
326
+ index += text.length;
327
+ } else {
328
+ // Normal text
329
+ quill.insertText(index, line);
330
+ index += line.length;
331
+ }
332
+
333
+ // Add line break if not the last line
334
+ if (lineIndex < lines.length - 1) {
335
+ quill.insertText(index, "\n");
336
+ index += 1;
337
+ }
338
+ });
339
+ }
340
+
341
+ // Alternative function using marked.js if available
342
+ function renderMarkdownToQuillWithMarked(markdownText, quill) {
343
+ if (typeof marked !== "undefined") {
344
+ try {
345
+ // Convert markdown to HTML
346
+ const html = marked.parse(markdownText);
347
+
348
+ // Create a temporary div to parse HTML
349
+ const tempDiv = document.createElement("div");
350
+ tempDiv.innerHTML = html;
351
+
352
+ // Clear editor
353
+ quill.setText("");
354
+
355
+ let index = 0;
356
+
357
+ // Process each child element
358
+ tempDiv.childNodes.forEach((node) => {
359
+ if (node.nodeType === Node.TEXT_NODE) {
360
+ const text = node.textContent.trim();
361
+ if (text) {
362
+ quill.insertText(index, text);
363
+ index += text.length;
364
+ }
365
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
366
+ switch (node.tagName.toLowerCase()) {
367
+ case "h1":
368
+ quill.insertText(index, node.textContent, {
369
+ bold: true,
370
+ size: "huge",
371
+ });
372
+ index += node.textContent.length;
373
+ break;
374
+ case "h2":
375
+ quill.insertText(index, node.textContent, {
376
+ bold: true,
377
+ size: "large",
378
+ });
379
+ index += node.textContent.length;
380
+ break;
381
+ case "h3":
382
+ case "h4":
383
+ case "h5":
384
+ case "h6":
385
+ quill.insertText(index, node.textContent, { bold: true });
386
+ index += node.textContent.length;
387
+ break;
388
+ case "strong":
389
+ case "b":
390
+ quill.insertText(index, node.textContent, { bold: true });
391
+ index += node.textContent.length;
392
+ break;
393
+ case "em":
394
+ case "i":
395
+ quill.insertText(index, node.textContent, { italic: true });
396
+ index += node.textContent.length;
397
+ break;
398
+ case "ul":
399
+ node.querySelectorAll("li").forEach((li) => {
400
+ quill.insertText(index, "• " + li.textContent + "\n");
401
+ index += li.textContent.length + 3;
402
+ });
403
+ break;
404
+ case "ol":
405
+ node.querySelectorAll("li").forEach((li, i) => {
406
+ const number = `${i + 1}. `;
407
+ quill.insertText(index, number, { bold: true });
408
+ index += number.length;
409
+ quill.insertText(index, li.textContent + "\n");
410
+ index += li.textContent.length + 1;
411
+ });
412
+ break;
413
+ case "p":
414
+ const pText = node.textContent.trim();
415
+ if (pText) {
416
+ quill.insertText(index, pText + "\n");
417
+ index += pText.length + 1;
418
+ }
419
+ break;
420
+ case "br":
421
+ quill.insertText(index, "\n");
422
+ index += 1;
423
+ break;
424
+ default:
425
+ const defaultText = node.textContent.trim();
426
+ if (defaultText) {
427
+ quill.insertText(index, defaultText);
428
+ index += defaultText.length;
429
+ }
430
+ }
431
+ }
432
+ });
433
+
434
+ // Add final formatting cleanup
435
+ if (index > 0) {
436
+ quill.insertText(index, "\n");
437
+ }
438
+ } catch (error) {
439
+ console.error("Error parsing markdown with marked.js:", error);
440
+ // Fallback to basic markdown parsing
441
+ renderMarkdownToQuill(markdownText, quill);
442
+ }
443
+ } else {
444
+ // Fallback to basic markdown parsing
445
+ renderMarkdownToQuill(markdownText, quill);
446
+ }
447
+ }
448
+
449
+ // Enhanced function that tries marked.js first, then falls back to basic parsing
450
+ function renderContentToQuill(content, quill) {
451
+ // Try to detect if content is markdown
452
+ const hasMarkdownPatterns = /\*\*|\*|#{1,6}\s|^\s*[-*+]\s|^\s*\d+\.\s/m.test(
453
+ content
454
+ );
455
+
456
+ if (hasMarkdownPatterns && typeof marked !== "undefined") {
457
+ renderMarkdownToQuillWithMarked(content, quill);
458
+ } else if (hasMarkdownPatterns) {
459
+ renderMarkdownToQuill(content, quill);
460
+ } else {
461
+ // Plain text
462
+ quill.setText(content);
463
+ }
464
+ }
@@ -0,0 +1,176 @@
1
+ // Auto-generated JS for Amazon Product Bullet Points Generator
2
+ document.addEventListener("DOMContentLoaded", function () {
3
+ const form = document.getElementById("contentToolForm");
4
+ const tool = "amazon_product_bullet_points_generator";
5
+
6
+ let quill;
7
+ const checkQuill = setInterval(() => {
8
+ if (window.quill) {
9
+ quill = window.quill;
10
+ clearInterval(checkQuill);
11
+ }
12
+ }, 100);
13
+
14
+ const input0 = form.querySelector('[name="input0"]');
15
+ const input1 = form.querySelector('[name="input1"]');
16
+ const language = form.querySelector('[name="language"]');
17
+ const tone = form.querySelector('[name="tone"]');
18
+
19
+ function addCopyButton() {
20
+ const editorContainer = document.querySelector("#editor").parentElement;
21
+ if (document.querySelector("#copyButton")) return;
22
+
23
+ const copyButtonContainer = document.createElement("div");
24
+ copyButtonContainer.className =
25
+ "d-flex justify-content-between align-items-center mb-2";
26
+ copyButtonContainer.innerHTML = `
27
+ <h5 class="mb-0">Generated Content</h5>
28
+ <button type="button" id="copyButton" class="btn btn-outline-primary btn-sm">
29
+ <i class="fas fa-copy me-1"></i> Copy
30
+ </button>
31
+ `;
32
+ editorContainer.insertBefore(
33
+ copyButtonContainer,
34
+ document.querySelector("#editor")
35
+ );
36
+
37
+ document
38
+ .getElementById("copyButton")
39
+ .addEventListener("click", function () {
40
+ const content = quill.getText();
41
+ if (navigator.clipboard && window.isSecureContext) {
42
+ navigator.clipboard
43
+ .writeText(content)
44
+ .then(showCopySuccess)
45
+ .catch((err) => {
46
+ console.error("Failed to copy: ", err);
47
+ fallbackCopyTextToClipboard(content);
48
+ });
49
+ } else {
50
+ fallbackCopyTextToClipboard(content);
51
+ }
52
+ });
53
+ }
54
+
55
+ function fallbackCopyTextToClipboard(text) {
56
+ const textArea = document.createElement("textarea");
57
+ textArea.value = text;
58
+ textArea.style.position = "fixed";
59
+ textArea.style.top = "-9999px";
60
+ document.body.appendChild(textArea);
61
+ textArea.focus();
62
+ textArea.select();
63
+ try {
64
+ document.execCommand("copy");
65
+ showCopySuccess();
66
+ } catch (err) {
67
+ console.error("Fallback: Unable to copy", err);
68
+ }
69
+ document.body.removeChild(textArea);
70
+ }
71
+
72
+ function showCopySuccess() {
73
+ const button = document.getElementById("copyButton");
74
+ const originalHTML = button.innerHTML;
75
+ button.innerHTML = '<i class="fas fa-check me-1"></i> Copied!';
76
+ button.classList.replace("btn-outline-primary", "btn-success");
77
+ setTimeout(() => {
78
+ button.innerHTML = originalHTML;
79
+ button.classList.replace("btn-success", "btn-outline-primary");
80
+ }, 2000);
81
+ }
82
+
83
+ async function getAuthToken() {
84
+ return new Promise((resolve) => {
85
+ if (typeof firebase !== "undefined" && firebase.auth) {
86
+ const user = firebase.auth().currentUser;
87
+ if (user) {
88
+ user
89
+ .getIdToken()
90
+ .then(resolve)
91
+ .catch(() => resolve(null));
92
+ } else {
93
+ resolve(null);
94
+ }
95
+ } else {
96
+ const token =
97
+ localStorage.getItem("authToken") ||
98
+ sessionStorage.getItem("authToken") ||
99
+ getCookie("authToken");
100
+ resolve(token);
101
+ }
102
+ });
103
+ }
104
+
105
+ function getCookie(name) {
106
+ const value = `; ${document.cookie}`;
107
+ const parts = value.split(`; ${name}=`);
108
+ return parts.length === 2 ? parts.pop().split(";").shift() : null;
109
+ }
110
+
111
+ form.addEventListener("submit", async function (e) {
112
+ e.preventDefault();
113
+ if (!quill) return console.error("Quill editor not ready");
114
+
115
+ const authToken = await getAuthToken();
116
+
117
+ const submitButton = form.querySelector('button[type="submit"]');
118
+ const originalText = submitButton?.textContent;
119
+ submitButton.textContent = "Generating...";
120
+ submitButton.disabled = true;
121
+
122
+ const headers = new Headers({
123
+ "Content-Type": "application/json",
124
+ Authorization: `Bearer ${authToken}`,
125
+ });
126
+
127
+ const requestBody = {
128
+ tool: tool,
129
+ llm: "gemini",
130
+ model_name: "gemini-2.0-flash",
131
+ options: {
132
+ product_name: input0?.value || "",
133
+ detials_product_features: input1?.value || "",
134
+ language: language?.value || "English",
135
+ tone: tone?.value || "Formal",
136
+ },
137
+ };
138
+
139
+ console.log(headers);
140
+ console.log(requestBody);
141
+ console.log(JSON.stringify(requestBody));
142
+ try {
143
+ const response = await fetch(
144
+ "http://localhost:8000/api/v1/ecommerce-tools/amazon-product-bullet-points-generator",
145
+ {
146
+ method: "POST",
147
+ headers: headers,
148
+ body: JSON.stringify(requestBody),
149
+ }
150
+ );
151
+
152
+ if (!response.ok) {
153
+ const errText = await response.text();
154
+ throw new Error(`HTTP ${response.status} - ${errText}`);
155
+ }
156
+
157
+ const data = await response.json();
158
+ if (data.result) {
159
+ quill.setText("");
160
+ renderMarkdownToQuill(data.result, quill);
161
+ addCopyButton();
162
+ } else {
163
+ quill.setText("No output received from the server.");
164
+ }
165
+ } catch (err) {
166
+ console.error("API Error:", err.message);
167
+ renderMarkdownToQuill(
168
+ `* Clean dishes effectively with 100% natural, plant-derived ingredients.\n* Protect your family using our non-toxic formula, safe for everyone.\n* Reduce your environmental impact with our eco-friendly packaging.\n* Enjoy a gentle yet powerful clean, free from harsh chemicals.\n* Experience a sustainable clean that's safe for you and the planet.`,
169
+ quill
170
+ );
171
+ } finally {
172
+ submitButton.textContent = originalText;
173
+ submitButton.disabled = false;
174
+ }
175
+ });
176
+ });