@contenify/chatbot 1.0.0 → 3.0.0
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.
- package/README.md +202 -48
- package/dist/index.js +625 -644
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +631 -650
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +192 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -110,7 +110,7 @@ var api_default = api;
|
|
|
110
110
|
|
|
111
111
|
// services/preferences.service.ts
|
|
112
112
|
var getMyPreferencesApi = async () => {
|
|
113
|
-
const { data } = await api_default.get("/preferences/me");
|
|
113
|
+
const { data } = await api_default.get("/chatboat/preferences/me");
|
|
114
114
|
return data.data;
|
|
115
115
|
};
|
|
116
116
|
var savePreferencesApi = async ({
|
|
@@ -188,7 +188,7 @@ var savePreferencesApi = async ({
|
|
|
188
188
|
if (targetAudience !== void 0) {
|
|
189
189
|
formData.append("targetAudience", targetAudience);
|
|
190
190
|
}
|
|
191
|
-
const { data } = await api_default.put("/preferences", formData, {
|
|
191
|
+
const { data } = await api_default.put("/chatboat/preferences", formData, {
|
|
192
192
|
headers: {
|
|
193
193
|
"Content-Type": "multipart/form-data"
|
|
194
194
|
}
|
|
@@ -200,7 +200,7 @@ var savePreferencesApi = async ({
|
|
|
200
200
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
201
201
|
var defaultPreferences = {
|
|
202
202
|
chatbot: {
|
|
203
|
-
name: "
|
|
203
|
+
name: "ContenifyAI Assistant",
|
|
204
204
|
primaryColor: "#10b981",
|
|
205
205
|
secondaryColor: "#064e3b",
|
|
206
206
|
theme: "system"
|
|
@@ -299,31 +299,79 @@ function usePreferences() {
|
|
|
299
299
|
// components/chatbot/ChatBot.tsx
|
|
300
300
|
var import_react10 = require("react");
|
|
301
301
|
|
|
302
|
-
//
|
|
303
|
-
function
|
|
304
|
-
if (!raw)
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
302
|
+
// src/utils/ aiJsonParser.ts
|
|
303
|
+
function extractJSON(raw) {
|
|
304
|
+
if (!raw) return null;
|
|
305
|
+
let cleaned = raw.replace(/```json/gi, "").replace(/```/g, "").trim();
|
|
306
|
+
const first = cleaned.indexOf("{");
|
|
307
|
+
const last = cleaned.lastIndexOf("}");
|
|
308
|
+
if (first === -1 || last === -1 || last <= first) return null;
|
|
309
|
+
const possibleJson = cleaned.substring(first, last + 1);
|
|
310
|
+
try {
|
|
311
|
+
return JSON.parse(possibleJson);
|
|
312
|
+
} catch (err) {
|
|
313
|
+
console.warn("JSON parse failed:", err);
|
|
314
|
+
return null;
|
|
312
315
|
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// src/utils/decodeUnicode.ts
|
|
319
|
+
function decodeUnicode(text) {
|
|
320
|
+
if (!text) return "";
|
|
313
321
|
try {
|
|
314
|
-
|
|
315
|
-
return {
|
|
316
|
-
title: parsed.title || "",
|
|
317
|
-
article: parsed.article || parsed.content || "",
|
|
318
|
-
metaKeywords: Array.isArray(parsed.metaKeywords) ? parsed.metaKeywords : []
|
|
319
|
-
};
|
|
322
|
+
return JSON.parse(`"${text.replace(/"/g, '\\"')}"`);
|
|
320
323
|
} catch (e) {
|
|
321
|
-
|
|
324
|
+
return text;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// src/utils/articleTextToHtml.ts
|
|
329
|
+
function articleTextToHtml(text) {
|
|
330
|
+
if (!text) return "";
|
|
331
|
+
text = text.replace(/\\n/g, "\n");
|
|
332
|
+
const lines = text.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
333
|
+
let html = "";
|
|
334
|
+
for (const line of lines) {
|
|
335
|
+
if (line.length < 80 && !line.endsWith("\u0964") && !line.endsWith(".")) {
|
|
336
|
+
html += `<h2>${line}</h2>`;
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
html += `<p>${line}</p>`;
|
|
340
|
+
}
|
|
341
|
+
return html;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// src/utils/formatAIContent.ts
|
|
345
|
+
function formatAIContent(raw) {
|
|
346
|
+
const empty = {
|
|
347
|
+
isArticle: false,
|
|
348
|
+
title: "",
|
|
349
|
+
subtitle: "",
|
|
350
|
+
articleHtml: "",
|
|
351
|
+
article: "",
|
|
352
|
+
metaDescription: "",
|
|
353
|
+
metaKeywords: [],
|
|
354
|
+
plainText: ""
|
|
355
|
+
};
|
|
356
|
+
if (!raw) return empty;
|
|
357
|
+
const parsed = extractJSON(raw);
|
|
358
|
+
if (parsed && (parsed.title || parsed.article)) {
|
|
359
|
+
const rawArticle = (parsed.article || "").trim();
|
|
360
|
+
const safeArticle = decodeUnicode(rawArticle);
|
|
361
|
+
const isHtml = /<[a-z][\s\S]*>/i.test(safeArticle);
|
|
362
|
+
const articleHtml = isHtml ? safeArticle : articleTextToHtml(safeArticle);
|
|
322
363
|
return {
|
|
323
|
-
|
|
324
|
-
|
|
364
|
+
isArticle: true,
|
|
365
|
+
title: parsed.title || "",
|
|
366
|
+
subtitle: parsed.subtitle || "",
|
|
367
|
+
articleHtml,
|
|
368
|
+
article: rawArticle,
|
|
369
|
+
metaDescription: parsed.metaDescription || "",
|
|
370
|
+
metaKeywords: Array.isArray(parsed.metaKeywords) ? parsed.metaKeywords : [],
|
|
371
|
+
plainText: raw
|
|
325
372
|
};
|
|
326
373
|
}
|
|
374
|
+
return __spreadProps(__spreadValues({}, empty), { plainText: raw });
|
|
327
375
|
}
|
|
328
376
|
|
|
329
377
|
// components/chatbot/ChatWindow.tsx
|
|
@@ -506,38 +554,38 @@ function useTheme() {
|
|
|
506
554
|
|
|
507
555
|
// components/chatbot/EditModal.tsx
|
|
508
556
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
557
|
+
function toSlug(text) {
|
|
558
|
+
return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
559
|
+
}
|
|
509
560
|
function EditModal({
|
|
510
561
|
isOpen,
|
|
562
|
+
initialTitle = "",
|
|
563
|
+
initialSubtitle = "",
|
|
511
564
|
initialContent,
|
|
565
|
+
initialMetaDescription = "",
|
|
512
566
|
metaKeywords,
|
|
513
567
|
onClose,
|
|
514
568
|
onSaveDraft,
|
|
515
569
|
onPost
|
|
516
570
|
}) {
|
|
517
571
|
const { primaryColor } = useTheme();
|
|
572
|
+
const [title, setTitle] = (0, import_react4.useState)("");
|
|
573
|
+
const [subtitle, setSubtitle] = (0, import_react4.useState)("");
|
|
574
|
+
const [slug, setSlug] = (0, import_react4.useState)("");
|
|
575
|
+
const [slugEdited, setSlugEdited] = (0, import_react4.useState)(false);
|
|
576
|
+
const [metaDescription, setMetaDescription] = (0, import_react4.useState)("");
|
|
518
577
|
const [content, setContent] = (0, import_react4.useState)("");
|
|
519
578
|
const [keywords, setKeywords] = (0, import_react4.useState)(metaKeywords);
|
|
520
579
|
const [newKeyword, setNewKeyword] = (0, import_react4.useState)("");
|
|
521
|
-
const markdownToHtml = (text) => {
|
|
522
|
-
const lines = text.split("\n").filter((line) => line.trim());
|
|
523
|
-
let html = "";
|
|
524
|
-
lines.forEach((line) => {
|
|
525
|
-
const trimmed = line.trim();
|
|
526
|
-
if (trimmed.startsWith("# ")) {
|
|
527
|
-
html += `<h1>${trimmed.replace(/^#\s+/, "")}</h1>`;
|
|
528
|
-
} else if (trimmed.startsWith("## ")) {
|
|
529
|
-
html += `<h2>${trimmed.replace(/^##\s+/, "")}</h2>`;
|
|
530
|
-
} else {
|
|
531
|
-
html += `<p>${trimmed}</p>`;
|
|
532
|
-
}
|
|
533
|
-
});
|
|
534
|
-
return html;
|
|
535
|
-
};
|
|
536
580
|
(0, import_react4.useEffect)(() => {
|
|
537
|
-
|
|
538
|
-
|
|
581
|
+
setTitle(initialTitle);
|
|
582
|
+
setSubtitle(initialSubtitle);
|
|
583
|
+
setMetaDescription(initialMetaDescription);
|
|
584
|
+
setSlug(toSlug(initialTitle));
|
|
585
|
+
setSlugEdited(false);
|
|
586
|
+
setContent(initialContent);
|
|
539
587
|
setKeywords(metaKeywords);
|
|
540
|
-
}, [initialContent, metaKeywords]);
|
|
588
|
+
}, [initialTitle, initialSubtitle, initialContent, initialMetaDescription, metaKeywords]);
|
|
541
589
|
(0, import_react4.useEffect)(() => {
|
|
542
590
|
if (isOpen) {
|
|
543
591
|
document.body.style.overflow = "hidden";
|
|
@@ -548,6 +596,16 @@ function EditModal({
|
|
|
548
596
|
document.body.style.overflow = "";
|
|
549
597
|
};
|
|
550
598
|
}, [isOpen]);
|
|
599
|
+
const handleTitleChange = (value) => {
|
|
600
|
+
setTitle(value);
|
|
601
|
+
if (!slugEdited) {
|
|
602
|
+
setSlug(toSlug(value));
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
const handleSlugChange = (value) => {
|
|
606
|
+
setSlug(toSlug(value));
|
|
607
|
+
setSlugEdited(true);
|
|
608
|
+
};
|
|
551
609
|
const handleAddKeyword = () => {
|
|
552
610
|
if (newKeyword.trim() && !keywords.includes(newKeyword.trim())) {
|
|
553
611
|
setKeywords([...keywords, newKeyword.trim()]);
|
|
@@ -563,28 +621,62 @@ function EditModal({
|
|
|
563
621
|
handleAddKeyword();
|
|
564
622
|
}
|
|
565
623
|
};
|
|
624
|
+
const getEditData = () => ({
|
|
625
|
+
title,
|
|
626
|
+
subtitle,
|
|
627
|
+
article: content,
|
|
628
|
+
metaDescription,
|
|
629
|
+
slug,
|
|
630
|
+
keywords
|
|
631
|
+
});
|
|
566
632
|
if (!isOpen) return null;
|
|
567
633
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-edit-modal-overlay", children: [
|
|
568
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
569
|
-
"div",
|
|
570
|
-
{
|
|
571
|
-
className: "cnfy-edit-modal-backdrop",
|
|
572
|
-
onClick: onClose
|
|
573
|
-
}
|
|
574
|
-
),
|
|
634
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "cnfy-edit-modal-backdrop", onClick: onClose }),
|
|
575
635
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-edit-modal", children: [
|
|
576
636
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-edit-modal-header", children: [
|
|
577
637
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: "cnfy-edit-modal-title", children: "Edit Article" }),
|
|
578
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
579
|
-
"button",
|
|
580
|
-
{
|
|
581
|
-
onClick: onClose,
|
|
582
|
-
className: "cnfy-edit-modal-close-btn",
|
|
583
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.X, { size: 20, className: "cnfy-edit-modal-close-icon" })
|
|
584
|
-
}
|
|
585
|
-
)
|
|
638
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { onClick: onClose, className: "cnfy-edit-modal-close-btn", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.X, { size: 20, className: "cnfy-edit-modal-close-icon" }) })
|
|
586
639
|
] }),
|
|
587
640
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-edit-modal-body", children: [
|
|
641
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
642
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "cnfy-edit-label", children: "Title" }),
|
|
643
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
644
|
+
"input",
|
|
645
|
+
{
|
|
646
|
+
type: "text",
|
|
647
|
+
value: title,
|
|
648
|
+
onChange: (e) => handleTitleChange(e.target.value),
|
|
649
|
+
placeholder: "Article title...",
|
|
650
|
+
className: "cnfy-edit-input"
|
|
651
|
+
}
|
|
652
|
+
)
|
|
653
|
+
] }),
|
|
654
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
655
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "cnfy-edit-label", children: "Subtitle" }),
|
|
656
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
657
|
+
"input",
|
|
658
|
+
{
|
|
659
|
+
type: "text",
|
|
660
|
+
value: subtitle,
|
|
661
|
+
onChange: (e) => setSubtitle(e.target.value),
|
|
662
|
+
placeholder: "Article subtitle...",
|
|
663
|
+
className: "cnfy-edit-input"
|
|
664
|
+
}
|
|
665
|
+
)
|
|
666
|
+
] }),
|
|
667
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
668
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "cnfy-edit-label", children: "Slug" }),
|
|
669
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
670
|
+
"input",
|
|
671
|
+
{
|
|
672
|
+
type: "text",
|
|
673
|
+
value: slug,
|
|
674
|
+
onChange: (e) => handleSlugChange(e.target.value),
|
|
675
|
+
placeholder: "article-url-slug",
|
|
676
|
+
className: "cnfy-edit-input cnfy-edit-input--mono"
|
|
677
|
+
}
|
|
678
|
+
)
|
|
679
|
+
] }),
|
|
588
680
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
589
681
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "cnfy-edit-label", children: "Article Content" }),
|
|
590
682
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -597,26 +689,32 @@ function EditModal({
|
|
|
597
689
|
)
|
|
598
690
|
] }),
|
|
599
691
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
600
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "cnfy-edit-label", children: "Meta
|
|
601
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
602
|
-
"
|
|
692
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "cnfy-edit-label", children: "Meta Description" }),
|
|
693
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
694
|
+
"textarea",
|
|
603
695
|
{
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
696
|
+
value: metaDescription,
|
|
697
|
+
onChange: (e) => setMetaDescription(e.target.value),
|
|
698
|
+
placeholder: "Brief description for search engines...",
|
|
699
|
+
className: "cnfy-edit-textarea",
|
|
700
|
+
rows: 3
|
|
701
|
+
}
|
|
702
|
+
)
|
|
703
|
+
] }),
|
|
704
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
705
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "cnfy-edit-label", children: "Meta Keywords" }),
|
|
706
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "cnfy-keyword-list", children: keywords.map((keyword, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "cnfy-keyword-tag", children: [
|
|
707
|
+
"#",
|
|
708
|
+
keyword,
|
|
709
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
710
|
+
"button",
|
|
711
|
+
{
|
|
712
|
+
onClick: () => handleRemoveKeyword(index),
|
|
713
|
+
className: "cnfy-keyword-remove-btn",
|
|
714
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.X, { size: 14 })
|
|
715
|
+
}
|
|
716
|
+
)
|
|
717
|
+
] }, index)) }),
|
|
620
718
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-keyword-input-row", children: [
|
|
621
719
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
622
720
|
"input",
|
|
@@ -629,30 +727,16 @@ function EditModal({
|
|
|
629
727
|
className: "cnfy-keyword-input"
|
|
630
728
|
}
|
|
631
729
|
),
|
|
632
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
633
|
-
"button",
|
|
634
|
-
{
|
|
635
|
-
onClick: handleAddKeyword,
|
|
636
|
-
className: "cnfy-btn-add-keyword",
|
|
637
|
-
children: "Add"
|
|
638
|
-
}
|
|
639
|
-
)
|
|
730
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { onClick: handleAddKeyword, className: "cnfy-btn-add-keyword", children: "Add" })
|
|
640
731
|
] })
|
|
641
732
|
] })
|
|
642
733
|
] }),
|
|
643
734
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-edit-modal-footer", children: [
|
|
735
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { onClick: onClose, className: "cnfy-btn-footer-cancel", children: "Cancel" }),
|
|
644
736
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
645
737
|
"button",
|
|
646
738
|
{
|
|
647
|
-
onClick:
|
|
648
|
-
className: "cnfy-btn-footer-cancel",
|
|
649
|
-
children: "Cancel"
|
|
650
|
-
}
|
|
651
|
-
),
|
|
652
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
653
|
-
"button",
|
|
654
|
-
{
|
|
655
|
-
onClick: () => onSaveDraft(content, keywords),
|
|
739
|
+
onClick: () => onSaveDraft(getEditData()),
|
|
656
740
|
className: "cnfy-btn-save-draft",
|
|
657
741
|
children: "Save Draft"
|
|
658
742
|
}
|
|
@@ -660,7 +744,7 @@ function EditModal({
|
|
|
660
744
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
661
745
|
"button",
|
|
662
746
|
{
|
|
663
|
-
onClick: () => onPost(
|
|
747
|
+
onClick: () => onPost(getEditData()),
|
|
664
748
|
className: "cnfy-btn-post-article",
|
|
665
749
|
style: { backgroundColor: primaryColor, color: "#fff" },
|
|
666
750
|
children: "Post"
|
|
@@ -842,19 +926,19 @@ function NewsList({
|
|
|
842
926
|
|
|
843
927
|
// services/news.service.ts
|
|
844
928
|
var getTrendingNews = async () => {
|
|
845
|
-
const { data } = await api_default.get("/
|
|
929
|
+
const { data } = await api_default.get("/chatboat/trending");
|
|
846
930
|
return data.data;
|
|
847
931
|
};
|
|
848
932
|
var getNewsSources = async () => {
|
|
849
|
-
const { data } = await api_default.get("/
|
|
933
|
+
const { data } = await api_default.get("/chatboat/scrape/sources");
|
|
850
934
|
return data.data;
|
|
851
935
|
};
|
|
852
936
|
var scrapeNewsSource = async (sourceId) => {
|
|
853
|
-
const { data } = await api_default.post("/
|
|
937
|
+
const { data } = await api_default.post("/chatboat/scrape/source", { sourceId });
|
|
854
938
|
return data.data;
|
|
855
939
|
};
|
|
856
940
|
var getNewsBySource = async (sourceId) => {
|
|
857
|
-
const { data } = await api_default.get(`/
|
|
941
|
+
const { data } = await api_default.get(`/chatboat/scrape/by-source/${sourceId}`);
|
|
858
942
|
return data.data;
|
|
859
943
|
};
|
|
860
944
|
|
|
@@ -874,12 +958,13 @@ function ChatWindow({
|
|
|
874
958
|
onSend,
|
|
875
959
|
onSelectNews,
|
|
876
960
|
isStreaming = false,
|
|
961
|
+
activeField,
|
|
877
962
|
analyzedData,
|
|
878
963
|
onSelectAction,
|
|
879
964
|
onPost: onPostCallback
|
|
880
965
|
}) {
|
|
881
966
|
var _a, _b;
|
|
882
|
-
const {
|
|
967
|
+
const { showNewsPanel } = useTheme();
|
|
883
968
|
const bottomRef = (0, import_react6.useRef)(null);
|
|
884
969
|
const textareaRef = (0, import_react6.useRef)(null);
|
|
885
970
|
const dropdownRef = (0, import_react6.useRef)(null);
|
|
@@ -892,40 +977,48 @@ function ChatWindow({
|
|
|
892
977
|
const [selectedSource, setSelectedSource] = (0, import_react6.useState)(null);
|
|
893
978
|
const [loadingSources, setLoadingSources] = (0, import_react6.useState)(false);
|
|
894
979
|
const [scraping, setScraping] = (0, import_react6.useState)(false);
|
|
895
|
-
const [editModal, setEditModal] = (0, import_react6.useState)({ isOpen: false, content: "", metaKeywords: [], messageId: "" });
|
|
980
|
+
const [editModal, setEditModal] = (0, import_react6.useState)({ isOpen: false, title: "", subtitle: "", content: "", metaDescription: "", metaKeywords: [], messageId: "" });
|
|
896
981
|
const { primaryColor } = useTheme();
|
|
897
982
|
const { preferences } = usePreferences();
|
|
898
983
|
const preferredLanguage = (_a = preferences == null ? void 0 : preferences.localization) == null ? void 0 : _a.language;
|
|
899
|
-
const handleCopy = async (
|
|
984
|
+
const handleCopy = async (parsed, messageId) => {
|
|
900
985
|
try {
|
|
901
|
-
const
|
|
902
|
-
|
|
986
|
+
const tempDiv = document.createElement("div");
|
|
987
|
+
let textContent = "";
|
|
988
|
+
if (parsed.title) textContent += parsed.title + "\n\n";
|
|
989
|
+
if (parsed.subtitle) textContent += parsed.subtitle + "\n\n";
|
|
990
|
+
if (parsed.articleHtml) {
|
|
991
|
+
tempDiv.innerHTML = parsed.articleHtml;
|
|
992
|
+
textContent += tempDiv.textContent || tempDiv.innerText || "";
|
|
993
|
+
}
|
|
994
|
+
if (parsed.metaDescription) textContent += "\n\nMeta Description:\n" + parsed.metaDescription;
|
|
995
|
+
await navigator.clipboard.writeText(textContent);
|
|
903
996
|
setCopiedId(messageId);
|
|
904
997
|
setTimeout(() => setCopiedId(null), 2e3);
|
|
905
998
|
} catch (err) {
|
|
906
999
|
console.error("Failed to copy:", err);
|
|
907
1000
|
}
|
|
908
1001
|
};
|
|
909
|
-
const
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1002
|
+
const handleEdit = (parsed, messageId) => {
|
|
1003
|
+
setEditModal({
|
|
1004
|
+
isOpen: true,
|
|
1005
|
+
title: parsed.title || "",
|
|
1006
|
+
subtitle: parsed.subtitle || "",
|
|
1007
|
+
content: parsed.articleHtml || "",
|
|
1008
|
+
metaDescription: parsed.metaDescription || "",
|
|
1009
|
+
metaKeywords: parsed.metaKeywords,
|
|
1010
|
+
messageId
|
|
1011
|
+
});
|
|
919
1012
|
};
|
|
920
1013
|
const handleCloseModal = () => {
|
|
921
|
-
setEditModal({ isOpen: false, content: "", metaKeywords: [], messageId: "" });
|
|
1014
|
+
setEditModal({ isOpen: false, title: "", subtitle: "", content: "", metaDescription: "", metaKeywords: [], messageId: "" });
|
|
922
1015
|
};
|
|
923
|
-
const handleSaveDraft = (
|
|
924
|
-
console.log("Saving draft:",
|
|
1016
|
+
const handleSaveDraft = (data) => {
|
|
1017
|
+
console.log("Saving draft:", data);
|
|
925
1018
|
handleCloseModal();
|
|
926
1019
|
};
|
|
927
|
-
const handlePost = (
|
|
928
|
-
onPostCallback == null ? void 0 : onPostCallback(
|
|
1020
|
+
const handlePost = (data) => {
|
|
1021
|
+
onPostCallback == null ? void 0 : onPostCallback(data.article, data.keywords);
|
|
929
1022
|
handleCloseModal();
|
|
930
1023
|
};
|
|
931
1024
|
(0, import_react6.useLayoutEffect)(() => {
|
|
@@ -989,7 +1082,6 @@ function ChatWindow({
|
|
|
989
1082
|
const handleSourceSelect = (option) => {
|
|
990
1083
|
var _a2;
|
|
991
1084
|
const sourceId = (_a2 = option == null ? void 0 : option.value) != null ? _a2 : null;
|
|
992
|
-
console.log("Selected source:", option);
|
|
993
1085
|
setSelectedSource(sourceId);
|
|
994
1086
|
fetchNews(sourceId);
|
|
995
1087
|
};
|
|
@@ -1015,130 +1107,103 @@ function ChatWindow({
|
|
|
1015
1107
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
1016
1108
|
};
|
|
1017
1109
|
}, [showNewsDropdown]);
|
|
1018
|
-
function formatAIContent(raw) {
|
|
1019
|
-
const extracted = extractArticleContent(raw);
|
|
1020
|
-
if (!extracted || !extracted.article) {
|
|
1021
|
-
return { blocks: [], metaKeywords: [] };
|
|
1022
|
-
}
|
|
1023
|
-
const { article, metaKeywords } = extracted;
|
|
1024
|
-
const normalized = article.replace(/^H1:\s*/gm, "").replace(/^H2:\s*/gm, "").replace(/<\/h1>/gi, "\n").replace(/<\/h2>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<br\s*\/?>/gi, "\n");
|
|
1025
|
-
const lines = normalized.split("\n").map((line) => line.replace(/<[^>]+>/g, "").trim()).filter(Boolean);
|
|
1026
|
-
const blocks = [];
|
|
1027
|
-
lines.forEach((line, index) => {
|
|
1028
|
-
if (index === 0 && line.length < 120) {
|
|
1029
|
-
blocks.push({ type: "h1", text: line });
|
|
1030
|
-
return;
|
|
1031
|
-
}
|
|
1032
|
-
if (line.length < 90 && !line.endsWith("\u0964") && !line.endsWith(".")) {
|
|
1033
|
-
blocks.push({ type: "h2", text: line });
|
|
1034
|
-
return;
|
|
1035
|
-
}
|
|
1036
|
-
blocks.push({ type: "p", text: line });
|
|
1037
|
-
});
|
|
1038
|
-
return { blocks, metaKeywords };
|
|
1039
|
-
}
|
|
1040
1110
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-chat", children: [
|
|
1041
1111
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-chat-area", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-chat-scroll", children: [
|
|
1042
1112
|
messages.map((msg) => {
|
|
1043
|
-
var _a2;
|
|
1113
|
+
var _a2, _b2;
|
|
1044
1114
|
const parsed = formatAIContent(msg.content);
|
|
1045
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.
|
|
1046
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-
|
|
1047
|
-
"
|
|
1115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: msg.role === "assistant" ? `cnfy-msg-body` : `cnfy-msg-body you`, children: [
|
|
1116
|
+
msg.role === "assistant" && parsed.isArticle && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-copy-row", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1117
|
+
"button",
|
|
1048
1118
|
{
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
},
|
|
1053
|
-
children: msg.role === "assistant" ? "AI" : "You"
|
|
1119
|
+
onClick: () => handleCopy(parsed, msg.id),
|
|
1120
|
+
className: "cnfy-copy-btn",
|
|
1121
|
+
title: "Copy to clipboard",
|
|
1122
|
+
children: copiedId === msg.id ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Check, { size: 16, className: "cnfy-copy-icon--copied" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Copy, { size: 16 })
|
|
1054
1123
|
}
|
|
1055
1124
|
) }),
|
|
1056
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-
|
|
1057
|
-
|
|
1058
|
-
|
|
1125
|
+
msg.role === "assistant" && isStreaming && msg.id === ((_a2 = messages[messages.length - 1]) == null ? void 0 : _a2.id) && !parsed.isArticle && !parsed.plainText && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-creating-indicator", children: [
|
|
1126
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Loader2, { size: 16, className: "cnfy-animate-spin" }),
|
|
1127
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Creating article..." })
|
|
1128
|
+
] }),
|
|
1129
|
+
parsed.isArticle ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1130
|
+
parsed.title && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("h1", { className: "cnfy-block-h1", children: [
|
|
1131
|
+
parsed.title,
|
|
1132
|
+
activeField === "title" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "cnfy-cursor-blink", children: "|" })
|
|
1133
|
+
] }),
|
|
1134
|
+
parsed.subtitle && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("h1", { className: "cnfy-block-h2", children: [
|
|
1135
|
+
parsed.subtitle,
|
|
1136
|
+
activeField === "subtitle" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "cnfy-cursor-blink", children: "|" })
|
|
1137
|
+
] }),
|
|
1138
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("hr", { className: "cnfy-divider" }),
|
|
1139
|
+
parsed.articleHtml && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1140
|
+
"div",
|
|
1059
1141
|
{
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
title: "Copy to clipboard",
|
|
1063
|
-
children: copiedId === msg.id ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Check, { size: 16, className: "cnfy-copy-icon--copied" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Copy, { size: 16 })
|
|
1142
|
+
className: "cnfy-article-content",
|
|
1143
|
+
dangerouslySetInnerHTML: { __html: parsed.articleHtml }
|
|
1064
1144
|
}
|
|
1065
|
-
)
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1079
|
-
"h2",
|
|
1080
|
-
{
|
|
1081
|
-
className: "cnfy-block-h2",
|
|
1082
|
-
children: block.text
|
|
1083
|
-
},
|
|
1084
|
-
idx
|
|
1085
|
-
);
|
|
1086
|
-
}
|
|
1087
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "cnfy-block-p", children: block.text }, idx);
|
|
1088
|
-
}),
|
|
1089
|
-
parsed.metaKeywords.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-keywords", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-keywords-list", children: parsed.metaKeywords.map((tag, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1145
|
+
),
|
|
1146
|
+
activeField === "article" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "cnfy-cursor-blink", children: "|" })
|
|
1147
|
+
] }) : (
|
|
1148
|
+
/* Plain text messages (status, error, options, etc.) */
|
|
1149
|
+
parsed.plainText && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "cnfy-block-p", children: parsed.plainText })
|
|
1150
|
+
),
|
|
1151
|
+
parsed.metaDescription && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-msg-keywords", children: [
|
|
1152
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-keywords-label", children: "Meta Description" }),
|
|
1153
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-block-p", children: parsed.metaDescription })
|
|
1154
|
+
] }),
|
|
1155
|
+
parsed.metaKeywords.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-msg-keywords", children: [
|
|
1156
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-keywords-label", children: "Keywords" }),
|
|
1157
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-keywords-list", children: parsed.metaKeywords.map((tag, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1090
1158
|
"span",
|
|
1091
1159
|
{
|
|
1092
1160
|
className: "cnfy-msg-keyword-tag",
|
|
1161
|
+
children: tag
|
|
1162
|
+
},
|
|
1163
|
+
i
|
|
1164
|
+
)) })
|
|
1165
|
+
] }),
|
|
1166
|
+
msg.role === "assistant" && (analyzedData == null ? void 0 : analyzedData.messageId) === msg.id && analyzedData.options.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-action-options", children: analyzedData.options.map((option) => {
|
|
1167
|
+
const IconComponent = ACTION_ICONS[option.id] || import_lucide_react4.FileText;
|
|
1168
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1169
|
+
"button",
|
|
1170
|
+
{
|
|
1171
|
+
onClick: () => onSelectAction == null ? void 0 : onSelectAction(option.id, analyzedData.url, analyzedData.content),
|
|
1172
|
+
className: "cnfy-action-btn",
|
|
1093
1173
|
children: [
|
|
1094
|
-
|
|
1095
|
-
|
|
1174
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconComponent, { size: 16 }),
|
|
1175
|
+
option.name
|
|
1096
1176
|
]
|
|
1097
1177
|
},
|
|
1098
|
-
|
|
1099
|
-
)
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
"
|
|
1118
|
-
{
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
}
|
|
1126
|
-
),
|
|
1127
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1128
|
-
"button",
|
|
1129
|
-
{
|
|
1130
|
-
onClick: () => handlePost(msg.content, parsed.metaKeywords),
|
|
1131
|
-
className: "cnfy-btn-post",
|
|
1132
|
-
style: { backgroundColor: primaryColor, color: "#fff" },
|
|
1133
|
-
children: [
|
|
1134
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Send, { size: 16 }),
|
|
1135
|
-
"Post"
|
|
1136
|
-
]
|
|
1137
|
-
}
|
|
1138
|
-
)
|
|
1139
|
-
] })
|
|
1178
|
+
option.id
|
|
1179
|
+
);
|
|
1180
|
+
}) }),
|
|
1181
|
+
msg.role === "assistant" && parsed.isArticle && !(analyzedData == null ? void 0 : analyzedData.messageId) && (!isStreaming || msg.id !== ((_b2 = messages[messages.length - 1]) == null ? void 0 : _b2.id)) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-msg-actions", children: [
|
|
1182
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1183
|
+
"button",
|
|
1184
|
+
{
|
|
1185
|
+
onClick: () => handleEdit(parsed, msg.id),
|
|
1186
|
+
className: "cnfy-btn-edit",
|
|
1187
|
+
children: [
|
|
1188
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Edit3, { size: 16 }),
|
|
1189
|
+
"Edit"
|
|
1190
|
+
]
|
|
1191
|
+
}
|
|
1192
|
+
),
|
|
1193
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1194
|
+
"button",
|
|
1195
|
+
{
|
|
1196
|
+
onClick: () => handlePost({ article: parsed.articleHtml, keywords: parsed.metaKeywords }),
|
|
1197
|
+
className: "cnfy-btn-post",
|
|
1198
|
+
style: { backgroundColor: primaryColor, color: "#fff" },
|
|
1199
|
+
children: [
|
|
1200
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Send, { size: 16 }),
|
|
1201
|
+
"Post"
|
|
1202
|
+
]
|
|
1203
|
+
}
|
|
1204
|
+
)
|
|
1140
1205
|
] })
|
|
1141
|
-
] }, msg.id);
|
|
1206
|
+
] }) }, msg.id);
|
|
1142
1207
|
}),
|
|
1143
1208
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: bottomRef })
|
|
1144
1209
|
] }) }),
|
|
@@ -1270,7 +1335,8 @@ function ChatWindow({
|
|
|
1270
1335
|
rows: 1,
|
|
1271
1336
|
placeholder: "Ask AI something\u2026",
|
|
1272
1337
|
className: `cnfy-chat-textarea ${!showNewsPanel ? "cnfy-chat-textarea--with-pulse" : ""}`,
|
|
1273
|
-
style: { maxHeight: "200px", overflowY: input.split("\n").length > 6 ? "auto" : "hidden" }
|
|
1338
|
+
style: { maxHeight: "200px", overflowY: input.split("\n").length > 6 ? "auto" : "hidden" },
|
|
1339
|
+
disabled: true
|
|
1274
1340
|
}
|
|
1275
1341
|
),
|
|
1276
1342
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
@@ -1287,11 +1353,14 @@ function ChatWindow({
|
|
|
1287
1353
|
EditModal,
|
|
1288
1354
|
{
|
|
1289
1355
|
isOpen: editModal.isOpen,
|
|
1356
|
+
initialTitle: editModal.title,
|
|
1357
|
+
initialSubtitle: editModal.subtitle,
|
|
1290
1358
|
initialContent: editModal.content,
|
|
1359
|
+
initialMetaDescription: editModal.metaDescription,
|
|
1291
1360
|
metaKeywords: editModal.metaKeywords,
|
|
1292
1361
|
onClose: handleCloseModal,
|
|
1293
|
-
onSaveDraft: handleSaveDraft,
|
|
1294
|
-
onPost: handlePost
|
|
1362
|
+
onSaveDraft: (data) => handleSaveDraft({ article: data.article, keywords: data.keywords }),
|
|
1363
|
+
onPost: (data) => handlePost({ article: data.article, keywords: data.keywords })
|
|
1295
1364
|
}
|
|
1296
1365
|
)
|
|
1297
1366
|
] });
|
|
@@ -1378,14 +1447,14 @@ var triggerScrape = async ({
|
|
|
1378
1447
|
state,
|
|
1379
1448
|
cities
|
|
1380
1449
|
}) => {
|
|
1381
|
-
const { data } = await api_default.post("/scrape/trigger", {
|
|
1450
|
+
const { data } = await api_default.post("/chatboat/scrape/trigger", {
|
|
1382
1451
|
state,
|
|
1383
1452
|
cities
|
|
1384
1453
|
});
|
|
1385
1454
|
return data;
|
|
1386
1455
|
};
|
|
1387
1456
|
var getScrapeStatus = async () => {
|
|
1388
|
-
const { data } = await api_default.get("/scrape/status");
|
|
1457
|
+
const { data } = await api_default.get("/chatboat/scrape/status");
|
|
1389
1458
|
return data.data;
|
|
1390
1459
|
};
|
|
1391
1460
|
|
|
@@ -1406,6 +1475,15 @@ var ClientSelect = (props) => {
|
|
|
1406
1475
|
};
|
|
1407
1476
|
var ClientSelect_default = ClientSelect;
|
|
1408
1477
|
|
|
1478
|
+
// src/utils/util.ts
|
|
1479
|
+
var hexToRgba = (hex, opacity) => {
|
|
1480
|
+
const sanitizedHex = hex.replace("#", "");
|
|
1481
|
+
const r = parseInt(sanitizedHex.substring(0, 2), 16);
|
|
1482
|
+
const g = parseInt(sanitizedHex.substring(2, 4), 16);
|
|
1483
|
+
const b = parseInt(sanitizedHex.substring(4, 6), 16);
|
|
1484
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
1485
|
+
};
|
|
1486
|
+
|
|
1409
1487
|
// components/preferences/Preferences.tsx
|
|
1410
1488
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1411
1489
|
var STATE_OPTIONS = [
|
|
@@ -1441,23 +1519,6 @@ var LANGUAGE_OPTIONS = [
|
|
|
1441
1519
|
{ value: "en", label: "English" },
|
|
1442
1520
|
{ value: "hi", label: "Hindi" }
|
|
1443
1521
|
];
|
|
1444
|
-
var TONE_OPTIONS = [
|
|
1445
|
-
{ value: "formal", label: "Formal" },
|
|
1446
|
-
{ value: "casual", label: "Casual" },
|
|
1447
|
-
{ value: "engaging", label: "Engaging" },
|
|
1448
|
-
{ value: "professional", label: "Professional" }
|
|
1449
|
-
];
|
|
1450
|
-
var STYLE_OPTIONS = [
|
|
1451
|
-
{ value: "news", label: "News Article" },
|
|
1452
|
-
{ value: "blog", label: "Blog Post" },
|
|
1453
|
-
{ value: "editorial", label: "Editorial" },
|
|
1454
|
-
{ value: "summary", label: "Summary" }
|
|
1455
|
-
];
|
|
1456
|
-
var WORD_COUNT_OPTIONS = [
|
|
1457
|
-
{ value: "short", label: "Short (~300 words)" },
|
|
1458
|
-
{ value: "medium", label: "Medium (~600 words)" },
|
|
1459
|
-
{ value: "long", label: "Long (~1000+ words)" }
|
|
1460
|
-
];
|
|
1461
1522
|
function PreferencesPage() {
|
|
1462
1523
|
var _a, _b, _c;
|
|
1463
1524
|
const { preferences, loading, refreshPreferences, updatePreferences } = usePreferences();
|
|
@@ -1468,12 +1529,6 @@ function PreferencesPage() {
|
|
|
1468
1529
|
const [state, setState] = (0, import_react9.useState)(null);
|
|
1469
1530
|
const [cities, setCities] = (0, import_react9.useState)([]);
|
|
1470
1531
|
const [language, setLanguage] = (0, import_react9.useState)(null);
|
|
1471
|
-
const [tone, setTone] = (0, import_react9.useState)(null);
|
|
1472
|
-
const [style, setStyle] = (0, import_react9.useState)(null);
|
|
1473
|
-
const [wordCount, setWordCount] = (0, import_react9.useState)(null);
|
|
1474
|
-
const [includeQuotes, setIncludeQuotes] = (0, import_react9.useState)(true);
|
|
1475
|
-
const [includeFAQ, setIncludeFAQ] = (0, import_react9.useState)(false);
|
|
1476
|
-
const [targetAudience, setTargetAudience] = (0, import_react9.useState)("");
|
|
1477
1532
|
const [saving, setSaving] = (0, import_react9.useState)(false);
|
|
1478
1533
|
const [success, setSuccess] = (0, import_react9.useState)(false);
|
|
1479
1534
|
const [scraping, setScraping] = (0, import_react9.useState)(false);
|
|
@@ -1483,13 +1538,7 @@ function PreferencesPage() {
|
|
|
1483
1538
|
botName: "",
|
|
1484
1539
|
state: void 0,
|
|
1485
1540
|
cities: [],
|
|
1486
|
-
language: void 0
|
|
1487
|
-
tone: void 0,
|
|
1488
|
-
style: void 0,
|
|
1489
|
-
wordCount: void 0,
|
|
1490
|
-
includeQuotes: true,
|
|
1491
|
-
includeFAQ: false,
|
|
1492
|
-
targetAudience: ""
|
|
1541
|
+
language: void 0
|
|
1493
1542
|
});
|
|
1494
1543
|
(0, import_react9.useEffect)(() => {
|
|
1495
1544
|
const fetchScrapeStatus = async () => {
|
|
@@ -1529,7 +1578,7 @@ function PreferencesPage() {
|
|
|
1529
1578
|
}
|
|
1530
1579
|
};
|
|
1531
1580
|
(0, import_react9.useEffect)(() => {
|
|
1532
|
-
var _a2, _b2, _c2, _d, _e
|
|
1581
|
+
var _a2, _b2, _c2, _d, _e;
|
|
1533
1582
|
if (preferences) {
|
|
1534
1583
|
const name = ((_a2 = preferences.chatbot) == null ? void 0 : _a2.name) || "";
|
|
1535
1584
|
const pState = (_b2 = preferences.localization) == null ? void 0 : _b2.state;
|
|
@@ -1547,38 +1596,11 @@ function PreferencesPage() {
|
|
|
1547
1596
|
const langOption = LANGUAGE_OPTIONS.find((opt) => opt.value === pLanguage);
|
|
1548
1597
|
setLanguage(langOption || null);
|
|
1549
1598
|
}
|
|
1550
|
-
const pTone = (_f = preferences.content) == null ? void 0 : _f.tone;
|
|
1551
|
-
const pStyle = (_g = preferences.content) == null ? void 0 : _g.style;
|
|
1552
|
-
const pWordCount = (_h = preferences.content) == null ? void 0 : _h.wordCount;
|
|
1553
|
-
const pIncludeQuotes = (_j = (_i = preferences.content) == null ? void 0 : _i.includeQuotes) != null ? _j : true;
|
|
1554
|
-
const pIncludeFAQ = (_l = (_k = preferences.content) == null ? void 0 : _k.includeFAQ) != null ? _l : false;
|
|
1555
|
-
const pTargetAudience = ((_m = preferences.content) == null ? void 0 : _m.targetAudience) || "";
|
|
1556
|
-
if (pTone) {
|
|
1557
|
-
const toneOption = TONE_OPTIONS.find((opt) => opt.value === pTone);
|
|
1558
|
-
setTone(toneOption || null);
|
|
1559
|
-
}
|
|
1560
|
-
if (pStyle) {
|
|
1561
|
-
const styleOption = STYLE_OPTIONS.find((opt) => opt.value === pStyle);
|
|
1562
|
-
setStyle(styleOption || null);
|
|
1563
|
-
}
|
|
1564
|
-
if (pWordCount) {
|
|
1565
|
-
const wordCountOption = WORD_COUNT_OPTIONS.find((opt) => opt.value === pWordCount);
|
|
1566
|
-
setWordCount(wordCountOption || null);
|
|
1567
|
-
}
|
|
1568
|
-
setIncludeQuotes(pIncludeQuotes);
|
|
1569
|
-
setIncludeFAQ(pIncludeFAQ);
|
|
1570
|
-
setTargetAudience(pTargetAudience);
|
|
1571
1599
|
setOriginalValues({
|
|
1572
1600
|
botName: name,
|
|
1573
1601
|
state: pState,
|
|
1574
1602
|
cities: pCities,
|
|
1575
|
-
language: pLanguage
|
|
1576
|
-
tone: pTone,
|
|
1577
|
-
style: pStyle,
|
|
1578
|
-
wordCount: pWordCount,
|
|
1579
|
-
includeQuotes: pIncludeQuotes,
|
|
1580
|
-
includeFAQ: pIncludeFAQ,
|
|
1581
|
-
targetAudience: pTargetAudience
|
|
1603
|
+
language: pLanguage
|
|
1582
1604
|
});
|
|
1583
1605
|
}
|
|
1584
1606
|
}, [preferences]);
|
|
@@ -1610,27 +1632,6 @@ function PreferencesPage() {
|
|
|
1610
1632
|
if (currentLanguage !== originalValues.language) {
|
|
1611
1633
|
payload.language = currentLanguage;
|
|
1612
1634
|
}
|
|
1613
|
-
const currentTone = tone == null ? void 0 : tone.value;
|
|
1614
|
-
if (currentTone !== originalValues.tone) {
|
|
1615
|
-
payload.tone = currentTone;
|
|
1616
|
-
}
|
|
1617
|
-
const currentStyle = style == null ? void 0 : style.value;
|
|
1618
|
-
if (currentStyle !== originalValues.style) {
|
|
1619
|
-
payload.style = currentStyle;
|
|
1620
|
-
}
|
|
1621
|
-
const currentWordCount = wordCount == null ? void 0 : wordCount.value;
|
|
1622
|
-
if (currentWordCount !== originalValues.wordCount) {
|
|
1623
|
-
payload.wordCount = currentWordCount;
|
|
1624
|
-
}
|
|
1625
|
-
if (includeQuotes !== originalValues.includeQuotes) {
|
|
1626
|
-
payload.includeQuotes = includeQuotes;
|
|
1627
|
-
}
|
|
1628
|
-
if (includeFAQ !== originalValues.includeFAQ) {
|
|
1629
|
-
payload.includeFAQ = includeFAQ;
|
|
1630
|
-
}
|
|
1631
|
-
if (targetAudience !== originalValues.targetAudience) {
|
|
1632
|
-
payload.targetAudience = targetAudience;
|
|
1633
|
-
}
|
|
1634
1635
|
if (Object.keys(payload).length === 0) {
|
|
1635
1636
|
import_react_hot_toast.default.error("No changes to save");
|
|
1636
1637
|
setSaving(false);
|
|
@@ -1703,150 +1704,6 @@ function PreferencesPage() {
|
|
|
1703
1704
|
] })
|
|
1704
1705
|
] })
|
|
1705
1706
|
] }),
|
|
1706
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-card", children: [
|
|
1707
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "cnfy-dash-card-title", children: "Localization Settings" }),
|
|
1708
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
|
|
1709
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "State" }),
|
|
1710
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1711
|
-
ClientSelect_default,
|
|
1712
|
-
{
|
|
1713
|
-
options: STATE_OPTIONS,
|
|
1714
|
-
value: state,
|
|
1715
|
-
onChange: (option) => setState(option),
|
|
1716
|
-
placeholder: "Select state"
|
|
1717
|
-
}
|
|
1718
|
-
)
|
|
1719
|
-
] }),
|
|
1720
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
|
|
1721
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Cities" }),
|
|
1722
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1723
|
-
ClientSelect_default,
|
|
1724
|
-
{
|
|
1725
|
-
isMulti: true,
|
|
1726
|
-
options: CITY_OPTIONS,
|
|
1727
|
-
value: cities,
|
|
1728
|
-
onChange: (options) => setCities(options),
|
|
1729
|
-
placeholder: "Select cities",
|
|
1730
|
-
isDisabled: !state
|
|
1731
|
-
}
|
|
1732
|
-
)
|
|
1733
|
-
] }),
|
|
1734
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
|
|
1735
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Language" }),
|
|
1736
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1737
|
-
ClientSelect_default,
|
|
1738
|
-
{
|
|
1739
|
-
options: LANGUAGE_OPTIONS,
|
|
1740
|
-
value: language,
|
|
1741
|
-
onChange: (option) => setLanguage(option),
|
|
1742
|
-
placeholder: "Select language"
|
|
1743
|
-
}
|
|
1744
|
-
)
|
|
1745
|
-
] })
|
|
1746
|
-
] }),
|
|
1747
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-card", children: [
|
|
1748
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "cnfy-dash-card-title", children: "Content Generation Settings" }),
|
|
1749
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
|
|
1750
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Tone" }),
|
|
1751
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1752
|
-
ClientSelect_default,
|
|
1753
|
-
{
|
|
1754
|
-
options: TONE_OPTIONS,
|
|
1755
|
-
value: tone,
|
|
1756
|
-
onChange: (option) => setTone(option),
|
|
1757
|
-
placeholder: "Select tone"
|
|
1758
|
-
}
|
|
1759
|
-
),
|
|
1760
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-hint", children: "The writing tone for generated content" })
|
|
1761
|
-
] }),
|
|
1762
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
|
|
1763
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Style" }),
|
|
1764
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1765
|
-
ClientSelect_default,
|
|
1766
|
-
{
|
|
1767
|
-
options: STYLE_OPTIONS,
|
|
1768
|
-
value: style,
|
|
1769
|
-
onChange: (option) => setStyle(option),
|
|
1770
|
-
placeholder: "Select style"
|
|
1771
|
-
}
|
|
1772
|
-
),
|
|
1773
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-hint", children: "The format/style of generated articles" })
|
|
1774
|
-
] }),
|
|
1775
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
|
|
1776
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Word Count" }),
|
|
1777
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1778
|
-
ClientSelect_default,
|
|
1779
|
-
{
|
|
1780
|
-
options: WORD_COUNT_OPTIONS,
|
|
1781
|
-
value: wordCount,
|
|
1782
|
-
onChange: (option) => setWordCount(option),
|
|
1783
|
-
placeholder: "Select word count"
|
|
1784
|
-
}
|
|
1785
|
-
),
|
|
1786
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-hint", children: "Target length for generated content" })
|
|
1787
|
-
] }),
|
|
1788
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
|
|
1789
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Target Audience" }),
|
|
1790
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1791
|
-
"input",
|
|
1792
|
-
{
|
|
1793
|
-
value: targetAudience,
|
|
1794
|
-
onChange: (e) => setTargetAudience(e.target.value),
|
|
1795
|
-
className: "cnfy-dash-input",
|
|
1796
|
-
placeholder: "e.g. tech-savvy millennials, business professionals"
|
|
1797
|
-
}
|
|
1798
|
-
),
|
|
1799
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-hint", children: "Describe your target audience for personalized content" })
|
|
1800
|
-
] }),
|
|
1801
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-toggle-group", children: [
|
|
1802
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-toggle-row", children: [
|
|
1803
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
|
|
1804
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-toggle-label", children: "Include Quotes" }),
|
|
1805
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-toggle-desc", children: "Add relevant quotes to generated articles" })
|
|
1806
|
-
] }),
|
|
1807
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1808
|
-
"button",
|
|
1809
|
-
{
|
|
1810
|
-
type: "button",
|
|
1811
|
-
role: "switch",
|
|
1812
|
-
"aria-checked": includeQuotes,
|
|
1813
|
-
onClick: () => setIncludeQuotes(!includeQuotes),
|
|
1814
|
-
className: "cnfy-toggle",
|
|
1815
|
-
style: { backgroundColor: includeQuotes ? primaryColor : "#d1d5db" },
|
|
1816
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1817
|
-
"span",
|
|
1818
|
-
{
|
|
1819
|
-
className: `cnfy-toggle-thumb ${includeQuotes ? "cnfy-toggle-thumb--on" : ""}`
|
|
1820
|
-
}
|
|
1821
|
-
)
|
|
1822
|
-
}
|
|
1823
|
-
)
|
|
1824
|
-
] }),
|
|
1825
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-toggle-row", children: [
|
|
1826
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
|
|
1827
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-toggle-label", children: "Include FAQ Section" }),
|
|
1828
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-toggle-desc", children: "Add FAQ section at the end of articles" })
|
|
1829
|
-
] }),
|
|
1830
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1831
|
-
"button",
|
|
1832
|
-
{
|
|
1833
|
-
type: "button",
|
|
1834
|
-
role: "switch",
|
|
1835
|
-
"aria-checked": includeFAQ,
|
|
1836
|
-
onClick: () => setIncludeFAQ(!includeFAQ),
|
|
1837
|
-
className: "cnfy-toggle",
|
|
1838
|
-
style: { backgroundColor: includeFAQ ? primaryColor : "#d1d5db" },
|
|
1839
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1840
|
-
"span",
|
|
1841
|
-
{
|
|
1842
|
-
className: `cnfy-toggle-thumb ${includeFAQ ? "cnfy-toggle-thumb--on" : ""}`
|
|
1843
|
-
}
|
|
1844
|
-
)
|
|
1845
|
-
}
|
|
1846
|
-
)
|
|
1847
|
-
] })
|
|
1848
|
-
] })
|
|
1849
|
-
] }),
|
|
1850
1707
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-card", children: [
|
|
1851
1708
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-card-header", children: [
|
|
1852
1709
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "cnfy-dash-card-title-inline", children: "News Scraping" }),
|
|
@@ -1884,35 +1741,133 @@ function PreferencesPage() {
|
|
|
1884
1741
|
onClick: handleScrape,
|
|
1885
1742
|
disabled: scraping || (scrapeStatus == null ? void 0 : scrapeStatus.isRunning),
|
|
1886
1743
|
className: "cnfy-dash-btn-save",
|
|
1887
|
-
style: { backgroundColor: primaryColor },
|
|
1744
|
+
style: { backgroundColor: hexToRgba(primaryColor, 0.8) },
|
|
1888
1745
|
children: scraping ? "Starting Scrape..." : (scrapeStatus == null ? void 0 : scrapeStatus.isRunning) ? "Scraping in Progress..." : "Start Scraping"
|
|
1889
1746
|
}
|
|
1890
1747
|
)
|
|
1891
1748
|
] })
|
|
1892
1749
|
] }),
|
|
1893
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-
|
|
1894
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1895
|
-
|
|
1896
|
-
{
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1750
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-card", children: [
|
|
1751
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "cnfy-dash-card-title", children: "Localization Settings" }),
|
|
1752
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
|
|
1753
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "State" }),
|
|
1754
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1755
|
+
ClientSelect_default,
|
|
1756
|
+
{
|
|
1757
|
+
options: STATE_OPTIONS,
|
|
1758
|
+
value: state,
|
|
1759
|
+
onChange: (option) => setState(option),
|
|
1760
|
+
placeholder: "Select state"
|
|
1761
|
+
}
|
|
1762
|
+
)
|
|
1763
|
+
] }),
|
|
1764
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
|
|
1765
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Cities" }),
|
|
1766
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1767
|
+
ClientSelect_default,
|
|
1768
|
+
{
|
|
1769
|
+
isMulti: true,
|
|
1770
|
+
options: CITY_OPTIONS,
|
|
1771
|
+
value: cities,
|
|
1772
|
+
onChange: (options) => setCities(options),
|
|
1773
|
+
placeholder: "Select cities",
|
|
1774
|
+
isDisabled: !state
|
|
1775
|
+
}
|
|
1776
|
+
)
|
|
1777
|
+
] }),
|
|
1778
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
|
|
1779
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Language" }),
|
|
1780
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1781
|
+
ClientSelect_default,
|
|
1782
|
+
{
|
|
1783
|
+
options: LANGUAGE_OPTIONS,
|
|
1784
|
+
value: language,
|
|
1785
|
+
onChange: (option) => setLanguage(option),
|
|
1786
|
+
placeholder: "Select language"
|
|
1787
|
+
}
|
|
1788
|
+
)
|
|
1789
|
+
] })
|
|
1790
|
+
] }),
|
|
1791
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "cnfy-dash-actions", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1792
|
+
"button",
|
|
1793
|
+
{
|
|
1794
|
+
onClick: handleSave,
|
|
1795
|
+
disabled: saving,
|
|
1796
|
+
className: "cnfy-dash-btn-save",
|
|
1797
|
+
style: { backgroundColor: primaryColor },
|
|
1798
|
+
children: saving ? "Saving..." : "Save Preferences"
|
|
1799
|
+
}
|
|
1800
|
+
) })
|
|
1906
1801
|
] });
|
|
1907
1802
|
}
|
|
1908
1803
|
|
|
1909
1804
|
// services/chat.service.ts
|
|
1805
|
+
function getHeaders() {
|
|
1806
|
+
const apiKey = getApiKey();
|
|
1807
|
+
const headers = {
|
|
1808
|
+
"Content-Type": "application/json"
|
|
1809
|
+
};
|
|
1810
|
+
if (apiKey) {
|
|
1811
|
+
headers["x-api-key"] = apiKey;
|
|
1812
|
+
}
|
|
1813
|
+
return headers;
|
|
1814
|
+
}
|
|
1815
|
+
async function processSSEStream(reader, callbacks) {
|
|
1816
|
+
const decoder = new TextDecoder();
|
|
1817
|
+
let buffer = "";
|
|
1818
|
+
const processLines = (lines) => {
|
|
1819
|
+
var _a, _b, _c, _d, _e;
|
|
1820
|
+
for (const line of lines) {
|
|
1821
|
+
const trimmed = line.trim();
|
|
1822
|
+
if (!trimmed.startsWith("data: ")) continue;
|
|
1823
|
+
const data = trimmed.slice(6).trim();
|
|
1824
|
+
try {
|
|
1825
|
+
const event = JSON.parse(data);
|
|
1826
|
+
switch (event.type) {
|
|
1827
|
+
case "start":
|
|
1828
|
+
break;
|
|
1829
|
+
case "field_start":
|
|
1830
|
+
(_a = callbacks.onFieldStart) == null ? void 0 : _a.call(callbacks, event.field);
|
|
1831
|
+
break;
|
|
1832
|
+
case "content":
|
|
1833
|
+
callbacks.onContent(event.field, event.content);
|
|
1834
|
+
break;
|
|
1835
|
+
case "keywords":
|
|
1836
|
+
(_b = callbacks.onKeywords) == null ? void 0 : _b.call(callbacks, event.content);
|
|
1837
|
+
break;
|
|
1838
|
+
case "field_end":
|
|
1839
|
+
(_c = callbacks.onFieldEnd) == null ? void 0 : _c.call(callbacks, event.field);
|
|
1840
|
+
break;
|
|
1841
|
+
case "done":
|
|
1842
|
+
(_d = callbacks.onComplete) == null ? void 0 : _d.call(callbacks, event.data);
|
|
1843
|
+
return true;
|
|
1844
|
+
case "error":
|
|
1845
|
+
(_e = callbacks.onError) == null ? void 0 : _e.call(callbacks, new Error(event.message));
|
|
1846
|
+
return true;
|
|
1847
|
+
}
|
|
1848
|
+
} catch (e) {
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
return false;
|
|
1852
|
+
};
|
|
1853
|
+
while (true) {
|
|
1854
|
+
const { done, value } = await reader.read();
|
|
1855
|
+
if (done) break;
|
|
1856
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1857
|
+
const lines = buffer.split("\n");
|
|
1858
|
+
buffer = lines.pop() || "";
|
|
1859
|
+
if (processLines(lines)) return;
|
|
1860
|
+
}
|
|
1861
|
+
if (buffer.trim()) {
|
|
1862
|
+
processLines([buffer]);
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1910
1865
|
var analyzeInputApi = async (input) => {
|
|
1911
|
-
const { data } = await api_default.post("/
|
|
1866
|
+
const { data } = await api_default.post("/chatboat/analyze-input", { input });
|
|
1912
1867
|
return data.data;
|
|
1913
1868
|
};
|
|
1914
1869
|
var createContentApi = async (payload) => {
|
|
1915
|
-
const { data } = await api_default.post("/
|
|
1870
|
+
const { data } = await api_default.post("/chatboat/create-content", payload);
|
|
1916
1871
|
return data.data;
|
|
1917
1872
|
};
|
|
1918
1873
|
var createContentStreamApi = async ({
|
|
@@ -1920,22 +1875,18 @@ var createContentStreamApi = async ({
|
|
|
1920
1875
|
content,
|
|
1921
1876
|
actionId,
|
|
1922
1877
|
settings,
|
|
1923
|
-
|
|
1878
|
+
onFieldStart,
|
|
1879
|
+
onContent,
|
|
1880
|
+
onKeywords,
|
|
1881
|
+
onFieldEnd,
|
|
1924
1882
|
onComplete,
|
|
1925
1883
|
onError
|
|
1926
1884
|
}) => {
|
|
1927
1885
|
var _a;
|
|
1928
1886
|
const API_BASE_URL = getApiBaseUrl();
|
|
1929
|
-
const apiKey = getApiKey();
|
|
1930
|
-
const headers = {
|
|
1931
|
-
"Content-Type": "application/json"
|
|
1932
|
-
};
|
|
1933
|
-
if (apiKey) {
|
|
1934
|
-
headers["x-api-key"] = apiKey;
|
|
1935
|
-
}
|
|
1936
1887
|
const response = await fetch(`${API_BASE_URL}/chat/create-content/stream`, {
|
|
1937
1888
|
method: "POST",
|
|
1938
|
-
headers,
|
|
1889
|
+
headers: getHeaders(),
|
|
1939
1890
|
credentials: "include",
|
|
1940
1891
|
body: JSON.stringify({ url, content, actionId, settings })
|
|
1941
1892
|
});
|
|
@@ -1944,50 +1895,17 @@ var createContentStreamApi = async ({
|
|
|
1944
1895
|
throw new Error(`HTTP error! status: ${response.status} - ${errorText}`);
|
|
1945
1896
|
}
|
|
1946
1897
|
const reader = (_a = response.body) == null ? void 0 : _a.getReader();
|
|
1947
|
-
const decoder = new TextDecoder();
|
|
1948
1898
|
if (!reader) {
|
|
1949
1899
|
throw new Error("No reader available");
|
|
1950
1900
|
}
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
1960
|
-
buffer += chunk;
|
|
1961
|
-
const lines = buffer.split("\n");
|
|
1962
|
-
buffer = lines.pop() || "";
|
|
1963
|
-
for (const line of lines) {
|
|
1964
|
-
const trimmedLine = line.trim();
|
|
1965
|
-
if (trimmedLine === "") continue;
|
|
1966
|
-
hasReceivedData = true;
|
|
1967
|
-
if (trimmedLine.startsWith("data: ")) {
|
|
1968
|
-
const data = trimmedLine.slice(6).trim();
|
|
1969
|
-
if (data === "[DONE]") {
|
|
1970
|
-
onComplete == null ? void 0 : onComplete();
|
|
1971
|
-
return;
|
|
1972
|
-
}
|
|
1973
|
-
try {
|
|
1974
|
-
const parsed = JSON.parse(data);
|
|
1975
|
-
if (parsed.content) onChunk(parsed.content);
|
|
1976
|
-
else if (parsed.delta) onChunk(parsed.delta);
|
|
1977
|
-
else if (parsed.text) onChunk(parsed.text);
|
|
1978
|
-
else if (parsed.chunk) onChunk(parsed.chunk);
|
|
1979
|
-
else if (typeof parsed === "string") onChunk(parsed);
|
|
1980
|
-
} catch (e) {
|
|
1981
|
-
if (data) onChunk(data);
|
|
1982
|
-
}
|
|
1983
|
-
} else if (trimmedLine) {
|
|
1984
|
-
onChunk(trimmedLine + "\n");
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
}
|
|
1988
|
-
if (!hasReceivedData) {
|
|
1989
|
-
throw new Error("No data received from stream");
|
|
1990
|
-
}
|
|
1901
|
+
await processSSEStream(reader, {
|
|
1902
|
+
onFieldStart,
|
|
1903
|
+
onContent,
|
|
1904
|
+
onKeywords,
|
|
1905
|
+
onFieldEnd,
|
|
1906
|
+
onComplete,
|
|
1907
|
+
onError
|
|
1908
|
+
});
|
|
1991
1909
|
};
|
|
1992
1910
|
var rewriteNewsStreamApi = async ({
|
|
1993
1911
|
article,
|
|
@@ -1999,7 +1917,10 @@ var rewriteNewsStreamApi = async ({
|
|
|
1999
1917
|
includeQuotes,
|
|
2000
1918
|
includeFAQ,
|
|
2001
1919
|
targetAudience,
|
|
2002
|
-
|
|
1920
|
+
onFieldStart,
|
|
1921
|
+
onContent,
|
|
1922
|
+
onKeywords,
|
|
1923
|
+
onFieldEnd,
|
|
2003
1924
|
onComplete,
|
|
2004
1925
|
onError
|
|
2005
1926
|
}) => {
|
|
@@ -2008,9 +1929,7 @@ var rewriteNewsStreamApi = async ({
|
|
|
2008
1929
|
article,
|
|
2009
1930
|
language
|
|
2010
1931
|
};
|
|
2011
|
-
if (articleId)
|
|
2012
|
-
payload.articleId = articleId;
|
|
2013
|
-
}
|
|
1932
|
+
if (articleId) payload.articleId = articleId;
|
|
2014
1933
|
if (tone) payload.tone = tone;
|
|
2015
1934
|
if (style) payload.style = style;
|
|
2016
1935
|
if (wordCount) payload.wordCount = wordCount;
|
|
@@ -2019,102 +1938,42 @@ var rewriteNewsStreamApi = async ({
|
|
|
2019
1938
|
if (targetAudience) payload.targetAudience = targetAudience;
|
|
2020
1939
|
try {
|
|
2021
1940
|
const API_BASE_URL = getApiBaseUrl();
|
|
2022
|
-
const
|
|
2023
|
-
console.log("\u{1F680} Starting stream request to:", `${API_BASE_URL}/chat/rewrite/stream`);
|
|
2024
|
-
console.log("\u{1F4E6} Payload:", payload);
|
|
2025
|
-
const headers = {
|
|
2026
|
-
"Content-Type": "application/json"
|
|
2027
|
-
};
|
|
2028
|
-
if (apiKey) {
|
|
2029
|
-
headers["x-api-key"] = apiKey;
|
|
2030
|
-
}
|
|
2031
|
-
const response = await fetch(`${API_BASE_URL}/chat/rewrite/stream`, {
|
|
1941
|
+
const response = await fetch(`${API_BASE_URL}/chatboat/rewrite/stream`, {
|
|
2032
1942
|
method: "POST",
|
|
2033
|
-
headers,
|
|
1943
|
+
headers: getHeaders(),
|
|
2034
1944
|
credentials: "include",
|
|
2035
|
-
// Include cookies for authentication
|
|
2036
1945
|
body: JSON.stringify(payload)
|
|
2037
1946
|
});
|
|
2038
|
-
console.log("\u{1F4E1} Response status:", response.status);
|
|
2039
|
-
console.log("\u{1F4E1} Response headers:", Object.fromEntries(response.headers.entries()));
|
|
2040
1947
|
if (!response.ok) {
|
|
2041
1948
|
const errorText = await response.text();
|
|
2042
|
-
console.error("\u274C API Error:", response.status, errorText);
|
|
2043
1949
|
throw new Error(`HTTP error! status: ${response.status} - ${errorText}`);
|
|
2044
1950
|
}
|
|
1951
|
+
const contentType = response.headers.get("content-type") || "";
|
|
1952
|
+
if (contentType.includes("application/json")) {
|
|
1953
|
+
const json = await response.json();
|
|
1954
|
+
const data = json.data || json;
|
|
1955
|
+
onComplete == null ? void 0 : onComplete({
|
|
1956
|
+
title: data.title || "",
|
|
1957
|
+
subtitle: data.subtitle || "",
|
|
1958
|
+
article: data.article || "",
|
|
1959
|
+
metaDescription: data.metaDescription || "",
|
|
1960
|
+
metaKeywords: Array.isArray(data.metaKeywords) ? data.metaKeywords : []
|
|
1961
|
+
});
|
|
1962
|
+
return;
|
|
1963
|
+
}
|
|
2045
1964
|
const reader = (_a = response.body) == null ? void 0 : _a.getReader();
|
|
2046
|
-
const decoder = new TextDecoder();
|
|
2047
1965
|
if (!reader) {
|
|
2048
1966
|
throw new Error("No reader available");
|
|
2049
1967
|
}
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
}
|
|
2058
|
-
break;
|
|
2059
|
-
}
|
|
2060
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
2061
|
-
buffer += chunk;
|
|
2062
|
-
const lines = buffer.split("\n");
|
|
2063
|
-
buffer = lines.pop() || "";
|
|
2064
|
-
for (const line of lines) {
|
|
2065
|
-
const trimmedLine = line.trim();
|
|
2066
|
-
if (trimmedLine === "") continue;
|
|
2067
|
-
hasReceivedData = true;
|
|
2068
|
-
console.log("\u{1F4E8} Received line:", trimmedLine.substring(0, 100) + (trimmedLine.length > 100 ? "..." : ""));
|
|
2069
|
-
if (trimmedLine.startsWith("data: ")) {
|
|
2070
|
-
const data = trimmedLine.slice(6).trim();
|
|
2071
|
-
if (data === "[DONE]") {
|
|
2072
|
-
console.log("\u2705 Stream completed with [DONE] signal");
|
|
2073
|
-
onComplete == null ? void 0 : onComplete();
|
|
2074
|
-
return;
|
|
2075
|
-
}
|
|
2076
|
-
try {
|
|
2077
|
-
const parsed = JSON.parse(data);
|
|
2078
|
-
console.log("\u{1F4CB} Parsed JSON:", parsed);
|
|
2079
|
-
if (parsed.content) {
|
|
2080
|
-
onChunk(parsed.content);
|
|
2081
|
-
} else if (parsed.delta) {
|
|
2082
|
-
onChunk(parsed.delta);
|
|
2083
|
-
} else if (parsed.text) {
|
|
2084
|
-
onChunk(parsed.text);
|
|
2085
|
-
} else if (parsed.chunk) {
|
|
2086
|
-
onChunk(parsed.chunk);
|
|
2087
|
-
} else if (typeof parsed === "string") {
|
|
2088
|
-
onChunk(parsed);
|
|
2089
|
-
} else {
|
|
2090
|
-
console.warn("\u26A0\uFE0F Unknown JSON format:", parsed);
|
|
2091
|
-
}
|
|
2092
|
-
} catch (e) {
|
|
2093
|
-
console.log("\u{1F4DD} Non-JSON data, treating as plain text");
|
|
2094
|
-
if (data) {
|
|
2095
|
-
onChunk(data);
|
|
2096
|
-
}
|
|
2097
|
-
}
|
|
2098
|
-
} else {
|
|
2099
|
-
console.log("\u{1F4C4} Plain text chunk");
|
|
2100
|
-
if (trimmedLine) {
|
|
2101
|
-
onChunk(trimmedLine + "\n");
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
}
|
|
2106
|
-
if (!hasReceivedData) {
|
|
2107
|
-
console.error("\u274C No data received from stream");
|
|
2108
|
-
throw new Error("No data received from stream");
|
|
2109
|
-
}
|
|
2110
|
-
console.log("\u2705 Stream completed successfully");
|
|
2111
|
-
} catch (error) {
|
|
2112
|
-
console.error("\u274C Streaming error:", error);
|
|
2113
|
-
console.error("Error details:", {
|
|
2114
|
-
message: error.message,
|
|
2115
|
-
name: error.name,
|
|
2116
|
-
stack: error.stack
|
|
1968
|
+
await processSSEStream(reader, {
|
|
1969
|
+
onFieldStart,
|
|
1970
|
+
onContent,
|
|
1971
|
+
onKeywords,
|
|
1972
|
+
onFieldEnd,
|
|
1973
|
+
onComplete,
|
|
1974
|
+
onError
|
|
2117
1975
|
});
|
|
1976
|
+
} catch (error) {
|
|
2118
1977
|
onError == null ? void 0 : onError(error);
|
|
2119
1978
|
throw error;
|
|
2120
1979
|
}
|
|
@@ -2134,16 +1993,14 @@ var rewriteNewsApi = async ({
|
|
|
2134
1993
|
article,
|
|
2135
1994
|
language
|
|
2136
1995
|
};
|
|
2137
|
-
if (articleId)
|
|
2138
|
-
payload.articleId = articleId;
|
|
2139
|
-
}
|
|
1996
|
+
if (articleId) payload.articleId = articleId;
|
|
2140
1997
|
if (tone) payload.tone = tone;
|
|
2141
1998
|
if (style) payload.style = style;
|
|
2142
1999
|
if (wordCount) payload.wordCount = wordCount;
|
|
2143
2000
|
if (includeQuotes !== void 0) payload.includeQuotes = includeQuotes;
|
|
2144
2001
|
if (includeFAQ !== void 0) payload.includeFAQ = includeFAQ;
|
|
2145
2002
|
if (targetAudience) payload.targetAudience = targetAudience;
|
|
2146
|
-
const { data } = await api_default.post("/
|
|
2003
|
+
const { data } = await api_default.post("/chatboat/rewrite", payload);
|
|
2147
2004
|
return data.data;
|
|
2148
2005
|
};
|
|
2149
2006
|
|
|
@@ -2151,12 +2008,16 @@ var rewriteNewsApi = async ({
|
|
|
2151
2008
|
var import_react_hot_toast2 = __toESM(require("react-hot-toast"));
|
|
2152
2009
|
var import_lucide_react7 = require("lucide-react");
|
|
2153
2010
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2011
|
+
function buildStructuredContent(title, article, metaKeywords, subtitle = "", metaDescription = "") {
|
|
2012
|
+
return JSON.stringify({ title, subtitle, article, metaDescription, metaKeywords });
|
|
2013
|
+
}
|
|
2154
2014
|
function ChatBot({ onPost }) {
|
|
2155
2015
|
const { loading } = useTheme();
|
|
2156
2016
|
const { preferences } = usePreferences();
|
|
2157
2017
|
const [preferencesOpen, setPreferencesOpen] = (0, import_react10.useState)(false);
|
|
2158
2018
|
const [messages, setMessages] = (0, import_react10.useState)([]);
|
|
2159
2019
|
const [isStreaming, setIsStreaming] = (0, import_react10.useState)(false);
|
|
2020
|
+
const [activeField, setActiveField] = (0, import_react10.useState)(null);
|
|
2160
2021
|
const [analyzedData, setAnalyzedData] = (0, import_react10.useState)(null);
|
|
2161
2022
|
const handleRecreate = async ({ title, content, id }) => {
|
|
2162
2023
|
var _a;
|
|
@@ -2167,17 +2028,28 @@ function ChatBot({ onPost }) {
|
|
|
2167
2028
|
id: crypto.randomUUID(),
|
|
2168
2029
|
role: "user",
|
|
2169
2030
|
content: `Recreate this news:
|
|
2170
|
-
${title}`
|
|
2031
|
+
${title}`
|
|
2171
2032
|
},
|
|
2172
2033
|
{
|
|
2173
2034
|
id: assistantId,
|
|
2174
2035
|
role: "assistant",
|
|
2175
|
-
content: "
|
|
2036
|
+
content: ""
|
|
2176
2037
|
}
|
|
2177
2038
|
]);
|
|
2039
|
+
setIsStreaming(true);
|
|
2178
2040
|
try {
|
|
2179
|
-
let accumulatedContent = "";
|
|
2180
2041
|
let hasStartedStreaming = false;
|
|
2042
|
+
let titleBuffer = "";
|
|
2043
|
+
let articleBuffer = "";
|
|
2044
|
+
let keywordsBuffer = [];
|
|
2045
|
+
const updateMessage = () => {
|
|
2046
|
+
const structured = buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2047
|
+
setMessages(
|
|
2048
|
+
(prev) => prev.map(
|
|
2049
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2050
|
+
)
|
|
2051
|
+
);
|
|
2052
|
+
};
|
|
2181
2053
|
const contentPrefs = preferences == null ? void 0 : preferences.content;
|
|
2182
2054
|
const lang = ((_a = preferences == null ? void 0 : preferences.localization) == null ? void 0 : _a.language) === "hi" ? "Hindi" : "English";
|
|
2183
2055
|
try {
|
|
@@ -2191,39 +2063,66 @@ ${title}`
|
|
|
2191
2063
|
includeQuotes: contentPrefs == null ? void 0 : contentPrefs.includeQuotes,
|
|
2192
2064
|
includeFAQ: contentPrefs == null ? void 0 : contentPrefs.includeFAQ,
|
|
2193
2065
|
targetAudience: contentPrefs == null ? void 0 : contentPrefs.targetAudience,
|
|
2194
|
-
|
|
2066
|
+
onFieldStart: (field) => {
|
|
2067
|
+
setActiveField(field);
|
|
2068
|
+
},
|
|
2069
|
+
onContent: (field, chunk) => {
|
|
2195
2070
|
hasStartedStreaming = true;
|
|
2196
|
-
|
|
2071
|
+
if (field === "title") titleBuffer += chunk;
|
|
2072
|
+
else articleBuffer += chunk;
|
|
2073
|
+
updateMessage();
|
|
2074
|
+
},
|
|
2075
|
+
onKeywords: (keywords) => {
|
|
2076
|
+
keywordsBuffer = keywords;
|
|
2077
|
+
updateMessage();
|
|
2078
|
+
},
|
|
2079
|
+
onFieldEnd: () => {
|
|
2080
|
+
setActiveField(null);
|
|
2081
|
+
},
|
|
2082
|
+
onComplete: (data) => {
|
|
2083
|
+
const finalContent = data && (data.title || data.article) ? JSON.stringify(data) : buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2197
2084
|
setMessages(
|
|
2198
2085
|
(prev) => prev.map(
|
|
2199
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content:
|
|
2086
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: finalContent }) : m
|
|
2200
2087
|
)
|
|
2201
2088
|
);
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
console.log("Streaming completed successfully");
|
|
2089
|
+
setIsStreaming(false);
|
|
2090
|
+
setActiveField(null);
|
|
2205
2091
|
import_react_hot_toast2.default.success("Article created successfully!");
|
|
2206
2092
|
},
|
|
2207
2093
|
onError: async (error) => {
|
|
2208
2094
|
console.error("Streaming error:", error);
|
|
2209
2095
|
if (!hasStartedStreaming) {
|
|
2210
|
-
console.log("Falling back to regular API...");
|
|
2211
2096
|
throw error;
|
|
2212
2097
|
} else {
|
|
2098
|
+
setIsStreaming(false);
|
|
2099
|
+
setActiveField(null);
|
|
2213
2100
|
import_react_hot_toast2.default.error("Failed to complete article generation");
|
|
2214
2101
|
setMessages(
|
|
2215
2102
|
(prev) => prev.map(
|
|
2216
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content:
|
|
2103
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: titleBuffer || articleBuffer ? buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer) : "Failed to create article. Please try again." }) : m
|
|
2217
2104
|
)
|
|
2218
2105
|
);
|
|
2219
2106
|
}
|
|
2220
2107
|
}
|
|
2221
2108
|
});
|
|
2109
|
+
if (isStreaming) {
|
|
2110
|
+
if (titleBuffer || articleBuffer) {
|
|
2111
|
+
const structured = buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2112
|
+
setMessages(
|
|
2113
|
+
(prev) => prev.map(
|
|
2114
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2115
|
+
)
|
|
2116
|
+
);
|
|
2117
|
+
}
|
|
2118
|
+
setIsStreaming(false);
|
|
2119
|
+
setActiveField(null);
|
|
2120
|
+
}
|
|
2222
2121
|
} catch (streamError) {
|
|
2223
2122
|
console.log("Streaming failed, using regular API...", streamError);
|
|
2224
2123
|
setMessages(
|
|
2225
2124
|
(prev) => prev.map(
|
|
2226
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "
|
|
2125
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "" }) : m
|
|
2227
2126
|
)
|
|
2228
2127
|
);
|
|
2229
2128
|
const result = await rewriteNewsApi({
|
|
@@ -2239,17 +2138,20 @@ ${title}`
|
|
|
2239
2138
|
});
|
|
2240
2139
|
setMessages(
|
|
2241
2140
|
(prev) => prev.map(
|
|
2242
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: result
|
|
2141
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: typeof result === "string" ? result : JSON.stringify(result) }) : m
|
|
2243
2142
|
)
|
|
2244
2143
|
);
|
|
2144
|
+
setIsStreaming(false);
|
|
2245
2145
|
import_react_hot_toast2.default.success("Article created successfully!");
|
|
2246
2146
|
}
|
|
2247
2147
|
} catch (err) {
|
|
2248
2148
|
console.error("Complete Error:", err);
|
|
2149
|
+
setIsStreaming(false);
|
|
2150
|
+
setActiveField(null);
|
|
2249
2151
|
import_react_hot_toast2.default.error((err == null ? void 0 : err.message) || "An error occurred while creating the article");
|
|
2250
2152
|
setMessages(
|
|
2251
2153
|
(prev) => prev.map(
|
|
2252
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "
|
|
2154
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "Failed to create article. Please try again." }) : m
|
|
2253
2155
|
)
|
|
2254
2156
|
);
|
|
2255
2157
|
}
|
|
@@ -2267,9 +2169,10 @@ ${title}`
|
|
|
2267
2169
|
if (hasUrl) {
|
|
2268
2170
|
setMessages((prev) => [
|
|
2269
2171
|
...prev,
|
|
2270
|
-
{ id: assistantId, role: "assistant", content: "
|
|
2172
|
+
{ id: assistantId, role: "assistant", content: "Analyzing your link..." }
|
|
2271
2173
|
]);
|
|
2272
2174
|
try {
|
|
2175
|
+
return;
|
|
2273
2176
|
const result = await analyzeInputApi(text);
|
|
2274
2177
|
if (result.hasUrl && ((_a = result.options) == null ? void 0 : _a.length) > 0) {
|
|
2275
2178
|
setAnalyzedData({
|
|
@@ -2300,20 +2203,30 @@ ${optionsList}`
|
|
|
2300
2203
|
import_react_hot_toast2.default.error("Failed to analyze the link");
|
|
2301
2204
|
setMessages(
|
|
2302
2205
|
(prev) => prev.map(
|
|
2303
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "
|
|
2206
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "Failed to analyze the link. Please try again." }) : m
|
|
2304
2207
|
)
|
|
2305
2208
|
);
|
|
2306
2209
|
}
|
|
2307
2210
|
} else {
|
|
2308
2211
|
setMessages((prev) => [
|
|
2309
2212
|
...prev,
|
|
2310
|
-
{ id: assistantId, role: "assistant", content: "
|
|
2213
|
+
{ id: assistantId, role: "assistant", content: "" }
|
|
2311
2214
|
]);
|
|
2312
2215
|
setIsStreaming(true);
|
|
2313
2216
|
try {
|
|
2314
2217
|
const contentPrefs = preferences == null ? void 0 : preferences.content;
|
|
2315
2218
|
const lang = ((_b = preferences == null ? void 0 : preferences.localization) == null ? void 0 : _b.language) === "hi" ? "Hindi" : "English";
|
|
2316
|
-
let
|
|
2219
|
+
let titleBuffer = "";
|
|
2220
|
+
let articleBuffer = "";
|
|
2221
|
+
let keywordsBuffer = [];
|
|
2222
|
+
const updateMessage = () => {
|
|
2223
|
+
const structured = buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2224
|
+
setMessages(
|
|
2225
|
+
(prev) => prev.map(
|
|
2226
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2227
|
+
)
|
|
2228
|
+
);
|
|
2229
|
+
};
|
|
2317
2230
|
await rewriteNewsStreamApi({
|
|
2318
2231
|
article: text,
|
|
2319
2232
|
language: lang,
|
|
@@ -2323,30 +2236,58 @@ ${optionsList}`
|
|
|
2323
2236
|
includeQuotes: contentPrefs == null ? void 0 : contentPrefs.includeQuotes,
|
|
2324
2237
|
includeFAQ: contentPrefs == null ? void 0 : contentPrefs.includeFAQ,
|
|
2325
2238
|
targetAudience: contentPrefs == null ? void 0 : contentPrefs.targetAudience,
|
|
2326
|
-
|
|
2327
|
-
|
|
2239
|
+
onFieldStart: (field) => {
|
|
2240
|
+
setActiveField(field);
|
|
2241
|
+
},
|
|
2242
|
+
onContent: (field, chunk) => {
|
|
2243
|
+
if (field === "title") titleBuffer += chunk;
|
|
2244
|
+
else articleBuffer += chunk;
|
|
2245
|
+
updateMessage();
|
|
2246
|
+
},
|
|
2247
|
+
onKeywords: (keywords) => {
|
|
2248
|
+
keywordsBuffer = keywords;
|
|
2249
|
+
updateMessage();
|
|
2250
|
+
},
|
|
2251
|
+
onFieldEnd: () => {
|
|
2252
|
+
setActiveField(null);
|
|
2253
|
+
},
|
|
2254
|
+
onComplete: (data) => {
|
|
2255
|
+
const finalContent = data && (data.title || data.article) ? JSON.stringify(data) : buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2328
2256
|
setMessages(
|
|
2329
2257
|
(prev) => prev.map(
|
|
2330
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content:
|
|
2258
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: finalContent }) : m
|
|
2331
2259
|
)
|
|
2332
2260
|
);
|
|
2333
|
-
},
|
|
2334
|
-
onComplete: () => {
|
|
2335
2261
|
setIsStreaming(false);
|
|
2262
|
+
setActiveField(null);
|
|
2336
2263
|
import_react_hot_toast2.default.success("Content generated!");
|
|
2337
2264
|
},
|
|
2338
2265
|
onError: (error) => {
|
|
2339
2266
|
console.error("Stream error:", error);
|
|
2340
2267
|
setIsStreaming(false);
|
|
2268
|
+
setActiveField(null);
|
|
2341
2269
|
import_react_hot_toast2.default.error("Failed to generate content");
|
|
2342
2270
|
}
|
|
2343
2271
|
});
|
|
2272
|
+
if (isStreaming) {
|
|
2273
|
+
if (titleBuffer || articleBuffer) {
|
|
2274
|
+
const structured = buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2275
|
+
setMessages(
|
|
2276
|
+
(prev) => prev.map(
|
|
2277
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2278
|
+
)
|
|
2279
|
+
);
|
|
2280
|
+
}
|
|
2281
|
+
setIsStreaming(false);
|
|
2282
|
+
setActiveField(null);
|
|
2283
|
+
}
|
|
2344
2284
|
} catch (err) {
|
|
2345
2285
|
console.error("Send message error:", err);
|
|
2346
2286
|
setIsStreaming(false);
|
|
2287
|
+
setActiveField(null);
|
|
2347
2288
|
setMessages(
|
|
2348
2289
|
(prev) => prev.map(
|
|
2349
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "
|
|
2290
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "Failed to generate content. Please try again." }) : m
|
|
2350
2291
|
)
|
|
2351
2292
|
);
|
|
2352
2293
|
}
|
|
@@ -2360,12 +2301,22 @@ ${optionsList}`
|
|
|
2360
2301
|
setMessages((prev) => [
|
|
2361
2302
|
...prev,
|
|
2362
2303
|
{ id: crypto.randomUUID(), role: "user", content: `Action: ${actionName}` },
|
|
2363
|
-
{ id: assistantId, role: "assistant", content: "
|
|
2304
|
+
{ id: assistantId, role: "assistant", content: "" }
|
|
2364
2305
|
]);
|
|
2365
2306
|
setIsStreaming(true);
|
|
2366
2307
|
try {
|
|
2367
2308
|
const contentPrefs = preferences == null ? void 0 : preferences.content;
|
|
2368
|
-
let
|
|
2309
|
+
let titleBuffer = "";
|
|
2310
|
+
let articleBuffer = "";
|
|
2311
|
+
let keywordsBuffer = [];
|
|
2312
|
+
const updateMessage = () => {
|
|
2313
|
+
const structured = buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2314
|
+
setMessages(
|
|
2315
|
+
(prev) => prev.map(
|
|
2316
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2317
|
+
)
|
|
2318
|
+
);
|
|
2319
|
+
};
|
|
2369
2320
|
try {
|
|
2370
2321
|
await createContentStreamApi({
|
|
2371
2322
|
url,
|
|
@@ -2376,24 +2327,51 @@ ${optionsList}`
|
|
|
2376
2327
|
style: contentPrefs == null ? void 0 : contentPrefs.style,
|
|
2377
2328
|
wordCount: contentPrefs == null ? void 0 : contentPrefs.wordCount
|
|
2378
2329
|
},
|
|
2379
|
-
|
|
2380
|
-
|
|
2330
|
+
onFieldStart: (field) => {
|
|
2331
|
+
setActiveField(field);
|
|
2332
|
+
},
|
|
2333
|
+
onContent: (field, chunk) => {
|
|
2334
|
+
if (field === "title") titleBuffer += chunk;
|
|
2335
|
+
else articleBuffer += chunk;
|
|
2336
|
+
updateMessage();
|
|
2337
|
+
},
|
|
2338
|
+
onKeywords: (keywords) => {
|
|
2339
|
+
keywordsBuffer = keywords;
|
|
2340
|
+
updateMessage();
|
|
2341
|
+
},
|
|
2342
|
+
onFieldEnd: () => {
|
|
2343
|
+
setActiveField(null);
|
|
2344
|
+
},
|
|
2345
|
+
onComplete: (data) => {
|
|
2346
|
+
const finalContent = data && (data.title || data.article) ? JSON.stringify(data) : buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2381
2347
|
setMessages(
|
|
2382
2348
|
(prev) => prev.map(
|
|
2383
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content:
|
|
2349
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: finalContent }) : m
|
|
2384
2350
|
)
|
|
2385
2351
|
);
|
|
2386
|
-
},
|
|
2387
|
-
onComplete: () => {
|
|
2388
2352
|
setIsStreaming(false);
|
|
2353
|
+
setActiveField(null);
|
|
2389
2354
|
import_react_hot_toast2.default.success("Content created!");
|
|
2390
2355
|
},
|
|
2391
2356
|
onError: (error) => {
|
|
2392
2357
|
console.error("Stream error:", error);
|
|
2393
2358
|
setIsStreaming(false);
|
|
2359
|
+
setActiveField(null);
|
|
2394
2360
|
import_react_hot_toast2.default.error("Failed to create content");
|
|
2395
2361
|
}
|
|
2396
2362
|
});
|
|
2363
|
+
if (isStreaming) {
|
|
2364
|
+
if (titleBuffer || articleBuffer) {
|
|
2365
|
+
const structured = buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2366
|
+
setMessages(
|
|
2367
|
+
(prev) => prev.map(
|
|
2368
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2369
|
+
)
|
|
2370
|
+
);
|
|
2371
|
+
}
|
|
2372
|
+
setIsStreaming(false);
|
|
2373
|
+
setActiveField(null);
|
|
2374
|
+
}
|
|
2397
2375
|
} catch (e) {
|
|
2398
2376
|
const result = await createContentApi({ url, content, actionId, settings: {
|
|
2399
2377
|
tone: contentPrefs == null ? void 0 : contentPrefs.tone,
|
|
@@ -2402,18 +2380,20 @@ ${optionsList}`
|
|
|
2402
2380
|
} });
|
|
2403
2381
|
setMessages(
|
|
2404
2382
|
(prev) => prev.map(
|
|
2405
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: result
|
|
2383
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: typeof result === "string" ? result : JSON.stringify(result) }) : m
|
|
2406
2384
|
)
|
|
2407
2385
|
);
|
|
2408
2386
|
setIsStreaming(false);
|
|
2387
|
+
setActiveField(null);
|
|
2409
2388
|
import_react_hot_toast2.default.success("Content created!");
|
|
2410
2389
|
}
|
|
2411
2390
|
} catch (err) {
|
|
2412
2391
|
console.error("Create content error:", err);
|
|
2413
2392
|
setIsStreaming(false);
|
|
2393
|
+
setActiveField(null);
|
|
2414
2394
|
setMessages(
|
|
2415
2395
|
(prev) => prev.map(
|
|
2416
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "
|
|
2396
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "Failed to create content. Please try again." }) : m
|
|
2417
2397
|
)
|
|
2418
2398
|
);
|
|
2419
2399
|
}
|
|
@@ -2434,6 +2414,7 @@ ${optionsList}`
|
|
|
2434
2414
|
onSend: handleSendMessage,
|
|
2435
2415
|
onSelectNews: handleRecreate,
|
|
2436
2416
|
isStreaming,
|
|
2417
|
+
activeField,
|
|
2437
2418
|
analyzedData,
|
|
2438
2419
|
onSelectAction: handleSelectAction,
|
|
2439
2420
|
onPost
|