@contenify/chatbot 3.0.0 → 4.0.1
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 +70 -203
- package/dist/index.d.mts +1 -42
- package/dist/index.d.ts +1 -42
- package/dist/index.js +1693 -1225
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1677 -1209
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1311 -78
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -20,251 +20,10 @@ var __spreadValues = (a, b) => {
|
|
|
20
20
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
21
|
|
|
22
22
|
// src/index.tsx
|
|
23
|
-
import { useEffect as
|
|
24
|
-
|
|
25
|
-
// contexts/PreferencesContext.tsx
|
|
26
|
-
import { createContext, useContext, useState, useEffect } from "react";
|
|
27
|
-
|
|
28
|
-
// lib/api.ts
|
|
29
|
-
import axios from "axios";
|
|
30
|
-
|
|
31
|
-
// lib/config.ts
|
|
32
|
-
var _apiUrl = process.env.NEXT_PUBLIC_CONTENIFY_API_URL || "http://localhost:8080/api";
|
|
33
|
-
var _apiKey = process.env.NEXT_PUBLIC_API_KEY || "";
|
|
34
|
-
var _domain = process.env.NEXT_PUBLIC_DOMAIN || "";
|
|
35
|
-
function setConfig(config) {
|
|
36
|
-
if (config.apiUrl) _apiUrl = config.apiUrl;
|
|
37
|
-
if (config.apiKey) _apiKey = config.apiKey;
|
|
38
|
-
if (config.domain) _domain = config.domain;
|
|
39
|
-
}
|
|
40
|
-
function getApiBaseUrl() {
|
|
41
|
-
return _apiUrl;
|
|
42
|
-
}
|
|
43
|
-
function getServerBaseUrl() {
|
|
44
|
-
return _apiUrl.replace(/\/api\/?$/, "");
|
|
45
|
-
}
|
|
46
|
-
function getApiKey() {
|
|
47
|
-
return _apiKey;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// lib/api.ts
|
|
51
|
-
var api = axios.create({
|
|
52
|
-
baseURL: getApiBaseUrl(),
|
|
53
|
-
withCredentials: true,
|
|
54
|
-
headers: {
|
|
55
|
-
"Content-Type": "application/json"
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
api.interceptors.request.use(
|
|
59
|
-
(config) => {
|
|
60
|
-
const apiKey = getApiKey();
|
|
61
|
-
if (apiKey) {
|
|
62
|
-
config.headers["x-api-key"] = apiKey;
|
|
63
|
-
}
|
|
64
|
-
return config;
|
|
65
|
-
},
|
|
66
|
-
(error) => Promise.reject(error)
|
|
67
|
-
);
|
|
68
|
-
api.interceptors.response.use(
|
|
69
|
-
(response) => response,
|
|
70
|
-
(error) => {
|
|
71
|
-
var _a, _b;
|
|
72
|
-
const message = ((_b = (_a = error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message) || error.message || "Something went wrong";
|
|
73
|
-
return Promise.reject(message);
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
var api_default = api;
|
|
77
|
-
|
|
78
|
-
// services/preferences.service.ts
|
|
79
|
-
var getMyPreferencesApi = async () => {
|
|
80
|
-
const { data } = await api_default.get("/chatboat/preferences/me");
|
|
81
|
-
return data.data;
|
|
82
|
-
};
|
|
83
|
-
var savePreferencesApi = async ({
|
|
84
|
-
botName,
|
|
85
|
-
logo,
|
|
86
|
-
state,
|
|
87
|
-
cities,
|
|
88
|
-
primaryColor,
|
|
89
|
-
secondaryColor,
|
|
90
|
-
theme,
|
|
91
|
-
language,
|
|
92
|
-
showSidebar,
|
|
93
|
-
showHeader,
|
|
94
|
-
activeThemePreset,
|
|
95
|
-
showNewsPanel,
|
|
96
|
-
tone,
|
|
97
|
-
style,
|
|
98
|
-
wordCount,
|
|
99
|
-
includeQuotes,
|
|
100
|
-
includeFAQ,
|
|
101
|
-
targetAudience
|
|
102
|
-
}) => {
|
|
103
|
-
const formData = new FormData();
|
|
104
|
-
if (botName) {
|
|
105
|
-
formData.append("botName", botName);
|
|
106
|
-
}
|
|
107
|
-
if (logo) {
|
|
108
|
-
formData.append("logo", logo);
|
|
109
|
-
}
|
|
110
|
-
if (state) {
|
|
111
|
-
formData.append("state", state);
|
|
112
|
-
}
|
|
113
|
-
if (cities) {
|
|
114
|
-
formData.append("cities", JSON.stringify(cities));
|
|
115
|
-
}
|
|
116
|
-
if (primaryColor) {
|
|
117
|
-
formData.append("primaryColor", primaryColor);
|
|
118
|
-
}
|
|
119
|
-
if (secondaryColor) {
|
|
120
|
-
formData.append("secondaryColor", secondaryColor);
|
|
121
|
-
}
|
|
122
|
-
if (theme) {
|
|
123
|
-
formData.append("theme", theme);
|
|
124
|
-
}
|
|
125
|
-
if (language) {
|
|
126
|
-
formData.append("language", language);
|
|
127
|
-
}
|
|
128
|
-
if (showSidebar !== void 0) {
|
|
129
|
-
formData.append("showSidebar", String(showSidebar));
|
|
130
|
-
}
|
|
131
|
-
if (showHeader !== void 0) {
|
|
132
|
-
formData.append("showHeader", String(showHeader));
|
|
133
|
-
}
|
|
134
|
-
if (activeThemePreset !== void 0) {
|
|
135
|
-
formData.append("activeThemePreset", activeThemePreset != null ? activeThemePreset : "");
|
|
136
|
-
}
|
|
137
|
-
if (showNewsPanel !== void 0) {
|
|
138
|
-
formData.append("showNewsPanel", String(showNewsPanel));
|
|
139
|
-
}
|
|
140
|
-
if (tone) {
|
|
141
|
-
formData.append("tone", tone);
|
|
142
|
-
}
|
|
143
|
-
if (style) {
|
|
144
|
-
formData.append("style", style);
|
|
145
|
-
}
|
|
146
|
-
if (wordCount) {
|
|
147
|
-
formData.append("wordCount", wordCount);
|
|
148
|
-
}
|
|
149
|
-
if (includeQuotes !== void 0) {
|
|
150
|
-
formData.append("includeQuotes", String(includeQuotes));
|
|
151
|
-
}
|
|
152
|
-
if (includeFAQ !== void 0) {
|
|
153
|
-
formData.append("includeFAQ", String(includeFAQ));
|
|
154
|
-
}
|
|
155
|
-
if (targetAudience !== void 0) {
|
|
156
|
-
formData.append("targetAudience", targetAudience);
|
|
157
|
-
}
|
|
158
|
-
const { data } = await api_default.put("/chatboat/preferences", formData, {
|
|
159
|
-
headers: {
|
|
160
|
-
"Content-Type": "multipart/form-data"
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
return data.data;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
// contexts/PreferencesContext.tsx
|
|
167
|
-
import { jsx } from "react/jsx-runtime";
|
|
168
|
-
var defaultPreferences = {
|
|
169
|
-
chatbot: {
|
|
170
|
-
name: "ContenifyAI Assistant",
|
|
171
|
-
primaryColor: "#10b981",
|
|
172
|
-
secondaryColor: "#064e3b",
|
|
173
|
-
theme: "system"
|
|
174
|
-
},
|
|
175
|
-
localization: {
|
|
176
|
-
country: "India",
|
|
177
|
-
state: "Uttar Pradesh",
|
|
178
|
-
cities: [],
|
|
179
|
-
language: "en",
|
|
180
|
-
locale: "en-IN",
|
|
181
|
-
timezone: "Asia/Kolkata"
|
|
182
|
-
},
|
|
183
|
-
appearance: {
|
|
184
|
-
showSidebar: true,
|
|
185
|
-
showHeader: true,
|
|
186
|
-
activeThemePreset: null,
|
|
187
|
-
showNewsPanel: true
|
|
188
|
-
},
|
|
189
|
-
content: {
|
|
190
|
-
tone: "engaging",
|
|
191
|
-
style: "blog",
|
|
192
|
-
wordCount: "medium",
|
|
193
|
-
includeQuotes: true,
|
|
194
|
-
includeFAQ: false,
|
|
195
|
-
targetAudience: ""
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
var PreferencesContext = createContext(void 0);
|
|
199
|
-
function PreferencesProvider({ children }) {
|
|
200
|
-
const [preferences, setPreferences] = useState(defaultPreferences);
|
|
201
|
-
const [loading, setLoading] = useState(true);
|
|
202
|
-
const [error, setError] = useState(null);
|
|
203
|
-
const refreshPreferences = async () => {
|
|
204
|
-
var _a, _b, _c;
|
|
205
|
-
try {
|
|
206
|
-
setLoading(true);
|
|
207
|
-
setError(null);
|
|
208
|
-
const data = await getMyPreferencesApi();
|
|
209
|
-
if (data) {
|
|
210
|
-
if (((_a = data.chatbot) == null ? void 0 : _a.logoUrl) && !data.chatbot.logoUrl.startsWith("http")) {
|
|
211
|
-
data.chatbot.logoUrl = `${getServerBaseUrl()}/${data.chatbot.logoUrl}`;
|
|
212
|
-
}
|
|
213
|
-
const mergedPreferences = __spreadProps(__spreadValues(__spreadValues({}, defaultPreferences), data), {
|
|
214
|
-
chatbot: __spreadValues(__spreadValues({}, defaultPreferences.chatbot), data.chatbot),
|
|
215
|
-
localization: __spreadValues(__spreadValues({}, defaultPreferences.localization), data.localization),
|
|
216
|
-
appearance: __spreadValues(__spreadValues({}, defaultPreferences.appearance), data.appearance),
|
|
217
|
-
content: __spreadValues(__spreadValues({}, defaultPreferences.content), data.content)
|
|
218
|
-
});
|
|
219
|
-
setPreferences(mergedPreferences);
|
|
220
|
-
if (typeof document !== "undefined") {
|
|
221
|
-
document.documentElement.style.setProperty("--color-primary", ((_b = mergedPreferences.chatbot) == null ? void 0 : _b.primaryColor) || "#10b981");
|
|
222
|
-
document.documentElement.style.setProperty("--color-secondary", ((_c = mergedPreferences.chatbot) == null ? void 0 : _c.secondaryColor) || "#064e3b");
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
} catch (err) {
|
|
226
|
-
console.error("Failed to fetch preferences:", err);
|
|
227
|
-
setError(err instanceof Error ? err.message : "Failed to load preferences");
|
|
228
|
-
setPreferences(defaultPreferences);
|
|
229
|
-
} finally {
|
|
230
|
-
setLoading(false);
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
const updatePreferences = (newPreferences) => {
|
|
234
|
-
var _a, _b;
|
|
235
|
-
setPreferences(newPreferences);
|
|
236
|
-
if (typeof document !== "undefined") {
|
|
237
|
-
document.documentElement.style.setProperty("--color-primary", ((_a = newPreferences.chatbot) == null ? void 0 : _a.primaryColor) || "#10b981");
|
|
238
|
-
document.documentElement.style.setProperty("--color-secondary", ((_b = newPreferences.chatbot) == null ? void 0 : _b.secondaryColor) || "#064e3b");
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
useEffect(() => {
|
|
242
|
-
refreshPreferences();
|
|
243
|
-
}, []);
|
|
244
|
-
return /* @__PURE__ */ jsx(
|
|
245
|
-
PreferencesContext.Provider,
|
|
246
|
-
{
|
|
247
|
-
value: {
|
|
248
|
-
preferences,
|
|
249
|
-
loading,
|
|
250
|
-
error,
|
|
251
|
-
refreshPreferences,
|
|
252
|
-
updatePreferences
|
|
253
|
-
},
|
|
254
|
-
children
|
|
255
|
-
}
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
function usePreferences() {
|
|
259
|
-
const context = useContext(PreferencesContext);
|
|
260
|
-
if (context === void 0) {
|
|
261
|
-
throw new Error("usePreferences must be used within a PreferencesProvider");
|
|
262
|
-
}
|
|
263
|
-
return context;
|
|
264
|
-
}
|
|
23
|
+
import { useEffect as useEffect7 } from "react";
|
|
265
24
|
|
|
266
25
|
// components/chatbot/ChatBot.tsx
|
|
267
|
-
import { useState as
|
|
26
|
+
import { useState as useState6 } from "react";
|
|
268
27
|
|
|
269
28
|
// src/utils/ aiJsonParser.ts
|
|
270
29
|
function extractJSON(raw) {
|
|
@@ -318,7 +77,8 @@ function formatAIContent(raw) {
|
|
|
318
77
|
article: "",
|
|
319
78
|
metaDescription: "",
|
|
320
79
|
metaKeywords: [],
|
|
321
|
-
plainText: ""
|
|
80
|
+
plainText: "",
|
|
81
|
+
images: []
|
|
322
82
|
};
|
|
323
83
|
if (!raw) return empty;
|
|
324
84
|
const parsed = extractJSON(raw);
|
|
@@ -335,19 +95,21 @@ function formatAIContent(raw) {
|
|
|
335
95
|
article: rawArticle,
|
|
336
96
|
metaDescription: parsed.metaDescription || "",
|
|
337
97
|
metaKeywords: Array.isArray(parsed.metaKeywords) ? parsed.metaKeywords : [],
|
|
338
|
-
plainText: raw
|
|
98
|
+
plainText: raw,
|
|
99
|
+
seoAnalysis: parsed.seoAnalysis || null,
|
|
100
|
+
images: Array.isArray(parsed.images) ? parsed.images : []
|
|
339
101
|
};
|
|
340
102
|
}
|
|
341
103
|
return __spreadProps(__spreadValues({}, empty), { plainText: raw });
|
|
342
104
|
}
|
|
343
105
|
|
|
344
106
|
// components/chatbot/ChatWindow.tsx
|
|
345
|
-
import { Check, Copy, Edit3,
|
|
346
|
-
import { useLayoutEffect, useRef, useState as
|
|
107
|
+
import { Check, Copy, Edit3, FileDown as FileDown2, SendHorizontal, Zap, X as X2, RefreshCcw as RefreshCcw2, FileText, ListChecks, Share2, BookOpen, Mail, Key, Loader2 as Loader22, Sparkles, Link2, PenLine, LayoutList, BarChart2 as BarChart22, ChevronDown as ChevronDown2, ChevronUp as ChevronUp2, AlertTriangle as AlertTriangle2, Lightbulb as Lightbulb2, Wand2 } from "lucide-react";
|
|
108
|
+
import { useLayoutEffect as useLayoutEffect2, useRef, useState as useState3, useEffect as useEffect3, useCallback } from "react";
|
|
347
109
|
|
|
348
110
|
// components/chatbot/EditModal.tsx
|
|
349
|
-
import { X } from "lucide-react";
|
|
350
|
-
import { useEffect as
|
|
111
|
+
import { X, FileDown, Loader2, BarChart2, AlertTriangle, Lightbulb, ChevronDown, ChevronUp, Send } from "lucide-react";
|
|
112
|
+
import { useEffect as useEffect2, useLayoutEffect, useState } from "react";
|
|
351
113
|
|
|
352
114
|
// components/chatbot/RichTextEditor.tsx
|
|
353
115
|
import { useEditor, EditorContent } from "@tiptap/react";
|
|
@@ -364,8 +126,8 @@ import {
|
|
|
364
126
|
Redo,
|
|
365
127
|
Pilcrow
|
|
366
128
|
} from "lucide-react";
|
|
367
|
-
import { useEffect
|
|
368
|
-
import { jsx
|
|
129
|
+
import { useEffect } from "react";
|
|
130
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
369
131
|
function RichTextEditor({
|
|
370
132
|
content,
|
|
371
133
|
onChange,
|
|
@@ -394,102 +156,102 @@ function RichTextEditor({
|
|
|
394
156
|
onChange(editor2.getHTML());
|
|
395
157
|
}
|
|
396
158
|
});
|
|
397
|
-
|
|
159
|
+
useEffect(() => {
|
|
398
160
|
if (editor && content !== editor.getHTML()) {
|
|
399
161
|
editor.commands.setContent(content);
|
|
400
162
|
}
|
|
401
163
|
}, [content, editor]);
|
|
402
164
|
if (!editor) {
|
|
403
|
-
return /* @__PURE__ */
|
|
165
|
+
return /* @__PURE__ */ jsx("div", { className: "cnfy-editor-loading", children: "Loading editor..." });
|
|
404
166
|
}
|
|
405
167
|
return /* @__PURE__ */ jsxs("div", { className: "cnfy-editor", children: [
|
|
406
168
|
/* @__PURE__ */ jsxs("div", { className: "cnfy-toolbar", children: [
|
|
407
|
-
/* @__PURE__ */
|
|
169
|
+
/* @__PURE__ */ jsx(
|
|
408
170
|
ToolbarButton,
|
|
409
171
|
{
|
|
410
172
|
onClick: () => editor.chain().focus().toggleHeading({ level: 1 }).run(),
|
|
411
173
|
isActive: editor.isActive("heading", { level: 1 }),
|
|
412
174
|
title: "Heading 1",
|
|
413
|
-
children: /* @__PURE__ */
|
|
175
|
+
children: /* @__PURE__ */ jsx(Heading1, { size: 18 })
|
|
414
176
|
}
|
|
415
177
|
),
|
|
416
|
-
/* @__PURE__ */
|
|
178
|
+
/* @__PURE__ */ jsx(
|
|
417
179
|
ToolbarButton,
|
|
418
180
|
{
|
|
419
181
|
onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),
|
|
420
182
|
isActive: editor.isActive("heading", { level: 2 }),
|
|
421
183
|
title: "Heading 2",
|
|
422
|
-
children: /* @__PURE__ */
|
|
184
|
+
children: /* @__PURE__ */ jsx(Heading2, { size: 18 })
|
|
423
185
|
}
|
|
424
186
|
),
|
|
425
|
-
/* @__PURE__ */
|
|
187
|
+
/* @__PURE__ */ jsx(
|
|
426
188
|
ToolbarButton,
|
|
427
189
|
{
|
|
428
190
|
onClick: () => editor.chain().focus().setParagraph().run(),
|
|
429
191
|
isActive: editor.isActive("paragraph"),
|
|
430
192
|
title: "Paragraph",
|
|
431
|
-
children: /* @__PURE__ */
|
|
193
|
+
children: /* @__PURE__ */ jsx(Pilcrow, { size: 18 })
|
|
432
194
|
}
|
|
433
195
|
),
|
|
434
|
-
/* @__PURE__ */
|
|
435
|
-
/* @__PURE__ */
|
|
196
|
+
/* @__PURE__ */ jsx("div", { className: "cnfy-toolbar-divider" }),
|
|
197
|
+
/* @__PURE__ */ jsx(
|
|
436
198
|
ToolbarButton,
|
|
437
199
|
{
|
|
438
200
|
onClick: () => editor.chain().focus().toggleBold().run(),
|
|
439
201
|
isActive: editor.isActive("bold"),
|
|
440
202
|
title: "Bold",
|
|
441
|
-
children: /* @__PURE__ */
|
|
203
|
+
children: /* @__PURE__ */ jsx(Bold, { size: 18 })
|
|
442
204
|
}
|
|
443
205
|
),
|
|
444
|
-
/* @__PURE__ */
|
|
206
|
+
/* @__PURE__ */ jsx(
|
|
445
207
|
ToolbarButton,
|
|
446
208
|
{
|
|
447
209
|
onClick: () => editor.chain().focus().toggleItalic().run(),
|
|
448
210
|
isActive: editor.isActive("italic"),
|
|
449
211
|
title: "Italic",
|
|
450
|
-
children: /* @__PURE__ */
|
|
212
|
+
children: /* @__PURE__ */ jsx(Italic, { size: 18 })
|
|
451
213
|
}
|
|
452
214
|
),
|
|
453
|
-
/* @__PURE__ */
|
|
454
|
-
/* @__PURE__ */
|
|
215
|
+
/* @__PURE__ */ jsx("div", { className: "cnfy-toolbar-divider" }),
|
|
216
|
+
/* @__PURE__ */ jsx(
|
|
455
217
|
ToolbarButton,
|
|
456
218
|
{
|
|
457
219
|
onClick: () => editor.chain().focus().toggleBulletList().run(),
|
|
458
220
|
isActive: editor.isActive("bulletList"),
|
|
459
221
|
title: "Bullet List",
|
|
460
|
-
children: /* @__PURE__ */
|
|
222
|
+
children: /* @__PURE__ */ jsx(List, { size: 18 })
|
|
461
223
|
}
|
|
462
224
|
),
|
|
463
|
-
/* @__PURE__ */
|
|
225
|
+
/* @__PURE__ */ jsx(
|
|
464
226
|
ToolbarButton,
|
|
465
227
|
{
|
|
466
228
|
onClick: () => editor.chain().focus().toggleOrderedList().run(),
|
|
467
229
|
isActive: editor.isActive("orderedList"),
|
|
468
230
|
title: "Numbered List",
|
|
469
|
-
children: /* @__PURE__ */
|
|
231
|
+
children: /* @__PURE__ */ jsx(ListOrdered, { size: 18 })
|
|
470
232
|
}
|
|
471
233
|
),
|
|
472
|
-
/* @__PURE__ */
|
|
473
|
-
/* @__PURE__ */
|
|
234
|
+
/* @__PURE__ */ jsx("div", { className: "cnfy-toolbar-divider" }),
|
|
235
|
+
/* @__PURE__ */ jsx(
|
|
474
236
|
ToolbarButton,
|
|
475
237
|
{
|
|
476
238
|
onClick: () => editor.chain().focus().undo().run(),
|
|
477
239
|
disabled: !editor.can().undo(),
|
|
478
240
|
title: "Undo",
|
|
479
|
-
children: /* @__PURE__ */
|
|
241
|
+
children: /* @__PURE__ */ jsx(Undo, { size: 18 })
|
|
480
242
|
}
|
|
481
243
|
),
|
|
482
|
-
/* @__PURE__ */
|
|
244
|
+
/* @__PURE__ */ jsx(
|
|
483
245
|
ToolbarButton,
|
|
484
246
|
{
|
|
485
247
|
onClick: () => editor.chain().focus().redo().run(),
|
|
486
248
|
disabled: !editor.can().redo(),
|
|
487
249
|
title: "Redo",
|
|
488
|
-
children: /* @__PURE__ */
|
|
250
|
+
children: /* @__PURE__ */ jsx(Redo, { size: 18 })
|
|
489
251
|
}
|
|
490
252
|
)
|
|
491
253
|
] }),
|
|
492
|
-
/* @__PURE__ */
|
|
254
|
+
/* @__PURE__ */ jsx(EditorContent, { editor, className: "cnfy-editor-content" })
|
|
493
255
|
] });
|
|
494
256
|
}
|
|
495
257
|
function ToolbarButton({
|
|
@@ -499,7 +261,7 @@ function ToolbarButton({
|
|
|
499
261
|
title,
|
|
500
262
|
children
|
|
501
263
|
}) {
|
|
502
|
-
return /* @__PURE__ */
|
|
264
|
+
return /* @__PURE__ */ jsx(
|
|
503
265
|
"button",
|
|
504
266
|
{
|
|
505
267
|
onClick,
|
|
@@ -513,48 +275,66 @@ function ToolbarButton({
|
|
|
513
275
|
|
|
514
276
|
// hooks/useTheme.ts
|
|
515
277
|
function useTheme() {
|
|
516
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
517
|
-
const { preferences, loading } = usePreferences();
|
|
518
278
|
return {
|
|
519
|
-
loading,
|
|
520
|
-
primaryColor:
|
|
521
|
-
secondaryColor:
|
|
522
|
-
botName:
|
|
523
|
-
logoUrl:
|
|
524
|
-
theme:
|
|
525
|
-
showSidebar:
|
|
526
|
-
showHeader:
|
|
527
|
-
activeThemePreset:
|
|
528
|
-
showNewsPanel:
|
|
279
|
+
loading: false,
|
|
280
|
+
primaryColor: "#10b981",
|
|
281
|
+
secondaryColor: "#064e3b",
|
|
282
|
+
botName: "ContenifyAI Assistant",
|
|
283
|
+
logoUrl: "/logo.png",
|
|
284
|
+
theme: "system",
|
|
285
|
+
showSidebar: true,
|
|
286
|
+
showHeader: true,
|
|
287
|
+
activeThemePreset: null,
|
|
288
|
+
showNewsPanel: true
|
|
529
289
|
};
|
|
530
290
|
}
|
|
531
291
|
|
|
532
292
|
// components/chatbot/EditModal.tsx
|
|
533
|
-
import { jsx as
|
|
293
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
294
|
+
function seoScoreColor(score) {
|
|
295
|
+
if (score >= 80) return "#10b981";
|
|
296
|
+
if (score >= 60) return "#f59e0b";
|
|
297
|
+
if (score >= 40) return "#f97316";
|
|
298
|
+
return "#ef4444";
|
|
299
|
+
}
|
|
300
|
+
function seoGradeColor(grade) {
|
|
301
|
+
if (grade === "A") return "#10b981";
|
|
302
|
+
if (grade === "B") return "#3b82f6";
|
|
303
|
+
if (grade === "C") return "#f59e0b";
|
|
304
|
+
if (grade === "D") return "#f97316";
|
|
305
|
+
return "#ef4444";
|
|
306
|
+
}
|
|
534
307
|
function toSlug(text) {
|
|
535
308
|
return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
536
309
|
}
|
|
537
310
|
function EditModal({
|
|
538
311
|
isOpen,
|
|
312
|
+
inline = false,
|
|
539
313
|
initialTitle = "",
|
|
540
314
|
initialSubtitle = "",
|
|
541
315
|
initialContent,
|
|
542
316
|
initialMetaDescription = "",
|
|
543
317
|
metaKeywords,
|
|
318
|
+
initialFeaturedImage = "",
|
|
319
|
+
seoAnalysis = null,
|
|
544
320
|
onClose,
|
|
545
|
-
|
|
546
|
-
|
|
321
|
+
onDownload,
|
|
322
|
+
downloadingFormat,
|
|
323
|
+
onPost,
|
|
324
|
+
isPosting = false
|
|
547
325
|
}) {
|
|
548
326
|
const { primaryColor } = useTheme();
|
|
549
|
-
const [title, setTitle] =
|
|
550
|
-
const [
|
|
551
|
-
const [
|
|
552
|
-
const [
|
|
553
|
-
const [
|
|
554
|
-
const [
|
|
555
|
-
const [
|
|
556
|
-
const [
|
|
557
|
-
|
|
327
|
+
const [title, setTitle] = useState("");
|
|
328
|
+
const [seoSugOpen, setSeoSugOpen] = useState(false);
|
|
329
|
+
const [subtitle, setSubtitle] = useState("");
|
|
330
|
+
const [slug, setSlug] = useState("");
|
|
331
|
+
const [slugEdited, setSlugEdited] = useState(false);
|
|
332
|
+
const [metaDescription, setMetaDescription] = useState("");
|
|
333
|
+
const [content, setContent] = useState("");
|
|
334
|
+
const [keywords, setKeywords] = useState(metaKeywords);
|
|
335
|
+
const [newKeyword, setNewKeyword] = useState("");
|
|
336
|
+
const [featuredImage, setFeaturedImage] = useState(initialFeaturedImage);
|
|
337
|
+
useLayoutEffect(() => {
|
|
558
338
|
setTitle(initialTitle);
|
|
559
339
|
setSubtitle(initialSubtitle);
|
|
560
340
|
setMetaDescription(initialMetaDescription);
|
|
@@ -562,8 +342,9 @@ function EditModal({
|
|
|
562
342
|
setSlugEdited(false);
|
|
563
343
|
setContent(initialContent);
|
|
564
344
|
setKeywords(metaKeywords);
|
|
565
|
-
|
|
566
|
-
|
|
345
|
+
setFeaturedImage(initialFeaturedImage);
|
|
346
|
+
}, [initialTitle, initialSubtitle, initialContent, initialMetaDescription, metaKeywords, initialFeaturedImage]);
|
|
347
|
+
useEffect2(() => {
|
|
567
348
|
if (isOpen) {
|
|
568
349
|
document.body.style.overflow = "hidden";
|
|
569
350
|
} else {
|
|
@@ -604,138 +385,313 @@ function EditModal({
|
|
|
604
385
|
article: content,
|
|
605
386
|
metaDescription,
|
|
606
387
|
slug,
|
|
607
|
-
keywords
|
|
388
|
+
keywords,
|
|
389
|
+
featuredImage: featuredImage || void 0
|
|
608
390
|
});
|
|
609
391
|
if (!isOpen) return null;
|
|
610
|
-
|
|
611
|
-
/* @__PURE__ */
|
|
612
|
-
|
|
613
|
-
/* @__PURE__ */
|
|
614
|
-
|
|
615
|
-
|
|
392
|
+
const editContent = /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
393
|
+
/* @__PURE__ */ jsxs2("div", { className: "cnfy-edit-modal-header", children: [
|
|
394
|
+
/* @__PURE__ */ jsx2("h2", { className: "cnfy-edit-modal-title", children: "Edit Article" }),
|
|
395
|
+
/* @__PURE__ */ jsx2("button", { onClick: onClose, className: "cnfy-edit-modal-close-btn", children: /* @__PURE__ */ jsx2(X, { size: 20, className: "cnfy-edit-modal-close-icon" }) })
|
|
396
|
+
] }),
|
|
397
|
+
/* @__PURE__ */ jsxs2("div", { className: "cnfy-edit-modal-body", children: [
|
|
398
|
+
featuredImage && /* @__PURE__ */ jsxs2("div", { className: "cnfy-edit-featured-image-wrap", children: [
|
|
399
|
+
/* @__PURE__ */ jsx2(
|
|
400
|
+
"img",
|
|
401
|
+
{
|
|
402
|
+
src: featuredImage,
|
|
403
|
+
alt: "Featured",
|
|
404
|
+
className: "cnfy-edit-featured-image"
|
|
405
|
+
}
|
|
406
|
+
),
|
|
407
|
+
/* @__PURE__ */ jsx2(
|
|
408
|
+
"button",
|
|
409
|
+
{
|
|
410
|
+
type: "button",
|
|
411
|
+
onClick: () => setFeaturedImage(""),
|
|
412
|
+
className: "cnfy-edit-featured-image-remove",
|
|
413
|
+
title: "Remove image",
|
|
414
|
+
children: /* @__PURE__ */ jsx2(X, { size: 14 })
|
|
415
|
+
}
|
|
416
|
+
)
|
|
616
417
|
] }),
|
|
617
|
-
/* @__PURE__ */ jsxs2("div", {
|
|
618
|
-
/* @__PURE__ */
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
/* @__PURE__ */
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
418
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
419
|
+
/* @__PURE__ */ jsx2("label", { className: "cnfy-edit-label", children: "Title" }),
|
|
420
|
+
/* @__PURE__ */ jsx2(
|
|
421
|
+
"input",
|
|
422
|
+
{
|
|
423
|
+
type: "text",
|
|
424
|
+
value: title,
|
|
425
|
+
onChange: (e) => handleTitleChange(e.target.value),
|
|
426
|
+
placeholder: "Article title...",
|
|
427
|
+
className: "cnfy-edit-input"
|
|
428
|
+
}
|
|
429
|
+
)
|
|
430
|
+
] }),
|
|
431
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
432
|
+
/* @__PURE__ */ jsx2("label", { className: "cnfy-edit-label", children: "Subtitle" }),
|
|
433
|
+
/* @__PURE__ */ jsx2(
|
|
434
|
+
"input",
|
|
435
|
+
{
|
|
436
|
+
type: "text",
|
|
437
|
+
value: subtitle,
|
|
438
|
+
onChange: (e) => setSubtitle(e.target.value),
|
|
439
|
+
placeholder: "Article subtitle...",
|
|
440
|
+
className: "cnfy-edit-input"
|
|
441
|
+
}
|
|
442
|
+
)
|
|
443
|
+
] }),
|
|
444
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
445
|
+
/* @__PURE__ */ jsx2("label", { className: "cnfy-edit-label", children: "Slug" }),
|
|
446
|
+
/* @__PURE__ */ jsx2(
|
|
447
|
+
"input",
|
|
448
|
+
{
|
|
449
|
+
type: "text",
|
|
450
|
+
value: slug,
|
|
451
|
+
onChange: (e) => handleSlugChange(e.target.value),
|
|
452
|
+
placeholder: "article-url-slug",
|
|
453
|
+
className: "cnfy-edit-input cnfy-edit-input--mono"
|
|
454
|
+
}
|
|
455
|
+
)
|
|
456
|
+
] }),
|
|
457
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
458
|
+
/* @__PURE__ */ jsx2("label", { className: "cnfy-edit-label", children: "Article Content" }),
|
|
459
|
+
/* @__PURE__ */ jsx2(
|
|
460
|
+
RichTextEditor,
|
|
461
|
+
{
|
|
462
|
+
content,
|
|
463
|
+
onChange: setContent,
|
|
464
|
+
placeholder: "Start writing your article..."
|
|
465
|
+
}
|
|
466
|
+
)
|
|
467
|
+
] }),
|
|
468
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
469
|
+
/* @__PURE__ */ jsx2("label", { className: "cnfy-edit-label", children: "Meta Description" }),
|
|
470
|
+
/* @__PURE__ */ jsx2(
|
|
471
|
+
"textarea",
|
|
472
|
+
{
|
|
473
|
+
value: metaDescription,
|
|
474
|
+
onChange: (e) => setMetaDescription(e.target.value),
|
|
475
|
+
placeholder: "Brief description for search engines...",
|
|
476
|
+
className: "cnfy-edit-textarea",
|
|
477
|
+
rows: 3
|
|
478
|
+
}
|
|
479
|
+
)
|
|
480
|
+
] }),
|
|
481
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
482
|
+
/* @__PURE__ */ jsx2("label", { className: "cnfy-edit-label", children: "Meta Keywords" }),
|
|
483
|
+
/* @__PURE__ */ jsx2("div", { className: "cnfy-keyword-list", children: keywords.map((keyword, index) => /* @__PURE__ */ jsxs2("span", { className: "cnfy-keyword-tag", children: [
|
|
484
|
+
"#",
|
|
485
|
+
keyword,
|
|
486
|
+
/* @__PURE__ */ jsx2(
|
|
487
|
+
"button",
|
|
635
488
|
{
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
placeholder: "Article subtitle...",
|
|
640
|
-
className: "cnfy-edit-input"
|
|
489
|
+
onClick: () => handleRemoveKeyword(index),
|
|
490
|
+
className: "cnfy-keyword-remove-btn",
|
|
491
|
+
children: /* @__PURE__ */ jsx2(X, { size: 14 })
|
|
641
492
|
}
|
|
642
493
|
)
|
|
643
|
-
] }),
|
|
644
|
-
/* @__PURE__ */ jsxs2("div", { children: [
|
|
645
|
-
/* @__PURE__ */
|
|
646
|
-
/* @__PURE__ */ jsx3(
|
|
494
|
+
] }, index)) }),
|
|
495
|
+
/* @__PURE__ */ jsxs2("div", { className: "cnfy-keyword-input-row", children: [
|
|
496
|
+
/* @__PURE__ */ jsx2(
|
|
647
497
|
"input",
|
|
648
498
|
{
|
|
649
499
|
type: "text",
|
|
650
|
-
value:
|
|
651
|
-
onChange: (e) =>
|
|
652
|
-
|
|
653
|
-
|
|
500
|
+
value: newKeyword,
|
|
501
|
+
onChange: (e) => setNewKeyword(e.target.value),
|
|
502
|
+
onKeyDown: handleKeyDown,
|
|
503
|
+
placeholder: "Add a keyword...",
|
|
504
|
+
className: "cnfy-keyword-input"
|
|
654
505
|
}
|
|
655
|
-
)
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
]
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
"input",
|
|
506
|
+
),
|
|
507
|
+
/* @__PURE__ */ jsx2("button", { onClick: handleAddKeyword, className: "cnfy-btn-add-keyword", children: "Add" })
|
|
508
|
+
] })
|
|
509
|
+
] }),
|
|
510
|
+
seoAnalysis && (() => {
|
|
511
|
+
const seo = seoAnalysis;
|
|
512
|
+
const breakdown = [
|
|
513
|
+
{ key: "title", label: "Title", section: seo.breakdown.title },
|
|
514
|
+
{ key: "meta", label: "Meta", section: seo.breakdown.meta },
|
|
515
|
+
{ key: "content", label: "Content", section: seo.breakdown.content },
|
|
516
|
+
{ key: "keywords", label: "Keywords", section: seo.breakdown.keywords },
|
|
517
|
+
{ key: "readability", label: "Readability", section: seo.breakdown.readability }
|
|
518
|
+
];
|
|
519
|
+
const allIssues = breakdown.flatMap((b) => {
|
|
520
|
+
var _a, _b;
|
|
521
|
+
return (_b = (_a = b.section) == null ? void 0 : _a.issues) != null ? _b : [];
|
|
522
|
+
}).filter(Boolean);
|
|
523
|
+
return /* @__PURE__ */ jsxs2("div", { className: "cnfy-seo-panel", children: [
|
|
524
|
+
/* @__PURE__ */ jsxs2("div", { className: "cnfy-seo-header", children: [
|
|
525
|
+
/* @__PURE__ */ jsxs2("div", { className: "cnfy-seo-title", children: [
|
|
526
|
+
/* @__PURE__ */ jsx2(BarChart2, { size: 13 }),
|
|
527
|
+
"SEO Analysis",
|
|
528
|
+
seo.improvement != null && seo.improvement > 0 && /* @__PURE__ */ jsxs2("span", { className: "cnfy-seo-improvement-badge", children: [
|
|
529
|
+
"\u2191 +",
|
|
530
|
+
seo.improvement,
|
|
531
|
+
" pts"
|
|
532
|
+
] })
|
|
533
|
+
] }),
|
|
534
|
+
/* @__PURE__ */ jsxs2("div", { className: "cnfy-seo-score-info", children: [
|
|
535
|
+
seo.before && /* @__PURE__ */ jsxs2("span", { className: "cnfy-seo-before", children: [
|
|
536
|
+
"was ",
|
|
537
|
+
seo.before.overall,
|
|
538
|
+
/* @__PURE__ */ jsx2("span", { className: "cnfy-seo-before-grade", style: { background: seoGradeColor(seo.before.grade) }, children: seo.before.grade })
|
|
539
|
+
] }),
|
|
540
|
+
/* @__PURE__ */ jsx2("span", { className: "cnfy-seo-score-num", children: seo.overall }),
|
|
541
|
+
/* @__PURE__ */ jsx2("span", { className: "cnfy-seo-score-denom", children: "/100" }),
|
|
542
|
+
/* @__PURE__ */ jsx2("div", { className: "cnfy-seo-grade", style: { background: seoGradeColor(seo.grade) }, children: seo.grade })
|
|
543
|
+
] })
|
|
544
|
+
] }),
|
|
545
|
+
/* @__PURE__ */ jsxs2("div", { className: "cnfy-seo-body", children: [
|
|
546
|
+
/* @__PURE__ */ jsx2("div", { className: "cnfy-seo-overall-bar", children: /* @__PURE__ */ jsx2(
|
|
547
|
+
"div",
|
|
698
548
|
{
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
onChange: (e) => setNewKeyword(e.target.value),
|
|
702
|
-
onKeyDown: handleKeyDown,
|
|
703
|
-
placeholder: "Add a keyword...",
|
|
704
|
-
className: "cnfy-keyword-input"
|
|
549
|
+
className: "cnfy-seo-overall-fill",
|
|
550
|
+
style: { width: `${seo.overall}%`, background: seoScoreColor(seo.overall) }
|
|
705
551
|
}
|
|
706
|
-
),
|
|
707
|
-
/* @__PURE__ */
|
|
552
|
+
) }),
|
|
553
|
+
/* @__PURE__ */ jsx2("div", { className: "cnfy-seo-breakdown", children: breakdown.map(({ key, label, section }) => section && /* @__PURE__ */ jsxs2("div", { className: "cnfy-seo-breakdown-row", children: [
|
|
554
|
+
/* @__PURE__ */ jsx2("span", { className: "cnfy-seo-bd-label", children: label }),
|
|
555
|
+
/* @__PURE__ */ jsx2("div", { className: "cnfy-seo-bd-bar", children: /* @__PURE__ */ jsx2(
|
|
556
|
+
"div",
|
|
557
|
+
{
|
|
558
|
+
className: "cnfy-seo-bd-fill",
|
|
559
|
+
style: { width: `${section.score}%`, background: seoScoreColor(section.score) }
|
|
560
|
+
}
|
|
561
|
+
) }),
|
|
562
|
+
/* @__PURE__ */ jsx2("span", { className: "cnfy-seo-bd-score", style: { color: seoScoreColor(section.score) }, children: section.score }),
|
|
563
|
+
section.readingLabel && /* @__PURE__ */ jsx2("span", { className: "cnfy-seo-bd-extra", children: section.readingLabel })
|
|
564
|
+
] }, key)) }),
|
|
565
|
+
allIssues.length > 0 && /* @__PURE__ */ jsxs2("div", { className: "cnfy-seo-issues", children: [
|
|
566
|
+
/* @__PURE__ */ jsxs2("div", { className: "cnfy-seo-issues-title", children: [
|
|
567
|
+
/* @__PURE__ */ jsx2(AlertTriangle, { size: 11 }),
|
|
568
|
+
allIssues.length,
|
|
569
|
+
" ",
|
|
570
|
+
allIssues.length === 1 ? "Issue" : "Issues"
|
|
571
|
+
] }),
|
|
572
|
+
allIssues.map((issue, i) => /* @__PURE__ */ jsx2("div", { className: "cnfy-seo-issue-item", children: issue }, i))
|
|
573
|
+
] }),
|
|
574
|
+
seo.suggestions.length > 0 && /* @__PURE__ */ jsxs2("div", { className: "cnfy-seo-suggestions", children: [
|
|
575
|
+
/* @__PURE__ */ jsxs2(
|
|
576
|
+
"button",
|
|
577
|
+
{
|
|
578
|
+
type: "button",
|
|
579
|
+
className: "cnfy-seo-suggestions-toggle",
|
|
580
|
+
onClick: () => setSeoSugOpen((v) => !v),
|
|
581
|
+
children: [
|
|
582
|
+
/* @__PURE__ */ jsxs2("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
583
|
+
/* @__PURE__ */ jsx2(Lightbulb, { size: 11 }),
|
|
584
|
+
seo.suggestions.length,
|
|
585
|
+
" Suggestions"
|
|
586
|
+
] }),
|
|
587
|
+
seoSugOpen ? /* @__PURE__ */ jsx2(ChevronUp, { size: 12 }) : /* @__PURE__ */ jsx2(ChevronDown, { size: 12 })
|
|
588
|
+
]
|
|
589
|
+
}
|
|
590
|
+
),
|
|
591
|
+
seoSugOpen && /* @__PURE__ */ jsx2("div", { className: "cnfy-seo-suggestions-list", children: seo.suggestions.map((s, i) => /* @__PURE__ */ jsx2("div", { className: "cnfy-seo-suggestion-item", children: s }, i)) })
|
|
592
|
+
] })
|
|
708
593
|
] })
|
|
709
|
-
] })
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
594
|
+
] });
|
|
595
|
+
})()
|
|
596
|
+
] }),
|
|
597
|
+
/* @__PURE__ */ jsxs2("div", { className: "cnfy-edit-modal-footer", children: [
|
|
598
|
+
/* @__PURE__ */ jsx2("button", { onClick: onClose, className: "cnfy-btn-footer-cancel", children: "Cancel" }),
|
|
599
|
+
/* @__PURE__ */ jsxs2(
|
|
600
|
+
"button",
|
|
601
|
+
{
|
|
602
|
+
onClick: () => onDownload == null ? void 0 : onDownload(getEditData(), "docx"),
|
|
603
|
+
disabled: downloadingFormat === "docx",
|
|
604
|
+
className: "cnfy-btn-download",
|
|
605
|
+
children: [
|
|
606
|
+
downloadingFormat === "docx" ? /* @__PURE__ */ jsx2(Loader2, { size: 15, className: "cnfy-animate-spin" }) : /* @__PURE__ */ jsx2(FileDown, { size: 15 }),
|
|
607
|
+
"DOCX"
|
|
608
|
+
]
|
|
609
|
+
}
|
|
610
|
+
),
|
|
611
|
+
/* @__PURE__ */ jsxs2(
|
|
612
|
+
"button",
|
|
613
|
+
{
|
|
614
|
+
onClick: () => onDownload == null ? void 0 : onDownload(getEditData(), "pdf"),
|
|
615
|
+
disabled: downloadingFormat === "pdf",
|
|
616
|
+
className: "cnfy-btn-download cnfy-btn-download--pdf",
|
|
617
|
+
style: { backgroundColor: primaryColor, color: "#fff", border: "none" },
|
|
618
|
+
children: [
|
|
619
|
+
downloadingFormat === "pdf" ? /* @__PURE__ */ jsx2(Loader2, { size: 15, className: "cnfy-animate-spin" }) : /* @__PURE__ */ jsx2(FileDown, { size: 15 }),
|
|
620
|
+
"PDF"
|
|
621
|
+
]
|
|
622
|
+
}
|
|
623
|
+
),
|
|
624
|
+
onPost && /* @__PURE__ */ jsxs2(
|
|
625
|
+
"button",
|
|
626
|
+
{
|
|
627
|
+
onClick: () => onPost(getEditData()),
|
|
628
|
+
disabled: isPosting,
|
|
629
|
+
className: "cnfy-btn-download",
|
|
630
|
+
style: {
|
|
631
|
+
background: "linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%)",
|
|
632
|
+
color: "#fff",
|
|
633
|
+
border: "none",
|
|
634
|
+
opacity: isPosting ? 0.7 : 1
|
|
635
|
+
},
|
|
636
|
+
children: [
|
|
637
|
+
isPosting ? /* @__PURE__ */ jsx2(Loader2, { size: 15, className: "cnfy-animate-spin" }) : /* @__PURE__ */ jsx2(Send, { size: 15 }),
|
|
638
|
+
"Post"
|
|
639
|
+
]
|
|
640
|
+
}
|
|
641
|
+
)
|
|
731
642
|
] })
|
|
732
643
|
] });
|
|
644
|
+
if (inline) {
|
|
645
|
+
return /* @__PURE__ */ jsx2("div", { className: "cnfy-edit-inline", children: editContent });
|
|
646
|
+
}
|
|
647
|
+
return /* @__PURE__ */ jsxs2("div", { className: "cnfy-edit-modal-overlay", children: [
|
|
648
|
+
/* @__PURE__ */ jsx2("div", { className: "cnfy-edit-modal-backdrop", onClick: onClose }),
|
|
649
|
+
/* @__PURE__ */ jsx2("div", { className: "cnfy-edit-modal", children: editContent })
|
|
650
|
+
] });
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// lib/config.ts
|
|
654
|
+
var _apiUrl = process.env.NEXT_PUBLIC_CONTENIFY_API_URL || "http://localhost:8080/api";
|
|
655
|
+
var _apiKey = process.env.NEXT_PUBLIC_API_KEY || "";
|
|
656
|
+
var _domain = process.env.NEXT_PUBLIC_CONTENIFY_DOMAIN || "";
|
|
657
|
+
function setConfig(config) {
|
|
658
|
+
if (config.apiUrl) _apiUrl = config.apiUrl;
|
|
659
|
+
if (config.apiKey) _apiKey = config.apiKey;
|
|
660
|
+
if (config.domain) _domain = config.domain;
|
|
661
|
+
}
|
|
662
|
+
function getApiBaseUrl() {
|
|
663
|
+
return _apiUrl;
|
|
664
|
+
}
|
|
665
|
+
function getApiKey() {
|
|
666
|
+
return _apiKey;
|
|
733
667
|
}
|
|
734
668
|
|
|
735
669
|
// components/news/NewsList.tsx
|
|
736
|
-
import { useState as
|
|
670
|
+
import { useState as useState2 } from "react";
|
|
737
671
|
import { Eye, RefreshCcw } from "lucide-react";
|
|
738
|
-
|
|
672
|
+
|
|
673
|
+
// src/utils/util.ts
|
|
674
|
+
var lightenColor = (hex, amount) => {
|
|
675
|
+
const sanitized = hex.replace("#", "");
|
|
676
|
+
const r = parseInt(sanitized.substring(0, 2), 16);
|
|
677
|
+
const g = parseInt(sanitized.substring(2, 4), 16);
|
|
678
|
+
const b = parseInt(sanitized.substring(4, 6), 16);
|
|
679
|
+
const mix = amount / 100;
|
|
680
|
+
const lr = Math.round(r + (255 - r) * mix);
|
|
681
|
+
const lg = Math.round(g + (255 - g) * mix);
|
|
682
|
+
const lb = Math.round(b + (255 - b) * mix);
|
|
683
|
+
return `#${lr.toString(16).padStart(2, "0")}${lg.toString(16).padStart(2, "0")}${lb.toString(16).padStart(2, "0")}`;
|
|
684
|
+
};
|
|
685
|
+
var hexToRgba = (hex, opacity) => {
|
|
686
|
+
const sanitizedHex = hex.replace("#", "");
|
|
687
|
+
const r = parseInt(sanitizedHex.substring(0, 2), 16);
|
|
688
|
+
const g = parseInt(sanitizedHex.substring(2, 4), 16);
|
|
689
|
+
const b = parseInt(sanitizedHex.substring(4, 6), 16);
|
|
690
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
// components/news/NewsList.tsx
|
|
694
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
739
695
|
var dateFormatter = new Intl.DateTimeFormat("en-GB", {
|
|
740
696
|
day: "2-digit",
|
|
741
697
|
month: "short",
|
|
@@ -766,18 +722,8 @@ function NewsList({
|
|
|
766
722
|
onRecreate
|
|
767
723
|
}) {
|
|
768
724
|
const { primaryColor } = useTheme();
|
|
769
|
-
const [primaryColorState] =
|
|
770
|
-
|
|
771
|
-
hex = hex.replace("#", "");
|
|
772
|
-
let r = parseInt(hex.substring(0, 2), 16);
|
|
773
|
-
let g = parseInt(hex.substring(2, 4), 16);
|
|
774
|
-
let b = parseInt(hex.substring(4, 6), 16);
|
|
775
|
-
r = Math.round(r + (255 - r) * (percent / 100));
|
|
776
|
-
g = Math.round(g + (255 - g) * (percent / 100));
|
|
777
|
-
b = Math.round(b + (255 - b) * (percent / 100));
|
|
778
|
-
return `rgb(${r}, ${g}, ${b})`;
|
|
779
|
-
};
|
|
780
|
-
return /* @__PURE__ */ jsx4("div", { className: "cnfy-news-list", children: news.flatMap((item) => {
|
|
725
|
+
const [primaryColorState] = useState2(primaryColor);
|
|
726
|
+
return /* @__PURE__ */ jsx3("div", { className: "cnfy-news-list", children: news.flatMap((item) => {
|
|
781
727
|
const publishedDate = new Date(item.publishedAt);
|
|
782
728
|
const links = extractLinksFromContent(item.content);
|
|
783
729
|
if (links.length > 0) {
|
|
@@ -787,23 +733,23 @@ function NewsList({
|
|
|
787
733
|
className: "cnfy-news-card",
|
|
788
734
|
children: [
|
|
789
735
|
/* @__PURE__ */ jsxs3("div", { className: "cnfy-news-card-content", children: [
|
|
790
|
-
/* @__PURE__ */
|
|
736
|
+
/* @__PURE__ */ jsx3("p", { className: "cnfy-news-card-title", children: link.title }),
|
|
791
737
|
/* @__PURE__ */ jsxs3("div", { className: "cnfy-news-card-meta", children: [
|
|
792
|
-
/* @__PURE__ */
|
|
738
|
+
/* @__PURE__ */ jsx3(
|
|
793
739
|
"span",
|
|
794
740
|
{
|
|
795
741
|
className: "cnfy-news-badge",
|
|
796
742
|
style: {
|
|
797
|
-
|
|
798
|
-
color:
|
|
799
|
-
|
|
743
|
+
background: "linear-gradient(135deg, rgba(139,92,246,0.12), rgba(236,72,153,0.10))",
|
|
744
|
+
color: "#8b5cf6",
|
|
745
|
+
border: "1px solid rgba(139,92,246,0.2)"
|
|
800
746
|
},
|
|
801
747
|
children: link.source || item.sourceName
|
|
802
748
|
}
|
|
803
749
|
),
|
|
804
|
-
/* @__PURE__ */
|
|
805
|
-
/* @__PURE__ */
|
|
806
|
-
/* @__PURE__ */
|
|
750
|
+
/* @__PURE__ */ jsx3("span", { children: "\u2022" }),
|
|
751
|
+
/* @__PURE__ */ jsx3("span", { className: "cnfy-news-card-category", children: item.category }),
|
|
752
|
+
/* @__PURE__ */ jsx3("span", { children: "\u2022" }),
|
|
807
753
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
808
754
|
dateFormatter.format(publishedDate),
|
|
809
755
|
" ",
|
|
@@ -812,16 +758,16 @@ function NewsList({
|
|
|
812
758
|
] })
|
|
813
759
|
] }),
|
|
814
760
|
/* @__PURE__ */ jsxs3("div", { className: "cnfy-news-card-actions", children: [
|
|
815
|
-
/* @__PURE__ */
|
|
761
|
+
/* @__PURE__ */ jsx3(
|
|
816
762
|
"button",
|
|
817
763
|
{
|
|
818
764
|
onClick: () => window.open(link.url, "_blank"),
|
|
819
765
|
className: "cnfy-news-action-btn",
|
|
820
766
|
title: "View",
|
|
821
|
-
children: /* @__PURE__ */
|
|
767
|
+
children: /* @__PURE__ */ jsx3(Eye, { size: 16 })
|
|
822
768
|
}
|
|
823
769
|
),
|
|
824
|
-
/* @__PURE__ */
|
|
770
|
+
/* @__PURE__ */ jsx3(
|
|
825
771
|
"button",
|
|
826
772
|
{
|
|
827
773
|
onClick: () => onRecreate({
|
|
@@ -831,7 +777,7 @@ function NewsList({
|
|
|
831
777
|
}),
|
|
832
778
|
className: "cnfy-news-action-btn",
|
|
833
779
|
title: "Recreate",
|
|
834
|
-
children: /* @__PURE__ */
|
|
780
|
+
children: /* @__PURE__ */ jsx3(RefreshCcw, { size: 16 })
|
|
835
781
|
}
|
|
836
782
|
)
|
|
837
783
|
] })
|
|
@@ -846,9 +792,9 @@ function NewsList({
|
|
|
846
792
|
className: "cnfy-news-card",
|
|
847
793
|
children: [
|
|
848
794
|
/* @__PURE__ */ jsxs3("div", { className: "cnfy-news-card-content", children: [
|
|
849
|
-
/* @__PURE__ */
|
|
795
|
+
/* @__PURE__ */ jsx3("p", { className: "cnfy-news-card-title", children: item.title }),
|
|
850
796
|
/* @__PURE__ */ jsxs3("div", { className: "cnfy-news-card-meta", children: [
|
|
851
|
-
/* @__PURE__ */
|
|
797
|
+
/* @__PURE__ */ jsx3(
|
|
852
798
|
"span",
|
|
853
799
|
{
|
|
854
800
|
className: "cnfy-news-badge",
|
|
@@ -860,9 +806,9 @@ function NewsList({
|
|
|
860
806
|
children: item.sourceName
|
|
861
807
|
}
|
|
862
808
|
),
|
|
863
|
-
/* @__PURE__ */
|
|
864
|
-
/* @__PURE__ */
|
|
865
|
-
/* @__PURE__ */
|
|
809
|
+
/* @__PURE__ */ jsx3("span", { children: "\u2022" }),
|
|
810
|
+
/* @__PURE__ */ jsx3("span", { className: "cnfy-news-card-category", children: item.category }),
|
|
811
|
+
/* @__PURE__ */ jsx3("span", { children: "\u2022" }),
|
|
866
812
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
867
813
|
dateFormatter.format(publishedDate),
|
|
868
814
|
" ",
|
|
@@ -871,16 +817,16 @@ function NewsList({
|
|
|
871
817
|
] })
|
|
872
818
|
] }),
|
|
873
819
|
/* @__PURE__ */ jsxs3("div", { className: "cnfy-news-card-actions", children: [
|
|
874
|
-
/* @__PURE__ */
|
|
820
|
+
/* @__PURE__ */ jsx3(
|
|
875
821
|
"button",
|
|
876
822
|
{
|
|
877
823
|
onClick: () => onView(item),
|
|
878
824
|
className: "cnfy-news-action-btn",
|
|
879
825
|
title: "View",
|
|
880
|
-
children: /* @__PURE__ */
|
|
826
|
+
children: /* @__PURE__ */ jsx3(Eye, { size: 16 })
|
|
881
827
|
}
|
|
882
828
|
),
|
|
883
|
-
/* @__PURE__ */
|
|
829
|
+
/* @__PURE__ */ jsx3(
|
|
884
830
|
"button",
|
|
885
831
|
{
|
|
886
832
|
onClick: () => onRecreate({
|
|
@@ -890,7 +836,7 @@ function NewsList({
|
|
|
890
836
|
}),
|
|
891
837
|
className: "cnfy-news-action-btn",
|
|
892
838
|
title: "Recreate",
|
|
893
|
-
children: /* @__PURE__ */
|
|
839
|
+
children: /* @__PURE__ */ jsx3(RefreshCcw, { size: 16 })
|
|
894
840
|
}
|
|
895
841
|
)
|
|
896
842
|
] })
|
|
@@ -901,27 +847,103 @@ function NewsList({
|
|
|
901
847
|
}) });
|
|
902
848
|
}
|
|
903
849
|
|
|
850
|
+
// lib/api.ts
|
|
851
|
+
import axios from "axios";
|
|
852
|
+
var ApiKeyInvalidError = class extends Error {
|
|
853
|
+
constructor() {
|
|
854
|
+
super("Invalid or expired subscription key");
|
|
855
|
+
this.isApiKeyInvalid = true;
|
|
856
|
+
this.name = "ApiKeyInvalidError";
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
function emitApiKeyInvalid() {
|
|
860
|
+
if (typeof window !== "undefined") {
|
|
861
|
+
window.dispatchEvent(new CustomEvent("api-key-invalid"));
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
var api = axios.create({
|
|
865
|
+
withCredentials: true,
|
|
866
|
+
timeout: 15e3,
|
|
867
|
+
// 15 s — prevents requests hanging indefinitely
|
|
868
|
+
headers: {
|
|
869
|
+
"Content-Type": "application/json"
|
|
870
|
+
}
|
|
871
|
+
});
|
|
872
|
+
api.interceptors.request.use(
|
|
873
|
+
(config) => {
|
|
874
|
+
config.baseURL = getApiBaseUrl();
|
|
875
|
+
const apiKey = getApiKey();
|
|
876
|
+
if (!apiKey) {
|
|
877
|
+
emitApiKeyInvalid();
|
|
878
|
+
return Promise.reject(new ApiKeyInvalidError());
|
|
879
|
+
}
|
|
880
|
+
config.headers["x-api-key"] = apiKey;
|
|
881
|
+
if (typeof window !== "undefined") {
|
|
882
|
+
const token = localStorage.getItem("token");
|
|
883
|
+
if (token) {
|
|
884
|
+
config.headers["Authorization"] = `Bearer ${token}`;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return config;
|
|
888
|
+
},
|
|
889
|
+
(error) => Promise.reject(error)
|
|
890
|
+
);
|
|
891
|
+
api.interceptors.response.use(
|
|
892
|
+
(response) => {
|
|
893
|
+
const data = response.data;
|
|
894
|
+
if (data && data.success === false && typeof data.message === "string" && data.message.toLowerCase().includes("subscription key")) {
|
|
895
|
+
emitApiKeyInvalid();
|
|
896
|
+
}
|
|
897
|
+
return response;
|
|
898
|
+
},
|
|
899
|
+
(error) => {
|
|
900
|
+
var _a, _b, _c;
|
|
901
|
+
const status = (_a = error.response) == null ? void 0 : _a.status;
|
|
902
|
+
if (status === 401 || status === 403) {
|
|
903
|
+
emitApiKeyInvalid();
|
|
904
|
+
return Promise.reject(new ApiKeyInvalidError());
|
|
905
|
+
}
|
|
906
|
+
const message = ((_c = (_b = error.response) == null ? void 0 : _b.data) == null ? void 0 : _c.message) || error.message || "Something went wrong";
|
|
907
|
+
const err = new Error(message);
|
|
908
|
+
err.status = status;
|
|
909
|
+
return Promise.reject(err);
|
|
910
|
+
}
|
|
911
|
+
);
|
|
912
|
+
var api_default = api;
|
|
913
|
+
|
|
904
914
|
// services/news.service.ts
|
|
905
915
|
var getTrendingNews = async () => {
|
|
906
|
-
const { data } = await api_default.get("/
|
|
916
|
+
const { data } = await api_default.get("/news/trending");
|
|
907
917
|
return data.data;
|
|
908
918
|
};
|
|
909
919
|
var getNewsSources = async () => {
|
|
910
|
-
const { data } = await api_default.get("/
|
|
920
|
+
const { data } = await api_default.get("/news/sources");
|
|
911
921
|
return data.data;
|
|
912
922
|
};
|
|
913
923
|
var scrapeNewsSource = async (sourceId) => {
|
|
914
|
-
const { data } = await api_default.post("/
|
|
924
|
+
const { data } = await api_default.post("/news/source", { sourceId });
|
|
915
925
|
return data.data;
|
|
916
926
|
};
|
|
917
927
|
var getNewsBySource = async (sourceId) => {
|
|
918
|
-
const { data } = await api_default.get(`/
|
|
928
|
+
const { data } = await api_default.get(`/news/by-source/${sourceId}`);
|
|
919
929
|
return data.data;
|
|
920
930
|
};
|
|
921
931
|
|
|
922
932
|
// components/chatbot/ChatWindow.tsx
|
|
923
|
-
import
|
|
924
|
-
|
|
933
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
934
|
+
function seoScoreColor2(score) {
|
|
935
|
+
if (score >= 80) return "#10b981";
|
|
936
|
+
if (score >= 60) return "#f59e0b";
|
|
937
|
+
if (score >= 40) return "#f97316";
|
|
938
|
+
return "#ef4444";
|
|
939
|
+
}
|
|
940
|
+
function seoGradeColor2(grade) {
|
|
941
|
+
if (grade === "A") return "#10b981";
|
|
942
|
+
if (grade === "B") return "#3b82f6";
|
|
943
|
+
if (grade === "C") return "#f59e0b";
|
|
944
|
+
if (grade === "D") return "#f97316";
|
|
945
|
+
return "#ef4444";
|
|
946
|
+
}
|
|
925
947
|
var ACTION_ICONS = {
|
|
926
948
|
recreate_article: RefreshCcw2,
|
|
927
949
|
create_summary: ListChecks,
|
|
@@ -938,26 +960,48 @@ function ChatWindow({
|
|
|
938
960
|
activeField,
|
|
939
961
|
analyzedData,
|
|
940
962
|
onSelectAction,
|
|
941
|
-
|
|
963
|
+
onResolveSeo
|
|
942
964
|
}) {
|
|
943
|
-
var _a, _b;
|
|
944
965
|
const { showNewsPanel } = useTheme();
|
|
966
|
+
const THEME_GRADIENT = "linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%)";
|
|
945
967
|
const bottomRef = useRef(null);
|
|
946
968
|
const textareaRef = useRef(null);
|
|
947
969
|
const dropdownRef = useRef(null);
|
|
948
|
-
const
|
|
949
|
-
const [
|
|
950
|
-
const [
|
|
951
|
-
const [
|
|
952
|
-
const [
|
|
953
|
-
const [
|
|
954
|
-
const [
|
|
955
|
-
const [
|
|
956
|
-
const [
|
|
957
|
-
const [
|
|
958
|
-
const {
|
|
959
|
-
const
|
|
960
|
-
const
|
|
970
|
+
const pillsRef = useRef(null);
|
|
971
|
+
const [input, setInput] = useState3("");
|
|
972
|
+
const [copiedId, setCopiedId] = useState3(null);
|
|
973
|
+
const [showNewsDropdown, setShowNewsDropdown] = useState3(false);
|
|
974
|
+
const [trendingNews, setTrendingNews] = useState3([]);
|
|
975
|
+
const [loadingNews, setLoadingNews] = useState3(false);
|
|
976
|
+
const [sources, setSources] = useState3([]);
|
|
977
|
+
const [selectedSource, setSelectedSource] = useState3(null);
|
|
978
|
+
const [loadingSources, setLoadingSources] = useState3(false);
|
|
979
|
+
const [scraping, setScraping] = useState3(false);
|
|
980
|
+
const [editModal, setEditModal] = useState3({ isOpen: false, title: "", subtitle: "", content: "", metaDescription: "", metaKeywords: [], messageId: "", featuredImage: "", seoAnalysis: null });
|
|
981
|
+
const [selectedImages, setSelectedImages] = useState3({});
|
|
982
|
+
const [seoOpen, setSeoOpen] = useState3({});
|
|
983
|
+
const [seoSugOpen, setSeoSugOpen] = useState3({});
|
|
984
|
+
const [isPosting, setIsPosting] = useState3(false);
|
|
985
|
+
const [splitPct, setSplitPct] = useState3(50);
|
|
986
|
+
const wrapperRef = useRef(null);
|
|
987
|
+
const isDragging = useRef(false);
|
|
988
|
+
const handleDragStart = useCallback((e) => {
|
|
989
|
+
e.preventDefault();
|
|
990
|
+
isDragging.current = true;
|
|
991
|
+
const onMove = (ev) => {
|
|
992
|
+
if (!isDragging.current || !wrapperRef.current) return;
|
|
993
|
+
const rect = wrapperRef.current.getBoundingClientRect();
|
|
994
|
+
const pct = (ev.clientX - rect.left) / rect.width * 100;
|
|
995
|
+
setSplitPct(Math.min(80, Math.max(20, pct)));
|
|
996
|
+
};
|
|
997
|
+
const onUp = () => {
|
|
998
|
+
isDragging.current = false;
|
|
999
|
+
window.removeEventListener("mousemove", onMove);
|
|
1000
|
+
window.removeEventListener("mouseup", onUp);
|
|
1001
|
+
};
|
|
1002
|
+
window.addEventListener("mousemove", onMove);
|
|
1003
|
+
window.addEventListener("mouseup", onUp);
|
|
1004
|
+
}, []);
|
|
961
1005
|
const handleCopy = async (parsed, messageId) => {
|
|
962
1006
|
try {
|
|
963
1007
|
const tempDiv = document.createElement("div");
|
|
@@ -977,6 +1021,7 @@ function ChatWindow({
|
|
|
977
1021
|
}
|
|
978
1022
|
};
|
|
979
1023
|
const handleEdit = (parsed, messageId) => {
|
|
1024
|
+
var _a;
|
|
980
1025
|
setEditModal({
|
|
981
1026
|
isOpen: true,
|
|
982
1027
|
title: parsed.title || "",
|
|
@@ -984,23 +1029,99 @@ function ChatWindow({
|
|
|
984
1029
|
content: parsed.articleHtml || "",
|
|
985
1030
|
metaDescription: parsed.metaDescription || "",
|
|
986
1031
|
metaKeywords: parsed.metaKeywords,
|
|
987
|
-
messageId
|
|
1032
|
+
messageId,
|
|
1033
|
+
featuredImage: selectedImages[messageId] || "",
|
|
1034
|
+
seoAnalysis: (_a = parsed.seoAnalysis) != null ? _a : null
|
|
988
1035
|
});
|
|
989
1036
|
};
|
|
1037
|
+
const [downloadingKey, setDownloadingKey] = useState3(null);
|
|
990
1038
|
const handleCloseModal = () => {
|
|
991
|
-
setEditModal({ isOpen: false, title: "", subtitle: "", content: "", metaDescription: "", metaKeywords: [], messageId: "" });
|
|
1039
|
+
setEditModal({ isOpen: false, title: "", subtitle: "", content: "", metaDescription: "", metaKeywords: [], messageId: "", featuredImage: "", seoAnalysis: null });
|
|
992
1040
|
};
|
|
993
|
-
const
|
|
994
|
-
|
|
995
|
-
|
|
1041
|
+
const handleDownload = async (parsed, messageId, format) => {
|
|
1042
|
+
const key = `${messageId}-${format}`;
|
|
1043
|
+
setDownloadingKey(key);
|
|
1044
|
+
try {
|
|
1045
|
+
const apiUrl = getApiBaseUrl();
|
|
1046
|
+
const token = typeof window !== "undefined" ? localStorage.getItem("token") : null;
|
|
1047
|
+
const apiKey = getApiKey();
|
|
1048
|
+
const res = await fetch(`${apiUrl}/contenify/rewrite/download`, {
|
|
1049
|
+
method: "POST",
|
|
1050
|
+
credentials: "include",
|
|
1051
|
+
headers: __spreadValues(__spreadValues({
|
|
1052
|
+
"Content-Type": "application/json"
|
|
1053
|
+
}, token ? { Authorization: `Bearer ${token}` } : {}), apiKey ? { "x-api-key": apiKey } : {}),
|
|
1054
|
+
body: JSON.stringify({
|
|
1055
|
+
title: parsed.title,
|
|
1056
|
+
subtitle: parsed.subtitle,
|
|
1057
|
+
article: parsed.articleHtml,
|
|
1058
|
+
metaDescription: parsed.metaDescription,
|
|
1059
|
+
metaKeywords: parsed.metaKeywords,
|
|
1060
|
+
format
|
|
1061
|
+
})
|
|
1062
|
+
});
|
|
1063
|
+
if (!res.ok) throw new Error("Download failed");
|
|
1064
|
+
const blob = await res.blob();
|
|
1065
|
+
const url = URL.createObjectURL(blob);
|
|
1066
|
+
const a = document.createElement("a");
|
|
1067
|
+
a.href = url;
|
|
1068
|
+
a.download = `article.${format}`;
|
|
1069
|
+
a.click();
|
|
1070
|
+
URL.revokeObjectURL(url);
|
|
1071
|
+
} catch (err) {
|
|
1072
|
+
console.error("Download failed:", err);
|
|
1073
|
+
} finally {
|
|
1074
|
+
setDownloadingKey(null);
|
|
1075
|
+
}
|
|
996
1076
|
};
|
|
997
|
-
const
|
|
998
|
-
|
|
999
|
-
|
|
1077
|
+
const handleDownloadFromModal = async (data, format) => {
|
|
1078
|
+
const key = `modal-${format}`;
|
|
1079
|
+
setDownloadingKey(key);
|
|
1080
|
+
try {
|
|
1081
|
+
const apiUrl = getApiBaseUrl();
|
|
1082
|
+
const token = typeof window !== "undefined" ? localStorage.getItem("token") : null;
|
|
1083
|
+
const apiKey = getApiKey();
|
|
1084
|
+
const res = await fetch(`${apiUrl}/contenify/rewrite/download`, {
|
|
1085
|
+
method: "POST",
|
|
1086
|
+
credentials: "include",
|
|
1087
|
+
headers: __spreadValues(__spreadValues({
|
|
1088
|
+
"Content-Type": "application/json"
|
|
1089
|
+
}, token ? { Authorization: `Bearer ${token}` } : {}), apiKey ? { "x-api-key": apiKey } : {}),
|
|
1090
|
+
body: JSON.stringify({
|
|
1091
|
+
title: data.title,
|
|
1092
|
+
subtitle: data.subtitle,
|
|
1093
|
+
article: data.article,
|
|
1094
|
+
metaDescription: data.metaDescription,
|
|
1095
|
+
metaKeywords: data.keywords,
|
|
1096
|
+
format
|
|
1097
|
+
})
|
|
1098
|
+
});
|
|
1099
|
+
if (!res.ok) throw new Error("Download failed");
|
|
1100
|
+
const blob = await res.blob();
|
|
1101
|
+
const url = URL.createObjectURL(blob);
|
|
1102
|
+
const a = document.createElement("a");
|
|
1103
|
+
a.href = url;
|
|
1104
|
+
a.download = `article.${format}`;
|
|
1105
|
+
a.click();
|
|
1106
|
+
URL.revokeObjectURL(url);
|
|
1107
|
+
} catch (err) {
|
|
1108
|
+
console.error("Download failed:", err);
|
|
1109
|
+
} finally {
|
|
1110
|
+
setDownloadingKey(null);
|
|
1111
|
+
}
|
|
1000
1112
|
};
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1113
|
+
const handlePostFromModal = (data) => {
|
|
1114
|
+
setIsPosting(true);
|
|
1115
|
+
try {
|
|
1116
|
+
console.log("Posting article with data:", data);
|
|
1117
|
+
window.dispatchEvent(new CustomEvent("contenify-post-article", { detail: data }));
|
|
1118
|
+
} finally {
|
|
1119
|
+
setIsPosting(false);
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
|
+
useLayoutEffect2(() => {
|
|
1123
|
+
var _a;
|
|
1124
|
+
(_a = bottomRef.current) == null ? void 0 : _a.scrollIntoView({ block: "end" });
|
|
1004
1125
|
}, [messages]);
|
|
1005
1126
|
const handleSend = () => {
|
|
1006
1127
|
if (!input.trim()) return;
|
|
@@ -1008,13 +1129,16 @@ function ChatWindow({
|
|
|
1008
1129
|
setInput("");
|
|
1009
1130
|
if (textareaRef.current) {
|
|
1010
1131
|
textareaRef.current.style.height = "auto";
|
|
1132
|
+
textareaRef.current.style.borderRadius = "50px";
|
|
1011
1133
|
}
|
|
1012
1134
|
};
|
|
1013
|
-
|
|
1135
|
+
useEffect3(() => {
|
|
1014
1136
|
const textarea = textareaRef.current;
|
|
1015
1137
|
if (textarea) {
|
|
1016
1138
|
textarea.style.height = "auto";
|
|
1017
1139
|
textarea.style.height = `${textarea.scrollHeight}px`;
|
|
1140
|
+
const isMultiline = textarea.scrollHeight > 48;
|
|
1141
|
+
textarea.style.borderRadius = isMultiline ? "1.25rem" : "50px";
|
|
1018
1142
|
}
|
|
1019
1143
|
}, [input]);
|
|
1020
1144
|
const fetchSources = async () => {
|
|
@@ -1040,6 +1164,7 @@ function ChatWindow({
|
|
|
1040
1164
|
setTrendingNews(data || []);
|
|
1041
1165
|
} catch (err) {
|
|
1042
1166
|
console.error("Failed to fetch news:", err);
|
|
1167
|
+
setTrendingNews([]);
|
|
1043
1168
|
} finally {
|
|
1044
1169
|
setLoadingNews(false);
|
|
1045
1170
|
}
|
|
@@ -1056,9 +1181,7 @@ function ChatWindow({
|
|
|
1056
1181
|
setScraping(false);
|
|
1057
1182
|
}
|
|
1058
1183
|
};
|
|
1059
|
-
const handleSourceSelect = (
|
|
1060
|
-
var _a2;
|
|
1061
|
-
const sourceId = (_a2 = option == null ? void 0 : option.value) != null ? _a2 : null;
|
|
1184
|
+
const handleSourceSelect = (sourceId) => {
|
|
1062
1185
|
setSelectedSource(sourceId);
|
|
1063
1186
|
fetchNews(sourceId);
|
|
1064
1187
|
};
|
|
@@ -1071,7 +1194,7 @@ function ChatWindow({
|
|
|
1071
1194
|
fetchNews(selectedSource);
|
|
1072
1195
|
}
|
|
1073
1196
|
};
|
|
1074
|
-
|
|
1197
|
+
useEffect3(() => {
|
|
1075
1198
|
const handleClickOutside = (event) => {
|
|
1076
1199
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
1077
1200
|
setShowNewsDropdown(false);
|
|
@@ -1084,315 +1207,479 @@ function ChatWindow({
|
|
|
1084
1207
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
1085
1208
|
};
|
|
1086
1209
|
}, [showNewsDropdown]);
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
parsed.title && /* @__PURE__ */ jsxs4("h1", { className: "cnfy-block-h1", children: [
|
|
1108
|
-
parsed.title,
|
|
1109
|
-
activeField === "title" && /* @__PURE__ */ jsx5("span", { className: "cnfy-cursor-blink", children: "|" })
|
|
1110
|
-
] }),
|
|
1111
|
-
parsed.subtitle && /* @__PURE__ */ jsxs4("h1", { className: "cnfy-block-h2", children: [
|
|
1112
|
-
parsed.subtitle,
|
|
1113
|
-
activeField === "subtitle" && /* @__PURE__ */ jsx5("span", { className: "cnfy-cursor-blink", children: "|" })
|
|
1114
|
-
] }),
|
|
1115
|
-
/* @__PURE__ */ jsx5("hr", { className: "cnfy-divider" }),
|
|
1116
|
-
parsed.articleHtml && /* @__PURE__ */ jsx5(
|
|
1117
|
-
"div",
|
|
1118
|
-
{
|
|
1119
|
-
className: "cnfy-article-content",
|
|
1120
|
-
dangerouslySetInnerHTML: { __html: parsed.articleHtml }
|
|
1121
|
-
}
|
|
1122
|
-
),
|
|
1123
|
-
activeField === "article" && /* @__PURE__ */ jsx5("span", { className: "cnfy-cursor-blink", children: "|" })
|
|
1124
|
-
] }) : (
|
|
1125
|
-
/* Plain text messages (status, error, options, etc.) */
|
|
1126
|
-
parsed.plainText && /* @__PURE__ */ jsx5("p", { className: "cnfy-block-p", children: parsed.plainText })
|
|
1127
|
-
),
|
|
1128
|
-
parsed.metaDescription && /* @__PURE__ */ jsxs4("div", { className: "cnfy-msg-keywords", children: [
|
|
1129
|
-
/* @__PURE__ */ jsx5("div", { className: "cnfy-msg-keywords-label", children: "Meta Description" }),
|
|
1130
|
-
/* @__PURE__ */ jsx5("div", { className: "cnfy-block-p", children: parsed.metaDescription })
|
|
1131
|
-
] }),
|
|
1132
|
-
parsed.metaKeywords.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "cnfy-msg-keywords", children: [
|
|
1133
|
-
/* @__PURE__ */ jsx5("div", { className: "cnfy-msg-keywords-label", children: "Keywords" }),
|
|
1134
|
-
/* @__PURE__ */ jsx5("div", { className: "cnfy-msg-keywords-list", children: parsed.metaKeywords.map((tag, i) => /* @__PURE__ */ jsx5(
|
|
1135
|
-
"span",
|
|
1136
|
-
{
|
|
1137
|
-
className: "cnfy-msg-keyword-tag",
|
|
1138
|
-
children: tag
|
|
1139
|
-
},
|
|
1140
|
-
i
|
|
1141
|
-
)) })
|
|
1142
|
-
] }),
|
|
1143
|
-
msg.role === "assistant" && (analyzedData == null ? void 0 : analyzedData.messageId) === msg.id && analyzedData.options.length > 0 && /* @__PURE__ */ jsx5("div", { className: "cnfy-action-options", children: analyzedData.options.map((option) => {
|
|
1144
|
-
const IconComponent = ACTION_ICONS[option.id] || FileText;
|
|
1145
|
-
return /* @__PURE__ */ jsxs4(
|
|
1146
|
-
"button",
|
|
1147
|
-
{
|
|
1148
|
-
onClick: () => onSelectAction == null ? void 0 : onSelectAction(option.id, analyzedData.url, analyzedData.content),
|
|
1149
|
-
className: "cnfy-action-btn",
|
|
1150
|
-
children: [
|
|
1151
|
-
/* @__PURE__ */ jsx5(IconComponent, { size: 16 }),
|
|
1152
|
-
option.name
|
|
1153
|
-
]
|
|
1154
|
-
},
|
|
1155
|
-
option.id
|
|
1156
|
-
);
|
|
1157
|
-
}) }),
|
|
1158
|
-
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__ */ jsxs4("div", { className: "cnfy-msg-actions", children: [
|
|
1159
|
-
/* @__PURE__ */ jsxs4(
|
|
1160
|
-
"button",
|
|
1161
|
-
{
|
|
1162
|
-
onClick: () => handleEdit(parsed, msg.id),
|
|
1163
|
-
className: "cnfy-btn-edit",
|
|
1164
|
-
children: [
|
|
1165
|
-
/* @__PURE__ */ jsx5(Edit3, { size: 16 }),
|
|
1166
|
-
"Edit"
|
|
1167
|
-
]
|
|
1168
|
-
}
|
|
1169
|
-
),
|
|
1170
|
-
/* @__PURE__ */ jsxs4(
|
|
1171
|
-
"button",
|
|
1172
|
-
{
|
|
1173
|
-
onClick: () => handlePost({ article: parsed.articleHtml, keywords: parsed.metaKeywords }),
|
|
1174
|
-
className: "cnfy-btn-post",
|
|
1175
|
-
style: { backgroundColor: primaryColor, color: "#fff" },
|
|
1176
|
-
children: [
|
|
1177
|
-
/* @__PURE__ */ jsx5(Send, { size: 16 }),
|
|
1178
|
-
"Post"
|
|
1179
|
-
]
|
|
1180
|
-
}
|
|
1181
|
-
)
|
|
1182
|
-
] })
|
|
1183
|
-
] }) }, msg.id);
|
|
1184
|
-
}),
|
|
1185
|
-
/* @__PURE__ */ jsx5("div", { ref: bottomRef })
|
|
1186
|
-
] }) }),
|
|
1187
|
-
/* @__PURE__ */ jsx5("div", { className: "cnfy-input-area", children: /* @__PURE__ */ jsxs4("div", { className: "cnfy-input-inner", children: [
|
|
1188
|
-
/* @__PURE__ */ jsxs4("div", { ref: dropdownRef, className: "cnfy-news-pulse-wrap", children: [
|
|
1189
|
-
/* @__PURE__ */ jsx5(
|
|
1190
|
-
"button",
|
|
1191
|
-
{
|
|
1192
|
-
onClick: handleOpenNewsDropdown,
|
|
1193
|
-
className: "cnfy-news-pulse-btn cnfy-animate-pulse",
|
|
1194
|
-
title: "Select from trending news",
|
|
1195
|
-
children: /* @__PURE__ */ jsx5(Zap, { size: 16 })
|
|
1196
|
-
}
|
|
1197
|
-
),
|
|
1198
|
-
showNewsDropdown && /* @__PURE__ */ jsxs4("div", { className: "cnfy-news-dropdown", children: [
|
|
1199
|
-
/* @__PURE__ */ jsxs4("div", { className: "cnfy-news-dropdown-header", style: { backgroundColor: primaryColor, color: "#fff" }, children: [
|
|
1200
|
-
/* @__PURE__ */ jsx5("span", { className: "cnfy-news-dropdown-title", children: "Select News" }),
|
|
1201
|
-
/* @__PURE__ */ jsx5(
|
|
1202
|
-
"button",
|
|
1203
|
-
{
|
|
1204
|
-
onClick: () => setShowNewsDropdown(false),
|
|
1205
|
-
className: "cnfy-news-dropdown-close",
|
|
1206
|
-
style: { backgroundColor: primaryColor, color: "#fff" },
|
|
1207
|
-
children: /* @__PURE__ */ jsx5(X2, { size: 14 })
|
|
1208
|
-
}
|
|
1209
|
-
)
|
|
1210
|
-
] }),
|
|
1211
|
-
/* @__PURE__ */ jsxs4("div", { className: "cnfy-news-dropdown-source", children: [
|
|
1212
|
-
/* @__PURE__ */ jsx5("div", { className: "cnfy-news-dropdown-select-wrap", children: /* @__PURE__ */ jsx5(
|
|
1213
|
-
Select,
|
|
1214
|
-
{
|
|
1215
|
-
options: [
|
|
1216
|
-
{ value: null, label: "All Sources (Trending)" },
|
|
1217
|
-
...sources.filter((source) => !preferredLanguage || source.language === preferredLanguage).map((source) => ({
|
|
1218
|
-
value: source.id,
|
|
1219
|
-
label: source.name
|
|
1220
|
-
}))
|
|
1221
|
-
],
|
|
1222
|
-
value: selectedSource ? { value: selectedSource, label: ((_b = sources.find((s) => s.id === selectedSource)) == null ? void 0 : _b.name) || selectedSource } : { value: null, label: "All Sources (Trending)" },
|
|
1223
|
-
onChange: handleSourceSelect,
|
|
1224
|
-
isLoading: loadingSources,
|
|
1225
|
-
isDisabled: loadingSources,
|
|
1226
|
-
placeholder: "Select source...",
|
|
1227
|
-
classNamePrefix: "react-select",
|
|
1228
|
-
menuPlacement: "bottom",
|
|
1229
|
-
menuPosition: "fixed",
|
|
1230
|
-
menuShouldScrollIntoView: false,
|
|
1231
|
-
maxMenuHeight: 220,
|
|
1232
|
-
menuPortalTarget: typeof window !== "undefined" ? document.body : null,
|
|
1233
|
-
styles: {
|
|
1234
|
-
container: (base) => __spreadProps(__spreadValues({}, base), {
|
|
1235
|
-
width: "100%"
|
|
1236
|
-
}),
|
|
1237
|
-
control: (base) => __spreadProps(__spreadValues({}, base), {
|
|
1238
|
-
minHeight: "38px",
|
|
1239
|
-
borderColor: "#e5e7eb",
|
|
1240
|
-
boxShadow: "none",
|
|
1241
|
-
width: "100%"
|
|
1242
|
-
}),
|
|
1243
|
-
menu: (base) => __spreadProps(__spreadValues({}, base), {
|
|
1244
|
-
width: "100%",
|
|
1245
|
-
zIndex: 999999
|
|
1246
|
-
}),
|
|
1247
|
-
menuPortal: (base) => __spreadProps(__spreadValues({}, base), {
|
|
1248
|
-
zIndex: 999999
|
|
1249
|
-
}),
|
|
1250
|
-
option: (base, state) => __spreadProps(__spreadValues({}, base), {
|
|
1251
|
-
backgroundColor: state.isSelected ? primaryColor : state.isFocused ? "#f3f4f6" : "white",
|
|
1252
|
-
color: state.isSelected ? "white" : "#374151",
|
|
1253
|
-
cursor: "pointer"
|
|
1254
|
-
})
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
) }),
|
|
1258
|
-
selectedSource && /* @__PURE__ */ jsxs4(
|
|
1259
|
-
"button",
|
|
1260
|
-
{
|
|
1261
|
-
onClick: handleScrape,
|
|
1262
|
-
disabled: scraping,
|
|
1263
|
-
className: "cnfy-scrape-btn",
|
|
1264
|
-
title: "Fetch latest news",
|
|
1265
|
-
children: [
|
|
1266
|
-
/* @__PURE__ */ jsx5(RefreshCcw2, { size: 14, className: scraping ? "cnfy-animate-spin" : "" }),
|
|
1267
|
-
scraping ? "Scraping..." : "Scrape"
|
|
1268
|
-
]
|
|
1269
|
-
}
|
|
1270
|
-
),
|
|
1271
|
-
!selectedSource && /* @__PURE__ */ jsxs4(
|
|
1272
|
-
"button",
|
|
1273
|
-
{
|
|
1274
|
-
onClick: () => fetchNews(null),
|
|
1275
|
-
disabled: loadingNews,
|
|
1276
|
-
className: "cnfy-refresh-btn",
|
|
1277
|
-
children: [
|
|
1278
|
-
/* @__PURE__ */ jsx5(RefreshCcw2, { size: 14, className: loadingNews ? "cnfy-animate-spin" : "" }),
|
|
1279
|
-
"Refresh"
|
|
1280
|
-
]
|
|
1281
|
-
}
|
|
1282
|
-
)
|
|
1283
|
-
] }),
|
|
1284
|
-
/* @__PURE__ */ jsx5("div", { className: "cnfy-news-dropdown-list", children: loadingNews ? /* @__PURE__ */ jsx5("div", { className: "cnfy-news-dropdown-msg", children: "Loading news..." }) : trendingNews.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "cnfy-news-dropdown-msg", children: [
|
|
1285
|
-
/* @__PURE__ */ jsx5("p", { children: "No news found." }),
|
|
1286
|
-
selectedSource && /* @__PURE__ */ jsx5("p", { className: "cnfy-news-dropdown-hint", children: 'Click "Scrape" to fetch latest news.' })
|
|
1287
|
-
] }) : /* @__PURE__ */ jsx5(
|
|
1288
|
-
NewsList,
|
|
1289
|
-
{
|
|
1290
|
-
news: trendingNews.slice(0, 10),
|
|
1291
|
-
onView: (item) => window.open(item.sourceUrl || item.link, "_blank"),
|
|
1292
|
-
onRecreate: (payload) => {
|
|
1293
|
-
setShowNewsDropdown(false);
|
|
1294
|
-
onSelectNews == null ? void 0 : onSelectNews(payload);
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
) })
|
|
1298
|
-
] })
|
|
1299
|
-
] }),
|
|
1300
|
-
/* @__PURE__ */ jsx5(
|
|
1301
|
-
"textarea",
|
|
1302
|
-
{
|
|
1303
|
-
ref: textareaRef,
|
|
1304
|
-
value: input,
|
|
1305
|
-
onChange: (e) => setInput(e.target.value),
|
|
1306
|
-
onKeyDown: (e) => {
|
|
1307
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
1308
|
-
e.preventDefault();
|
|
1309
|
-
handleSend();
|
|
1310
|
-
}
|
|
1311
|
-
},
|
|
1312
|
-
rows: 1,
|
|
1313
|
-
placeholder: "Ask AI something\u2026",
|
|
1314
|
-
className: `cnfy-chat-textarea ${!showNewsPanel ? "cnfy-chat-textarea--with-pulse" : ""}`,
|
|
1315
|
-
style: { maxHeight: "200px", overflowY: input.split("\n").length > 6 ? "auto" : "hidden" },
|
|
1316
|
-
disabled: true
|
|
1317
|
-
}
|
|
1318
|
-
),
|
|
1319
|
-
/* @__PURE__ */ jsx5(
|
|
1320
|
-
"button",
|
|
1321
|
-
{
|
|
1322
|
-
onClick: handleSend,
|
|
1323
|
-
className: "cnfy-send-btn",
|
|
1324
|
-
style: { backgroundColor: primaryColor, color: "#fff" },
|
|
1325
|
-
children: /* @__PURE__ */ jsx5(SendHorizontal, { size: 18 })
|
|
1326
|
-
}
|
|
1327
|
-
)
|
|
1328
|
-
] }) }),
|
|
1329
|
-
/* @__PURE__ */ jsx5(
|
|
1330
|
-
EditModal,
|
|
1331
|
-
{
|
|
1332
|
-
isOpen: editModal.isOpen,
|
|
1333
|
-
initialTitle: editModal.title,
|
|
1334
|
-
initialSubtitle: editModal.subtitle,
|
|
1335
|
-
initialContent: editModal.content,
|
|
1336
|
-
initialMetaDescription: editModal.metaDescription,
|
|
1337
|
-
metaKeywords: editModal.metaKeywords,
|
|
1338
|
-
onClose: handleCloseModal,
|
|
1339
|
-
onSaveDraft: (data) => handleSaveDraft({ article: data.article, keywords: data.keywords }),
|
|
1340
|
-
onPost: (data) => handlePost({ article: data.article, keywords: data.keywords })
|
|
1341
|
-
}
|
|
1342
|
-
)
|
|
1343
|
-
] });
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
// components/chatbot/UserMenu.tsx
|
|
1347
|
-
import { Settings } from "lucide-react";
|
|
1348
|
-
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
1349
|
-
function UserMenu({
|
|
1350
|
-
onOpenPreferences
|
|
1351
|
-
}) {
|
|
1352
|
-
return /* @__PURE__ */ jsx6("div", { className: "cnfy-user-menu", children: /* @__PURE__ */ jsx6(
|
|
1353
|
-
"button",
|
|
1210
|
+
useEffect3(() => {
|
|
1211
|
+
const el = pillsRef.current;
|
|
1212
|
+
if (!el) return;
|
|
1213
|
+
const onWheel = (e) => {
|
|
1214
|
+
if (e.deltaY === 0) return;
|
|
1215
|
+
e.preventDefault();
|
|
1216
|
+
el.scrollLeft += e.deltaY;
|
|
1217
|
+
};
|
|
1218
|
+
el.addEventListener("wheel", onWheel, { passive: false });
|
|
1219
|
+
return () => el.removeEventListener("wheel", onWheel);
|
|
1220
|
+
}, [showNewsDropdown, loadingSources]);
|
|
1221
|
+
const SUGGESTIONS = [
|
|
1222
|
+
{ icon: /* @__PURE__ */ jsx4(Link2, { size: 13 }), label: "Paste a news URL to rewrite" },
|
|
1223
|
+
{ icon: /* @__PURE__ */ jsx4(PenLine, { size: 13 }), label: "Write a blog post about AI" },
|
|
1224
|
+
{ icon: /* @__PURE__ */ jsx4(LayoutList, { size: 13 }), label: "Summarize today's top stories" },
|
|
1225
|
+
{ icon: /* @__PURE__ */ jsx4(Share2, { size: 13 }), label: "Create social media posts" }
|
|
1226
|
+
];
|
|
1227
|
+
const isEmpty = messages.length === 0;
|
|
1228
|
+
return /* @__PURE__ */ jsxs4(
|
|
1229
|
+
"div",
|
|
1354
1230
|
{
|
|
1355
|
-
|
|
1356
|
-
className: "cnfy-
|
|
1357
|
-
|
|
1358
|
-
|
|
1231
|
+
ref: wrapperRef,
|
|
1232
|
+
className: `cnfy-editor-wrapper${editModal.isOpen ? " cnfy-editor-wrapper--editing" : ""}`,
|
|
1233
|
+
children: [
|
|
1234
|
+
/* @__PURE__ */ jsxs4(
|
|
1235
|
+
"div",
|
|
1236
|
+
{
|
|
1237
|
+
className: `cnfy-chat cnfy-editor-chat-pane${isEmpty ? " cnfy-chat--empty" : ""}`,
|
|
1238
|
+
style: editModal.isOpen ? { flex: `0 0 ${splitPct}%`, width: `${splitPct}%` } : void 0,
|
|
1239
|
+
children: [
|
|
1240
|
+
isEmpty && /* @__PURE__ */ jsxs4("div", { className: "cnfy-empty-hero", children: [
|
|
1241
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-empty-hero-icon", children: /* @__PURE__ */ jsx4(Sparkles, { size: 22 }) }),
|
|
1242
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1243
|
+
/* @__PURE__ */ jsx4("p", { className: "cnfy-empty-state-title", children: "AI News Assistant" }),
|
|
1244
|
+
/* @__PURE__ */ jsx4("p", { className: "cnfy-empty-state-subtitle", children: "Generate, rewrite and publish content in seconds" })
|
|
1245
|
+
] })
|
|
1246
|
+
] }),
|
|
1247
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-chat-area", children: /* @__PURE__ */ jsxs4("div", { className: "cnfy-chat-scroll", children: [
|
|
1248
|
+
messages.map((msg) => {
|
|
1249
|
+
var _a, _b, _c;
|
|
1250
|
+
const parsed = formatAIContent(msg.content);
|
|
1251
|
+
return /* @__PURE__ */ jsx4("div", { className: "cnfy-msg", children: /* @__PURE__ */ jsxs4("div", { className: msg.role === "assistant" ? `cnfy-msg-body` : `cnfy-msg-body you`, children: [
|
|
1252
|
+
msg.role === "assistant" && parsed.isArticle && /* @__PURE__ */ jsxs4("div", { className: "cnfy-msg-copy-row", children: [
|
|
1253
|
+
parsed.seoAnalysis && (!isStreaming || msg.id !== ((_a = messages[messages.length - 1]) == null ? void 0 : _a.id)) && /* @__PURE__ */ jsxs4(
|
|
1254
|
+
"button",
|
|
1255
|
+
{
|
|
1256
|
+
type: "button",
|
|
1257
|
+
onClick: () => setSeoOpen((prev) => __spreadProps(__spreadValues({}, prev), { [msg.id]: !prev[msg.id] })),
|
|
1258
|
+
className: `cnfy-seo-toggle-btn${seoOpen[msg.id] ? " cnfy-seo-toggle-btn--active" : ""}`,
|
|
1259
|
+
title: "SEO Analysis",
|
|
1260
|
+
children: [
|
|
1261
|
+
/* @__PURE__ */ jsx4(BarChart22, { size: 13 }),
|
|
1262
|
+
/* @__PURE__ */ jsxs4(
|
|
1263
|
+
"span",
|
|
1264
|
+
{
|
|
1265
|
+
className: "cnfy-seo-toggle-score",
|
|
1266
|
+
style: { color: seoScoreColor2(parsed.seoAnalysis.overall) },
|
|
1267
|
+
children: [
|
|
1268
|
+
parsed.seoAnalysis.overall,
|
|
1269
|
+
"%"
|
|
1270
|
+
]
|
|
1271
|
+
}
|
|
1272
|
+
)
|
|
1273
|
+
]
|
|
1274
|
+
}
|
|
1275
|
+
),
|
|
1276
|
+
/* @__PURE__ */ jsx4(
|
|
1277
|
+
"button",
|
|
1278
|
+
{
|
|
1279
|
+
onClick: () => handleCopy(parsed, msg.id),
|
|
1280
|
+
className: "cnfy-copy-btn",
|
|
1281
|
+
title: "Copy to clipboard",
|
|
1282
|
+
children: copiedId === msg.id ? /* @__PURE__ */ jsx4(Check, { size: 16, className: "cnfy-copy-icon--copied" }) : /* @__PURE__ */ jsx4(Copy, { size: 16 })
|
|
1283
|
+
}
|
|
1284
|
+
)
|
|
1285
|
+
] }),
|
|
1286
|
+
msg.role === "assistant" && isStreaming && msg.id === ((_b = messages[messages.length - 1]) == null ? void 0 : _b.id) && !parsed.isArticle && !parsed.plainText && /* @__PURE__ */ jsxs4("div", { className: "cnfy-creating-indicator", children: [
|
|
1287
|
+
/* @__PURE__ */ jsx4(Loader22, { size: 16, className: "cnfy-animate-spin" }),
|
|
1288
|
+
/* @__PURE__ */ jsx4("span", { children: "Creating article..." })
|
|
1289
|
+
] }),
|
|
1290
|
+
parsed.isArticle && parsed.seoAnalysis && seoOpen[msg.id] && (() => {
|
|
1291
|
+
const seo = parsed.seoAnalysis;
|
|
1292
|
+
const breakdown = [
|
|
1293
|
+
{ key: "title", label: "Title", section: seo.breakdown.title },
|
|
1294
|
+
{ key: "meta", label: "Meta", section: seo.breakdown.meta },
|
|
1295
|
+
{ key: "content", label: "Content", section: seo.breakdown.content },
|
|
1296
|
+
{ key: "keywords", label: "Keywords", section: seo.breakdown.keywords },
|
|
1297
|
+
{ key: "readability", label: "Readability", section: seo.breakdown.readability }
|
|
1298
|
+
];
|
|
1299
|
+
const allIssues = breakdown.flatMap((b) => {
|
|
1300
|
+
var _a2, _b2;
|
|
1301
|
+
return (_b2 = (_a2 = b.section) == null ? void 0 : _a2.issues) != null ? _b2 : [];
|
|
1302
|
+
}).filter(Boolean);
|
|
1303
|
+
const sugOpen = !!seoSugOpen[msg.id];
|
|
1304
|
+
return /* @__PURE__ */ jsxs4("div", { className: "cnfy-seo-panel", children: [
|
|
1305
|
+
/* @__PURE__ */ jsxs4("div", { className: "cnfy-seo-header", children: [
|
|
1306
|
+
/* @__PURE__ */ jsxs4("div", { className: "cnfy-seo-title", children: [
|
|
1307
|
+
/* @__PURE__ */ jsx4(BarChart22, { size: 13 }),
|
|
1308
|
+
"SEO Analysis",
|
|
1309
|
+
seo.improvement != null && seo.improvement > 0 && /* @__PURE__ */ jsxs4("span", { className: "cnfy-seo-improvement-badge", children: [
|
|
1310
|
+
"\u2191 +",
|
|
1311
|
+
seo.improvement,
|
|
1312
|
+
" pts"
|
|
1313
|
+
] })
|
|
1314
|
+
] }),
|
|
1315
|
+
/* @__PURE__ */ jsxs4("div", { className: "cnfy-seo-score-info", children: [
|
|
1316
|
+
seo.before && /* @__PURE__ */ jsxs4("span", { className: "cnfy-seo-before", children: [
|
|
1317
|
+
"was ",
|
|
1318
|
+
seo.before.overall,
|
|
1319
|
+
/* @__PURE__ */ jsx4("span", { className: "cnfy-seo-before-grade", style: { background: seoGradeColor2(seo.before.grade) }, children: seo.before.grade })
|
|
1320
|
+
] }),
|
|
1321
|
+
/* @__PURE__ */ jsx4("span", { className: "cnfy-seo-score-num", children: seo.overall }),
|
|
1322
|
+
/* @__PURE__ */ jsx4("span", { className: "cnfy-seo-score-denom", children: "/100" }),
|
|
1323
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-seo-grade", style: { background: seoGradeColor2(seo.grade) }, children: seo.grade })
|
|
1324
|
+
] })
|
|
1325
|
+
] }),
|
|
1326
|
+
/* @__PURE__ */ jsxs4("div", { className: "cnfy-seo-body", children: [
|
|
1327
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-seo-overall-bar", children: /* @__PURE__ */ jsx4(
|
|
1328
|
+
"div",
|
|
1329
|
+
{
|
|
1330
|
+
className: "cnfy-seo-overall-fill",
|
|
1331
|
+
style: { width: `${seo.overall}%`, background: seoScoreColor2(seo.overall) }
|
|
1332
|
+
}
|
|
1333
|
+
) }),
|
|
1334
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-seo-breakdown", children: breakdown.map(({ key, label, section }) => section && /* @__PURE__ */ jsxs4("div", { className: "cnfy-seo-breakdown-row", children: [
|
|
1335
|
+
/* @__PURE__ */ jsx4("span", { className: "cnfy-seo-bd-label", children: label }),
|
|
1336
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-seo-bd-bar", children: /* @__PURE__ */ jsx4(
|
|
1337
|
+
"div",
|
|
1338
|
+
{
|
|
1339
|
+
className: "cnfy-seo-bd-fill",
|
|
1340
|
+
style: { width: `${section.score}%`, background: seoScoreColor2(section.score) }
|
|
1341
|
+
}
|
|
1342
|
+
) }),
|
|
1343
|
+
/* @__PURE__ */ jsx4("span", { className: "cnfy-seo-bd-score", style: { color: seoScoreColor2(section.score) }, children: section.score }),
|
|
1344
|
+
section.readingLabel && /* @__PURE__ */ jsx4("span", { className: "cnfy-seo-bd-extra", children: section.readingLabel })
|
|
1345
|
+
] }, key)) }),
|
|
1346
|
+
allIssues.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "cnfy-seo-issues", children: [
|
|
1347
|
+
/* @__PURE__ */ jsxs4("div", { className: "cnfy-seo-issues-title", children: [
|
|
1348
|
+
/* @__PURE__ */ jsx4(AlertTriangle2, { size: 11 }),
|
|
1349
|
+
allIssues.length,
|
|
1350
|
+
" ",
|
|
1351
|
+
allIssues.length === 1 ? "Issue" : "Issues"
|
|
1352
|
+
] }),
|
|
1353
|
+
allIssues.map((issue, i) => /* @__PURE__ */ jsx4("div", { className: "cnfy-seo-issue-item", children: issue }, i))
|
|
1354
|
+
] }),
|
|
1355
|
+
/* @__PURE__ */ jsx4("div", { style: { display: "flex", justifyContent: "flex-end", padding: "8px 0" }, children: /* @__PURE__ */ jsxs4(
|
|
1356
|
+
"button",
|
|
1357
|
+
{
|
|
1358
|
+
onClick: () => {
|
|
1359
|
+
var _a2, _b2, _c2, _d;
|
|
1360
|
+
return onResolveSeo == null ? void 0 : onResolveSeo({
|
|
1361
|
+
title: parsed.title,
|
|
1362
|
+
subtitle: parsed.subtitle,
|
|
1363
|
+
article: parsed.articleHtml,
|
|
1364
|
+
metaDescription: parsed.metaDescription,
|
|
1365
|
+
metaKeywords: parsed.metaKeywords,
|
|
1366
|
+
seoAnalysis: parsed.seoAnalysis,
|
|
1367
|
+
language: (_a2 = parsed.article) == null ? void 0 : _a2.language,
|
|
1368
|
+
historyId: (_d = (_b2 = parsed.article) == null ? void 0 : _b2._id) != null ? _d : (_c2 = parsed.article) == null ? void 0 : _c2.historyId
|
|
1369
|
+
});
|
|
1370
|
+
},
|
|
1371
|
+
disabled: isStreaming,
|
|
1372
|
+
className: "cnfy-btn-fix-seo",
|
|
1373
|
+
children: [
|
|
1374
|
+
/* @__PURE__ */ jsx4(Wand2, { size: 16 }),
|
|
1375
|
+
"Fix SEO"
|
|
1376
|
+
]
|
|
1377
|
+
}
|
|
1378
|
+
) }),
|
|
1379
|
+
seo.suggestions.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "cnfy-seo-suggestions", children: [
|
|
1380
|
+
/* @__PURE__ */ jsxs4(
|
|
1381
|
+
"button",
|
|
1382
|
+
{
|
|
1383
|
+
type: "button",
|
|
1384
|
+
className: "cnfy-seo-suggestions-toggle",
|
|
1385
|
+
onClick: () => setSeoSugOpen((prev) => __spreadProps(__spreadValues({}, prev), { [msg.id]: !prev[msg.id] })),
|
|
1386
|
+
children: [
|
|
1387
|
+
/* @__PURE__ */ jsxs4("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
1388
|
+
/* @__PURE__ */ jsx4(Lightbulb2, { size: 11 }),
|
|
1389
|
+
seo.suggestions.length,
|
|
1390
|
+
" Suggestions"
|
|
1391
|
+
] }),
|
|
1392
|
+
sugOpen ? /* @__PURE__ */ jsx4(ChevronUp2, { size: 12 }) : /* @__PURE__ */ jsx4(ChevronDown2, { size: 12 })
|
|
1393
|
+
]
|
|
1394
|
+
}
|
|
1395
|
+
),
|
|
1396
|
+
sugOpen && /* @__PURE__ */ jsx4("div", { className: "cnfy-seo-suggestions-list", children: seo.suggestions.map((s, i) => /* @__PURE__ */ jsx4("div", { className: "cnfy-seo-suggestion-item", children: s }, i)) })
|
|
1397
|
+
] })
|
|
1398
|
+
] })
|
|
1399
|
+
] });
|
|
1400
|
+
})(),
|
|
1401
|
+
msg.role === "assistant" && (analyzedData == null ? void 0 : analyzedData.messageId) === msg.id && analyzedData.options.length > 0 && /* @__PURE__ */ jsx4("div", { className: "cnfy-action-options", children: analyzedData.options.map((option) => {
|
|
1402
|
+
const IconComponent = ACTION_ICONS[option.id] || FileText;
|
|
1403
|
+
return /* @__PURE__ */ jsxs4(
|
|
1404
|
+
"button",
|
|
1405
|
+
{
|
|
1406
|
+
onClick: () => onSelectAction == null ? void 0 : onSelectAction(option.id, analyzedData.url, analyzedData.content),
|
|
1407
|
+
className: "cnfy-action-btn",
|
|
1408
|
+
children: [
|
|
1409
|
+
/* @__PURE__ */ jsx4(IconComponent, { size: 16 }),
|
|
1410
|
+
option.name
|
|
1411
|
+
]
|
|
1412
|
+
},
|
|
1413
|
+
option.id
|
|
1414
|
+
);
|
|
1415
|
+
}) }),
|
|
1416
|
+
parsed.isArticle ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1417
|
+
parsed.title && /* @__PURE__ */ jsxs4("h1", { className: "cnfy-block-h1", children: [
|
|
1418
|
+
parsed.title,
|
|
1419
|
+
activeField === "title" && /* @__PURE__ */ jsx4("span", { className: "cnfy-cursor-blink", children: "|" })
|
|
1420
|
+
] }),
|
|
1421
|
+
parsed.subtitle && /* @__PURE__ */ jsxs4("h2", { className: "cnfy-block-h2", children: [
|
|
1422
|
+
parsed.subtitle,
|
|
1423
|
+
activeField === "subtitle" && /* @__PURE__ */ jsx4("span", { className: "cnfy-cursor-blink", children: "|" })
|
|
1424
|
+
] }),
|
|
1425
|
+
/* @__PURE__ */ jsx4("hr", { className: "cnfy-divider" }),
|
|
1426
|
+
parsed.articleHtml && /* @__PURE__ */ jsx4(
|
|
1427
|
+
"div",
|
|
1428
|
+
{
|
|
1429
|
+
className: "cnfy-article-content",
|
|
1430
|
+
dangerouslySetInnerHTML: { __html: parsed.articleHtml }
|
|
1431
|
+
}
|
|
1432
|
+
),
|
|
1433
|
+
activeField === "article" && /* @__PURE__ */ jsx4("span", { className: "cnfy-cursor-blink", children: "|" })
|
|
1434
|
+
] }) : (
|
|
1435
|
+
/* Plain text messages (status, error, options, etc.) */
|
|
1436
|
+
parsed.plainText && /* @__PURE__ */ jsx4("p", { className: "cnfy-block-p", children: parsed.plainText })
|
|
1437
|
+
),
|
|
1438
|
+
parsed.metaDescription && /* @__PURE__ */ jsxs4("div", { className: "cnfy-msg-keywords", children: [
|
|
1439
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-msg-keywords-label", children: "Meta Description" }),
|
|
1440
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-block-p", children: parsed.metaDescription })
|
|
1441
|
+
] }),
|
|
1442
|
+
parsed.metaKeywords.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "cnfy-msg-keywords", children: [
|
|
1443
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-msg-keywords-label", children: "Keywords" }),
|
|
1444
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-msg-keywords-list", children: parsed.metaKeywords.map((tag, i) => /* @__PURE__ */ jsx4(
|
|
1445
|
+
"span",
|
|
1446
|
+
{
|
|
1447
|
+
className: "cnfy-msg-keyword-tag",
|
|
1448
|
+
children: tag
|
|
1449
|
+
},
|
|
1450
|
+
i
|
|
1451
|
+
)) })
|
|
1452
|
+
] }),
|
|
1453
|
+
parsed.isArticle && parsed.images.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "cnfy-image-slider-wrap", children: [
|
|
1454
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-image-slider-label", children: "Select a featured image" }),
|
|
1455
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-image-slider", children: parsed.images.map((img, i) => {
|
|
1456
|
+
const isSelected = selectedImages[msg.id] === img.url;
|
|
1457
|
+
return /* @__PURE__ */ jsxs4(
|
|
1458
|
+
"button",
|
|
1459
|
+
{
|
|
1460
|
+
type: "button",
|
|
1461
|
+
onClick: () => setSelectedImages((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
1462
|
+
[msg.id]: isSelected ? "" : img.url
|
|
1463
|
+
})),
|
|
1464
|
+
className: `cnfy-image-slider-item${isSelected ? " cnfy-image-slider-item--selected" : ""}`,
|
|
1465
|
+
title: img.photographer ? `Photo by ${img.photographer}` : void 0,
|
|
1466
|
+
children: [
|
|
1467
|
+
/* @__PURE__ */ jsx4("img", { src: img.thumb, alt: `Image ${i + 1}`, className: "cnfy-image-slider-thumb" }),
|
|
1468
|
+
isSelected && /* @__PURE__ */ jsx4("span", { className: "cnfy-image-slider-check", children: /* @__PURE__ */ jsx4(Check, { size: 12 }) })
|
|
1469
|
+
]
|
|
1470
|
+
},
|
|
1471
|
+
i
|
|
1472
|
+
);
|
|
1473
|
+
}) })
|
|
1474
|
+
] }),
|
|
1475
|
+
msg.role === "assistant" && parsed.isArticle && !(analyzedData == null ? void 0 : analyzedData.messageId) && (!isStreaming || msg.id !== ((_c = messages[messages.length - 1]) == null ? void 0 : _c.id)) && /* @__PURE__ */ jsxs4("div", { className: "cnfy-msg-actions", children: [
|
|
1476
|
+
/* @__PURE__ */ jsxs4(
|
|
1477
|
+
"button",
|
|
1478
|
+
{
|
|
1479
|
+
onClick: () => handleEdit(parsed, msg.id),
|
|
1480
|
+
className: "cnfy-btn-edit",
|
|
1481
|
+
children: [
|
|
1482
|
+
/* @__PURE__ */ jsx4(Edit3, { size: 16 }),
|
|
1483
|
+
"Edit"
|
|
1484
|
+
]
|
|
1485
|
+
}
|
|
1486
|
+
),
|
|
1487
|
+
/* @__PURE__ */ jsxs4(
|
|
1488
|
+
"button",
|
|
1489
|
+
{
|
|
1490
|
+
onClick: () => handleDownload(parsed, msg.id, "docx"),
|
|
1491
|
+
disabled: downloadingKey === `${msg.id}-docx`,
|
|
1492
|
+
className: "cnfy-btn-download",
|
|
1493
|
+
children: [
|
|
1494
|
+
downloadingKey === `${msg.id}-docx` ? /* @__PURE__ */ jsx4(Loader22, { size: 16, className: "cnfy-animate-spin" }) : /* @__PURE__ */ jsx4(FileDown2, { size: 16 }),
|
|
1495
|
+
"DOCX"
|
|
1496
|
+
]
|
|
1497
|
+
}
|
|
1498
|
+
),
|
|
1499
|
+
/* @__PURE__ */ jsxs4(
|
|
1500
|
+
"button",
|
|
1501
|
+
{
|
|
1502
|
+
onClick: () => handleDownload(parsed, msg.id, "pdf"),
|
|
1503
|
+
disabled: downloadingKey === `${msg.id}-pdf`,
|
|
1504
|
+
className: "cnfy-btn-download cnfy-btn-download--pdf",
|
|
1505
|
+
style: { background: THEME_GRADIENT, color: "#fff", border: "none" },
|
|
1506
|
+
children: [
|
|
1507
|
+
downloadingKey === `${msg.id}-pdf` ? /* @__PURE__ */ jsx4(Loader22, { size: 16, className: "cnfy-animate-spin" }) : /* @__PURE__ */ jsx4(FileDown2, { size: 16 }),
|
|
1508
|
+
"PDF"
|
|
1509
|
+
]
|
|
1510
|
+
}
|
|
1511
|
+
)
|
|
1512
|
+
] })
|
|
1513
|
+
] }) }, msg.id);
|
|
1514
|
+
}),
|
|
1515
|
+
/* @__PURE__ */ jsx4("div", { ref: bottomRef })
|
|
1516
|
+
] }) }),
|
|
1517
|
+
isEmpty && /* @__PURE__ */ jsx4("div", { className: "cnfy-suggestions", children: SUGGESTIONS.map((s) => /* @__PURE__ */ jsxs4(
|
|
1518
|
+
"button",
|
|
1519
|
+
{
|
|
1520
|
+
className: "cnfy-suggestion-chip",
|
|
1521
|
+
onClick: () => {
|
|
1522
|
+
var _a;
|
|
1523
|
+
setInput(s.label);
|
|
1524
|
+
(_a = textareaRef.current) == null ? void 0 : _a.focus();
|
|
1525
|
+
},
|
|
1526
|
+
children: [
|
|
1527
|
+
s.icon,
|
|
1528
|
+
s.label
|
|
1529
|
+
]
|
|
1530
|
+
},
|
|
1531
|
+
s.label
|
|
1532
|
+
)) }),
|
|
1533
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-input-area", children: /* @__PURE__ */ jsxs4("div", { className: "cnfy-input-inner", children: [
|
|
1534
|
+
/* @__PURE__ */ jsxs4("div", { ref: dropdownRef, className: "cnfy-news-pulse-wrap", children: [
|
|
1535
|
+
/* @__PURE__ */ jsx4(
|
|
1536
|
+
"button",
|
|
1537
|
+
{
|
|
1538
|
+
onClick: handleOpenNewsDropdown,
|
|
1539
|
+
className: "cnfy-news-pulse-btn cnfy-animate-pulse",
|
|
1540
|
+
title: "Select from trending news",
|
|
1541
|
+
children: /* @__PURE__ */ jsx4(Zap, { size: 16 })
|
|
1542
|
+
}
|
|
1543
|
+
),
|
|
1544
|
+
showNewsDropdown && /* @__PURE__ */ jsxs4("div", { className: "cnfy-news-dropdown", children: [
|
|
1545
|
+
/* @__PURE__ */ jsxs4("div", { className: "cnfy-news-dropdown-header", style: { background: THEME_GRADIENT, color: "#fff" }, children: [
|
|
1546
|
+
/* @__PURE__ */ jsx4("span", { className: "cnfy-news-dropdown-title", children: "Select News" }),
|
|
1547
|
+
/* @__PURE__ */ jsx4(
|
|
1548
|
+
"button",
|
|
1549
|
+
{
|
|
1550
|
+
onClick: () => setShowNewsDropdown(false),
|
|
1551
|
+
className: "cnfy-news-dropdown-close",
|
|
1552
|
+
style: { background: "transparent", color: "#fff" },
|
|
1553
|
+
children: /* @__PURE__ */ jsx4(X2, { size: 14 })
|
|
1554
|
+
}
|
|
1555
|
+
)
|
|
1556
|
+
] }),
|
|
1557
|
+
/* @__PURE__ */ jsxs4("div", { className: "cnfy-source-pills-wrap", children: [
|
|
1558
|
+
loadingSources ? /* @__PURE__ */ jsxs4("div", { className: "cnfy-source-pills-loading", children: [
|
|
1559
|
+
/* @__PURE__ */ jsx4(Loader22, { size: 14, className: "cnfy-animate-spin" }),
|
|
1560
|
+
" Loading sources\u2026"
|
|
1561
|
+
] }) : /* @__PURE__ */ jsxs4("div", { className: "cnfy-source-pills", ref: pillsRef, children: [
|
|
1562
|
+
/* @__PURE__ */ jsx4(
|
|
1563
|
+
"button",
|
|
1564
|
+
{
|
|
1565
|
+
className: `cnfy-source-pill ${!selectedSource ? "cnfy-source-pill--active" : ""}`,
|
|
1566
|
+
style: !selectedSource ? { background: THEME_GRADIENT, borderColor: "transparent", color: "#fff" } : {},
|
|
1567
|
+
onClick: () => handleSourceSelect(null),
|
|
1568
|
+
children: "All"
|
|
1569
|
+
}
|
|
1570
|
+
),
|
|
1571
|
+
sources.map((source) => /* @__PURE__ */ jsx4(
|
|
1572
|
+
"button",
|
|
1573
|
+
{
|
|
1574
|
+
className: `cnfy-source-pill ${selectedSource === source.id ? "cnfy-source-pill--active" : ""}`,
|
|
1575
|
+
style: selectedSource === source.id ? { background: THEME_GRADIENT, borderColor: "transparent", color: "#fff" } : {},
|
|
1576
|
+
onClick: () => handleSourceSelect(source.id),
|
|
1577
|
+
children: source.name
|
|
1578
|
+
},
|
|
1579
|
+
source.id
|
|
1580
|
+
))
|
|
1581
|
+
] }),
|
|
1582
|
+
/* @__PURE__ */ jsx4(
|
|
1583
|
+
"button",
|
|
1584
|
+
{
|
|
1585
|
+
onClick: () => selectedSource ? handleScrape() : fetchNews(null),
|
|
1586
|
+
disabled: scraping || loadingNews,
|
|
1587
|
+
className: "cnfy-source-refresh-btn",
|
|
1588
|
+
title: selectedSource ? "Fetch latest news" : "Refresh",
|
|
1589
|
+
children: /* @__PURE__ */ jsx4(RefreshCcw2, { size: 13, className: scraping || loadingNews ? "cnfy-animate-spin" : "" })
|
|
1590
|
+
}
|
|
1591
|
+
)
|
|
1592
|
+
] }),
|
|
1593
|
+
/* @__PURE__ */ jsx4("div", { className: "cnfy-news-dropdown-list", children: loadingNews ? /* @__PURE__ */ jsx4("div", { className: "cnfy-news-dropdown-msg", children: "Loading news..." }) : trendingNews.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "cnfy-news-dropdown-msg", children: [
|
|
1594
|
+
/* @__PURE__ */ jsx4("p", { children: "No news found." }),
|
|
1595
|
+
selectedSource && /* @__PURE__ */ jsx4("p", { className: "cnfy-news-dropdown-hint", children: 'Click "Scrape" to fetch latest news.' })
|
|
1596
|
+
] }) : /* @__PURE__ */ jsx4(
|
|
1597
|
+
NewsList,
|
|
1598
|
+
{
|
|
1599
|
+
news: trendingNews.slice(0, 10),
|
|
1600
|
+
onView: (item) => window.open(item.sourceUrl || item.link, "_blank"),
|
|
1601
|
+
onRecreate: (payload) => {
|
|
1602
|
+
setShowNewsDropdown(false);
|
|
1603
|
+
onSelectNews == null ? void 0 : onSelectNews(payload);
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
) })
|
|
1607
|
+
] })
|
|
1608
|
+
] }),
|
|
1609
|
+
/* @__PURE__ */ jsx4(
|
|
1610
|
+
"textarea",
|
|
1611
|
+
{
|
|
1612
|
+
ref: textareaRef,
|
|
1613
|
+
value: input,
|
|
1614
|
+
onChange: (e) => setInput(e.target.value),
|
|
1615
|
+
onKeyDown: (e) => {
|
|
1616
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
1617
|
+
e.preventDefault();
|
|
1618
|
+
handleSend();
|
|
1619
|
+
}
|
|
1620
|
+
},
|
|
1621
|
+
rows: 1,
|
|
1622
|
+
placeholder: "Ask AI something\u2026",
|
|
1623
|
+
className: `cnfy-chat-textarea ${!showNewsPanel ? "cnfy-chat-textarea--with-trigger" : ""}`,
|
|
1624
|
+
style: { maxHeight: "200px", overflowY: input.split("\n").length > 6 ? "auto" : "hidden" }
|
|
1625
|
+
}
|
|
1626
|
+
),
|
|
1627
|
+
/* @__PURE__ */ jsx4(
|
|
1628
|
+
"button",
|
|
1629
|
+
{
|
|
1630
|
+
onClick: handleSend,
|
|
1631
|
+
className: "cnfy-send-btn",
|
|
1632
|
+
style: { background: THEME_GRADIENT, color: "#fff" },
|
|
1633
|
+
children: /* @__PURE__ */ jsx4(SendHorizontal, { size: 18 })
|
|
1634
|
+
}
|
|
1635
|
+
)
|
|
1636
|
+
] }) })
|
|
1637
|
+
]
|
|
1638
|
+
}
|
|
1639
|
+
),
|
|
1640
|
+
editModal.isOpen && /* @__PURE__ */ jsx4("div", { className: "cnfy-resize-handle", onMouseDown: handleDragStart, children: /* @__PURE__ */ jsx4("div", { className: "cnfy-resize-handle-bar" }) }),
|
|
1641
|
+
/* @__PURE__ */ jsx4(
|
|
1642
|
+
"div",
|
|
1643
|
+
{
|
|
1644
|
+
className: "cnfy-editor-edit-pane",
|
|
1645
|
+
style: editModal.isOpen ? { flex: `0 0 ${100 - splitPct}%`, width: `${100 - splitPct}%` } : void 0,
|
|
1646
|
+
children: /* @__PURE__ */ jsx4(
|
|
1647
|
+
EditModal,
|
|
1648
|
+
{
|
|
1649
|
+
isOpen: editModal.isOpen,
|
|
1650
|
+
inline: true,
|
|
1651
|
+
initialTitle: editModal.title,
|
|
1652
|
+
initialSubtitle: editModal.subtitle,
|
|
1653
|
+
initialContent: editModal.content,
|
|
1654
|
+
initialMetaDescription: editModal.metaDescription,
|
|
1655
|
+
metaKeywords: editModal.metaKeywords,
|
|
1656
|
+
initialFeaturedImage: editModal.featuredImage,
|
|
1657
|
+
seoAnalysis: editModal.seoAnalysis,
|
|
1658
|
+
onClose: handleCloseModal,
|
|
1659
|
+
onDownload: handleDownloadFromModal,
|
|
1660
|
+
downloadingFormat: (downloadingKey == null ? void 0 : downloadingKey.startsWith("modal-")) ? downloadingKey.replace("modal-", "") : null,
|
|
1661
|
+
onPost: handlePostFromModal,
|
|
1662
|
+
isPosting
|
|
1663
|
+
}
|
|
1664
|
+
)
|
|
1665
|
+
}
|
|
1666
|
+
)
|
|
1667
|
+
]
|
|
1359
1668
|
}
|
|
1360
|
-
)
|
|
1361
|
-
}
|
|
1362
|
-
|
|
1363
|
-
// components/chatbot/headerBar.tsx
|
|
1364
|
-
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1365
|
-
function HeaderBar({
|
|
1366
|
-
onOpenPreferences
|
|
1367
|
-
}) {
|
|
1368
|
-
const { primaryColor, botName, logoUrl } = useTheme();
|
|
1369
|
-
return /* @__PURE__ */ jsx7("header", { className: "cnfy-header", children: /* @__PURE__ */ jsxs5("div", { className: "cnfy-header-inner", children: [
|
|
1370
|
-
/* @__PURE__ */ jsxs5("div", { className: "cnfy-header-left", children: [
|
|
1371
|
-
logoUrl ? /* @__PURE__ */ jsx7("img", { src: logoUrl, alt: "Logo", className: "cnfy-header-logo-img" }) : /* @__PURE__ */ jsx7(
|
|
1372
|
-
"div",
|
|
1373
|
-
{
|
|
1374
|
-
className: "cnfy-header-logo-fallback",
|
|
1375
|
-
style: { backgroundColor: primaryColor },
|
|
1376
|
-
children: botName.charAt(0).toUpperCase()
|
|
1377
|
-
}
|
|
1378
|
-
),
|
|
1379
|
-
/* @__PURE__ */ jsx7("span", { className: "cnfy-header-brand", children: botName.toUpperCase() })
|
|
1380
|
-
] }),
|
|
1381
|
-
/* @__PURE__ */ jsx7("div", { className: "cnfy-header-right", children: /* @__PURE__ */ jsx7(UserMenu, { onOpenPreferences }) })
|
|
1382
|
-
] }) });
|
|
1669
|
+
);
|
|
1383
1670
|
}
|
|
1384
1671
|
|
|
1385
1672
|
// components/ui/Drawer.tsx
|
|
1386
|
-
import { useEffect as
|
|
1673
|
+
import { useEffect as useEffect4 } from "react";
|
|
1387
1674
|
import { X as X3 } from "lucide-react";
|
|
1388
|
-
import { jsx as
|
|
1675
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1389
1676
|
function Drawer({
|
|
1390
1677
|
open,
|
|
1391
1678
|
onClose,
|
|
1392
1679
|
title,
|
|
1393
1680
|
children
|
|
1394
1681
|
}) {
|
|
1395
|
-
|
|
1682
|
+
useEffect4(() => {
|
|
1396
1683
|
if (open) {
|
|
1397
1684
|
document.body.style.overflow = "hidden";
|
|
1398
1685
|
} else {
|
|
@@ -1403,20 +1690,20 @@ function Drawer({
|
|
|
1403
1690
|
};
|
|
1404
1691
|
}, [open]);
|
|
1405
1692
|
if (!open) return null;
|
|
1406
|
-
return /* @__PURE__ */
|
|
1407
|
-
/* @__PURE__ */
|
|
1408
|
-
/* @__PURE__ */
|
|
1409
|
-
/* @__PURE__ */
|
|
1410
|
-
title && /* @__PURE__ */
|
|
1411
|
-
/* @__PURE__ */
|
|
1693
|
+
return /* @__PURE__ */ jsxs5("div", { className: "cnfy-drawer-overlay", children: [
|
|
1694
|
+
/* @__PURE__ */ jsx5("div", { className: "cnfy-drawer-backdrop", onClick: onClose }),
|
|
1695
|
+
/* @__PURE__ */ jsxs5("div", { className: "cnfy-drawer-panel", children: [
|
|
1696
|
+
/* @__PURE__ */ jsxs5("div", { className: "cnfy-drawer-header", children: [
|
|
1697
|
+
title && /* @__PURE__ */ jsx5("h2", { className: "cnfy-drawer-title", children: title }),
|
|
1698
|
+
/* @__PURE__ */ jsx5("button", { onClick: onClose, className: "cnfy-drawer-close-btn", children: /* @__PURE__ */ jsx5(X3, { size: 20 }) })
|
|
1412
1699
|
] }),
|
|
1413
|
-
/* @__PURE__ */
|
|
1700
|
+
/* @__PURE__ */ jsx5("div", { className: "cnfy-drawer-body", children })
|
|
1414
1701
|
] })
|
|
1415
1702
|
] });
|
|
1416
1703
|
}
|
|
1417
1704
|
|
|
1418
1705
|
// components/preferences/Preferences.tsx
|
|
1419
|
-
import { useState as
|
|
1706
|
+
import { useState as useState4, useEffect as useEffect5 } from "react";
|
|
1420
1707
|
import toast from "react-hot-toast";
|
|
1421
1708
|
|
|
1422
1709
|
// services/settings.service.ts
|
|
@@ -1424,45 +1711,19 @@ var triggerScrape = async ({
|
|
|
1424
1711
|
state,
|
|
1425
1712
|
cities
|
|
1426
1713
|
}) => {
|
|
1427
|
-
const { data } = await api_default.post("/
|
|
1714
|
+
const { data } = await api_default.post("/news/trigger", {
|
|
1428
1715
|
state,
|
|
1429
1716
|
cities
|
|
1430
1717
|
});
|
|
1431
1718
|
return data;
|
|
1432
1719
|
};
|
|
1433
1720
|
var getScrapeStatus = async () => {
|
|
1434
|
-
const { data } = await api_default.get("/
|
|
1721
|
+
const { data } = await api_default.get("/news/status");
|
|
1435
1722
|
return data.data;
|
|
1436
1723
|
};
|
|
1437
1724
|
|
|
1438
|
-
// components/ClientSelect.tsx
|
|
1439
|
-
import { useEffect as useEffect6, useState as useState5 } from "react";
|
|
1440
|
-
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1441
|
-
var ReactSelect = null;
|
|
1442
|
-
var ClientSelect = (props) => {
|
|
1443
|
-
const [mounted, setMounted] = useState5(false);
|
|
1444
|
-
useEffect6(() => {
|
|
1445
|
-
setMounted(true);
|
|
1446
|
-
import("react-select").then((mod) => {
|
|
1447
|
-
ReactSelect = mod.default;
|
|
1448
|
-
});
|
|
1449
|
-
}, []);
|
|
1450
|
-
if (!mounted || !ReactSelect) return null;
|
|
1451
|
-
return /* @__PURE__ */ jsx9(ReactSelect, __spreadValues({}, props));
|
|
1452
|
-
};
|
|
1453
|
-
var ClientSelect_default = ClientSelect;
|
|
1454
|
-
|
|
1455
|
-
// src/utils/util.ts
|
|
1456
|
-
var hexToRgba = (hex, opacity) => {
|
|
1457
|
-
const sanitizedHex = hex.replace("#", "");
|
|
1458
|
-
const r = parseInt(sanitizedHex.substring(0, 2), 16);
|
|
1459
|
-
const g = parseInt(sanitizedHex.substring(2, 4), 16);
|
|
1460
|
-
const b = parseInt(sanitizedHex.substring(4, 6), 16);
|
|
1461
|
-
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
1462
|
-
};
|
|
1463
|
-
|
|
1464
1725
|
// components/preferences/Preferences.tsx
|
|
1465
|
-
import { Fragment as
|
|
1726
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1466
1727
|
var STATE_OPTIONS = [
|
|
1467
1728
|
{ value: "Uttar Pradesh", label: "Uttar Pradesh" }
|
|
1468
1729
|
];
|
|
@@ -1497,27 +1758,24 @@ var LANGUAGE_OPTIONS = [
|
|
|
1497
1758
|
{ value: "hi", label: "Hindi" }
|
|
1498
1759
|
];
|
|
1499
1760
|
function PreferencesPage() {
|
|
1500
|
-
|
|
1501
|
-
const
|
|
1502
|
-
const
|
|
1503
|
-
const [
|
|
1504
|
-
const [
|
|
1505
|
-
const [
|
|
1506
|
-
const [
|
|
1507
|
-
const [
|
|
1508
|
-
const [
|
|
1509
|
-
const [
|
|
1510
|
-
const [
|
|
1511
|
-
const [
|
|
1512
|
-
const [scrapeStatus, setScrapeStatus] = useState6(null);
|
|
1513
|
-
const [loadingStatus, setLoadingStatus] = useState6(true);
|
|
1514
|
-
const [originalValues, setOriginalValues] = useState6({
|
|
1761
|
+
const primaryColor = "#10b981";
|
|
1762
|
+
const [botName, setBotName] = useState4("");
|
|
1763
|
+
const [logo, setLogo] = useState4(null);
|
|
1764
|
+
const [logoUrl, setLogoUrl] = useState4(null);
|
|
1765
|
+
const [state, setState] = useState4(null);
|
|
1766
|
+
const [cities, setCities] = useState4([]);
|
|
1767
|
+
const [language, setLanguage] = useState4(null);
|
|
1768
|
+
const [saving, setSaving] = useState4(false);
|
|
1769
|
+
const [scraping, setScraping] = useState4(false);
|
|
1770
|
+
const [scrapeStatus, setScrapeStatus] = useState4(null);
|
|
1771
|
+
const [loadingStatus, setLoadingStatus] = useState4(true);
|
|
1772
|
+
const [originalValues, setOriginalValues] = useState4({
|
|
1515
1773
|
botName: "",
|
|
1516
1774
|
state: void 0,
|
|
1517
1775
|
cities: [],
|
|
1518
1776
|
language: void 0
|
|
1519
1777
|
});
|
|
1520
|
-
|
|
1778
|
+
useEffect5(() => {
|
|
1521
1779
|
const fetchScrapeStatus = async () => {
|
|
1522
1780
|
try {
|
|
1523
1781
|
const data = await getScrapeStatus();
|
|
@@ -1531,12 +1789,11 @@ function PreferencesPage() {
|
|
|
1531
1789
|
fetchScrapeStatus();
|
|
1532
1790
|
}, []);
|
|
1533
1791
|
const handleScrape = async () => {
|
|
1534
|
-
var _a2, _b2;
|
|
1535
1792
|
setScraping(true);
|
|
1536
1793
|
try {
|
|
1537
1794
|
await triggerScrape({
|
|
1538
|
-
state:
|
|
1539
|
-
cities: (
|
|
1795
|
+
state: state == null ? void 0 : state.value,
|
|
1796
|
+
cities: cities.map((c) => c.value)
|
|
1540
1797
|
});
|
|
1541
1798
|
toast.success("News scraping started successfully!");
|
|
1542
1799
|
setTimeout(async () => {
|
|
@@ -1554,40 +1811,12 @@ function PreferencesPage() {
|
|
|
1554
1811
|
setScraping(false);
|
|
1555
1812
|
}
|
|
1556
1813
|
};
|
|
1557
|
-
useEffect7(() => {
|
|
1558
|
-
var _a2, _b2, _c2, _d, _e;
|
|
1559
|
-
if (preferences) {
|
|
1560
|
-
const name = ((_a2 = preferences.chatbot) == null ? void 0 : _a2.name) || "";
|
|
1561
|
-
const pState = (_b2 = preferences.localization) == null ? void 0 : _b2.state;
|
|
1562
|
-
const pCities = ((_c2 = preferences.localization) == null ? void 0 : _c2.cities) || [];
|
|
1563
|
-
const pLanguage = (_d = preferences.localization) == null ? void 0 : _d.language;
|
|
1564
|
-
setBotName(name);
|
|
1565
|
-
if ((_e = preferences.chatbot) == null ? void 0 : _e.logoUrl) setLogoUrl(preferences.chatbot.logoUrl);
|
|
1566
|
-
if (pState) {
|
|
1567
|
-
setState({ value: pState, label: pState });
|
|
1568
|
-
}
|
|
1569
|
-
if (Array.isArray(pCities)) {
|
|
1570
|
-
setCities(pCities.map((city) => ({ value: city, label: city })));
|
|
1571
|
-
}
|
|
1572
|
-
if (pLanguage) {
|
|
1573
|
-
const langOption = LANGUAGE_OPTIONS.find((opt) => opt.value === pLanguage);
|
|
1574
|
-
setLanguage(langOption || null);
|
|
1575
|
-
}
|
|
1576
|
-
setOriginalValues({
|
|
1577
|
-
botName: name,
|
|
1578
|
-
state: pState,
|
|
1579
|
-
cities: pCities,
|
|
1580
|
-
language: pLanguage
|
|
1581
|
-
});
|
|
1582
|
-
}
|
|
1583
|
-
}, [preferences]);
|
|
1584
1814
|
const handleSave = async () => {
|
|
1585
1815
|
if (!botName) {
|
|
1586
1816
|
toast.error("Chatbot name is required");
|
|
1587
1817
|
return;
|
|
1588
1818
|
}
|
|
1589
1819
|
setSaving(true);
|
|
1590
|
-
setSuccess(false);
|
|
1591
1820
|
try {
|
|
1592
1821
|
const payload = {};
|
|
1593
1822
|
if (botName !== originalValues.botName) {
|
|
@@ -1614,13 +1843,6 @@ function PreferencesPage() {
|
|
|
1614
1843
|
setSaving(false);
|
|
1615
1844
|
return;
|
|
1616
1845
|
}
|
|
1617
|
-
const updatedPreferences = await savePreferencesApi(payload);
|
|
1618
|
-
if (updatedPreferences) {
|
|
1619
|
-
updatePreferences(updatedPreferences);
|
|
1620
|
-
} else {
|
|
1621
|
-
await refreshPreferences();
|
|
1622
|
-
}
|
|
1623
|
-
setSuccess(true);
|
|
1624
1846
|
setLogo(null);
|
|
1625
1847
|
toast.success("Preferences saved successfully!");
|
|
1626
1848
|
} catch (error) {
|
|
@@ -1630,15 +1852,12 @@ function PreferencesPage() {
|
|
|
1630
1852
|
setSaving(false);
|
|
1631
1853
|
}
|
|
1632
1854
|
};
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
/* @__PURE__ */ jsxs7("div", { className: "cnfy-dash-field", children: [
|
|
1640
|
-
/* @__PURE__ */ jsx10("label", { className: "cnfy-dash-label", children: "Chatbot Name" }),
|
|
1641
|
-
/* @__PURE__ */ jsx10(
|
|
1855
|
+
return /* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-page", children: [
|
|
1856
|
+
/* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-card", children: [
|
|
1857
|
+
/* @__PURE__ */ jsx6("h2", { className: "cnfy-dash-card-title", children: "Chatbot Settings" }),
|
|
1858
|
+
/* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-field", children: [
|
|
1859
|
+
/* @__PURE__ */ jsx6("label", { className: "cnfy-dash-label", children: "Chatbot Name" }),
|
|
1860
|
+
/* @__PURE__ */ jsx6(
|
|
1642
1861
|
"input",
|
|
1643
1862
|
{
|
|
1644
1863
|
value: botName,
|
|
@@ -1648,32 +1867,38 @@ function PreferencesPage() {
|
|
|
1648
1867
|
}
|
|
1649
1868
|
)
|
|
1650
1869
|
] }),
|
|
1651
|
-
/* @__PURE__ */
|
|
1652
|
-
/* @__PURE__ */
|
|
1653
|
-
/* @__PURE__ */
|
|
1654
|
-
/* @__PURE__ */
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1870
|
+
/* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-field", children: [
|
|
1871
|
+
/* @__PURE__ */ jsx6("label", { className: "cnfy-dash-label", children: "Chatbot Logo" }),
|
|
1872
|
+
/* @__PURE__ */ jsxs6("div", { className: "cnfy-logo-upload", children: [
|
|
1873
|
+
/* @__PURE__ */ jsx6("div", { className: "cnfy-logo-preview", children: logo ? (
|
|
1874
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
1875
|
+
/* @__PURE__ */ jsx6(
|
|
1876
|
+
"img",
|
|
1877
|
+
{
|
|
1878
|
+
src: URL.createObjectURL(logo),
|
|
1879
|
+
alt: "Logo preview",
|
|
1880
|
+
className: "cnfy-logo-img"
|
|
1881
|
+
}
|
|
1882
|
+
)
|
|
1883
|
+
) : logoUrl ? (
|
|
1884
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
1885
|
+
/* @__PURE__ */ jsx6(
|
|
1886
|
+
"img",
|
|
1887
|
+
{
|
|
1888
|
+
src: logoUrl,
|
|
1889
|
+
alt: "Current logo",
|
|
1890
|
+
className: "cnfy-logo-img"
|
|
1891
|
+
}
|
|
1892
|
+
)
|
|
1893
|
+
) : /* @__PURE__ */ jsx6("span", { className: "cnfy-logo-placeholder", children: "No logo" }) }),
|
|
1894
|
+
/* @__PURE__ */ jsx6(
|
|
1670
1895
|
"input",
|
|
1671
1896
|
{
|
|
1672
1897
|
type: "file",
|
|
1673
1898
|
accept: "image/*",
|
|
1674
1899
|
onChange: (e) => {
|
|
1675
|
-
var
|
|
1676
|
-
return setLogo(((
|
|
1900
|
+
var _a;
|
|
1901
|
+
return setLogo(((_a = e.target.files) == null ? void 0 : _a[0]) || null);
|
|
1677
1902
|
},
|
|
1678
1903
|
className: "cnfy-file-input"
|
|
1679
1904
|
}
|
|
@@ -1681,38 +1906,38 @@ function PreferencesPage() {
|
|
|
1681
1906
|
] })
|
|
1682
1907
|
] })
|
|
1683
1908
|
] }),
|
|
1684
|
-
/* @__PURE__ */
|
|
1685
|
-
/* @__PURE__ */
|
|
1686
|
-
/* @__PURE__ */
|
|
1687
|
-
/* @__PURE__ */
|
|
1909
|
+
/* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-card", children: [
|
|
1910
|
+
/* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-card-header", children: [
|
|
1911
|
+
/* @__PURE__ */ jsx6("h2", { className: "cnfy-dash-card-title-inline", children: "News Scraping" }),
|
|
1912
|
+
/* @__PURE__ */ jsx6("p", { className: "cnfy-dash-card-desc", children: "Scrape latest news from your configured locations" })
|
|
1688
1913
|
] }),
|
|
1689
|
-
!loadingStatus && scrapeStatus && /* @__PURE__ */
|
|
1690
|
-
/* @__PURE__ */
|
|
1691
|
-
/* @__PURE__ */
|
|
1692
|
-
/* @__PURE__ */
|
|
1914
|
+
!loadingStatus && scrapeStatus && /* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-grid cnfy-dash-grid--sm", children: [
|
|
1915
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
1916
|
+
/* @__PURE__ */ jsx6("span", { className: "cnfy-dash-label-muted", children: "Status:" }),
|
|
1917
|
+
/* @__PURE__ */ jsx6("p", { className: "cnfy-dash-label-bold", children: scrapeStatus.isRunning ? /* @__PURE__ */ jsx6("span", { className: "cnfy-dash-badge cnfy-dash-badge--yellow", children: "Running" }) : /* @__PURE__ */ jsx6("span", { className: "cnfy-dash-badge cnfy-dash-badge--green", children: "Idle" }) })
|
|
1693
1918
|
] }),
|
|
1694
|
-
scrapeStatus.lastRun && /* @__PURE__ */
|
|
1695
|
-
/* @__PURE__ */
|
|
1696
|
-
/* @__PURE__ */
|
|
1919
|
+
scrapeStatus.lastRun && /* @__PURE__ */ jsxs6("div", { children: [
|
|
1920
|
+
/* @__PURE__ */ jsx6("span", { className: "cnfy-dash-label-muted", children: "Last Run:" }),
|
|
1921
|
+
/* @__PURE__ */ jsx6("p", { className: "cnfy-dash-label-bold", children: new Date(scrapeStatus.lastRun).toLocaleString() })
|
|
1697
1922
|
] }),
|
|
1698
|
-
scrapeStatus.totalScraped !== void 0 && /* @__PURE__ */
|
|
1699
|
-
/* @__PURE__ */
|
|
1700
|
-
/* @__PURE__ */
|
|
1923
|
+
scrapeStatus.totalScraped !== void 0 && /* @__PURE__ */ jsxs6("div", { children: [
|
|
1924
|
+
/* @__PURE__ */ jsx6("span", { className: "cnfy-dash-label-muted", children: "Total Scraped:" }),
|
|
1925
|
+
/* @__PURE__ */ jsxs6("p", { className: "cnfy-dash-label-bold", children: [
|
|
1701
1926
|
scrapeStatus.totalScraped.toLocaleString(),
|
|
1702
1927
|
" articles"
|
|
1703
1928
|
] })
|
|
1704
1929
|
] })
|
|
1705
1930
|
] }),
|
|
1706
|
-
/* @__PURE__ */
|
|
1707
|
-
/* @__PURE__ */
|
|
1931
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
1932
|
+
/* @__PURE__ */ jsxs6("p", { className: "cnfy-dash-info-text", children: [
|
|
1708
1933
|
"Current configuration: ",
|
|
1709
|
-
/* @__PURE__ */
|
|
1710
|
-
|
|
1934
|
+
/* @__PURE__ */ jsx6("strong", { children: state == null ? void 0 : state.value }),
|
|
1935
|
+
cities.length > 0 && /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1711
1936
|
" - ",
|
|
1712
|
-
|
|
1937
|
+
cities.map((c) => c.label).join(", ")
|
|
1713
1938
|
] })
|
|
1714
1939
|
] }),
|
|
1715
|
-
/* @__PURE__ */
|
|
1940
|
+
/* @__PURE__ */ jsx6(
|
|
1716
1941
|
"button",
|
|
1717
1942
|
{
|
|
1718
1943
|
onClick: handleScrape,
|
|
@@ -1724,48 +1949,54 @@ function PreferencesPage() {
|
|
|
1724
1949
|
)
|
|
1725
1950
|
] })
|
|
1726
1951
|
] }),
|
|
1727
|
-
/* @__PURE__ */
|
|
1728
|
-
/* @__PURE__ */
|
|
1729
|
-
/* @__PURE__ */
|
|
1730
|
-
/* @__PURE__ */
|
|
1731
|
-
/* @__PURE__ */
|
|
1732
|
-
|
|
1952
|
+
/* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-card", children: [
|
|
1953
|
+
/* @__PURE__ */ jsx6("h2", { className: "cnfy-dash-card-title", children: "Localization Settings" }),
|
|
1954
|
+
/* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-field", children: [
|
|
1955
|
+
/* @__PURE__ */ jsx6("label", { className: "cnfy-dash-label", children: "State" }),
|
|
1956
|
+
/* @__PURE__ */ jsxs6(
|
|
1957
|
+
"select",
|
|
1733
1958
|
{
|
|
1734
|
-
|
|
1735
|
-
value: state,
|
|
1736
|
-
onChange: (
|
|
1737
|
-
|
|
1959
|
+
className: "cnfy-dash-input",
|
|
1960
|
+
value: (state == null ? void 0 : state.value) || "",
|
|
1961
|
+
onChange: (e) => setState(STATE_OPTIONS.find((o) => o.value === e.target.value) || null),
|
|
1962
|
+
children: [
|
|
1963
|
+
/* @__PURE__ */ jsx6("option", { value: "", children: "Select state" }),
|
|
1964
|
+
STATE_OPTIONS.map((opt) => /* @__PURE__ */ jsx6("option", { value: opt.value, children: opt.label }, opt.value))
|
|
1965
|
+
]
|
|
1738
1966
|
}
|
|
1739
1967
|
)
|
|
1740
1968
|
] }),
|
|
1741
|
-
/* @__PURE__ */
|
|
1742
|
-
/* @__PURE__ */
|
|
1743
|
-
/* @__PURE__ */
|
|
1744
|
-
|
|
1969
|
+
/* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-field", children: [
|
|
1970
|
+
/* @__PURE__ */ jsx6("label", { className: "cnfy-dash-label", children: "Cities" }),
|
|
1971
|
+
/* @__PURE__ */ jsx6(
|
|
1972
|
+
"select",
|
|
1745
1973
|
{
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
value: cities,
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1974
|
+
multiple: true,
|
|
1975
|
+
className: "cnfy-dash-input",
|
|
1976
|
+
value: cities.map((c) => c.value),
|
|
1977
|
+
disabled: !state,
|
|
1978
|
+
onChange: (e) => setCities(Array.from(e.target.selectedOptions).map((o) => ({ value: o.value, label: o.text }))),
|
|
1979
|
+
children: CITY_OPTIONS.map((opt) => /* @__PURE__ */ jsx6("option", { value: opt.value, children: opt.label }, opt.value))
|
|
1752
1980
|
}
|
|
1753
1981
|
)
|
|
1754
1982
|
] }),
|
|
1755
|
-
/* @__PURE__ */
|
|
1756
|
-
/* @__PURE__ */
|
|
1757
|
-
/* @__PURE__ */
|
|
1758
|
-
|
|
1983
|
+
/* @__PURE__ */ jsxs6("div", { className: "cnfy-dash-field", children: [
|
|
1984
|
+
/* @__PURE__ */ jsx6("label", { className: "cnfy-dash-label", children: "Language" }),
|
|
1985
|
+
/* @__PURE__ */ jsxs6(
|
|
1986
|
+
"select",
|
|
1759
1987
|
{
|
|
1760
|
-
|
|
1761
|
-
value: language,
|
|
1762
|
-
onChange: (
|
|
1763
|
-
|
|
1988
|
+
className: "cnfy-dash-input",
|
|
1989
|
+
value: (language == null ? void 0 : language.value) || "",
|
|
1990
|
+
onChange: (e) => setLanguage(LANGUAGE_OPTIONS.find((o) => o.value === e.target.value) || null),
|
|
1991
|
+
children: [
|
|
1992
|
+
/* @__PURE__ */ jsx6("option", { value: "", children: "Select language" }),
|
|
1993
|
+
LANGUAGE_OPTIONS.map((opt) => /* @__PURE__ */ jsx6("option", { value: opt.value, children: opt.label }, opt.value))
|
|
1994
|
+
]
|
|
1764
1995
|
}
|
|
1765
1996
|
)
|
|
1766
1997
|
] })
|
|
1767
1998
|
] }),
|
|
1768
|
-
/* @__PURE__ */
|
|
1999
|
+
/* @__PURE__ */ jsx6("div", { className: "cnfy-dash-actions", children: /* @__PURE__ */ jsx6(
|
|
1769
2000
|
"button",
|
|
1770
2001
|
{
|
|
1771
2002
|
onClick: handleSave,
|
|
@@ -1778,14 +2009,245 @@ function PreferencesPage() {
|
|
|
1778
2009
|
] });
|
|
1779
2010
|
}
|
|
1780
2011
|
|
|
1781
|
-
//
|
|
2012
|
+
// components/history/HistoryPanel.tsx
|
|
2013
|
+
import { useCallback as useCallback2, useEffect as useEffect6, useState as useState5 } from "react";
|
|
2014
|
+
import { Trash2, Loader2 as Loader23, ChevronDown as ChevronDown3, AlertCircle, FileText as FileText2, SquarePen, History, PanelLeftOpen, PanelLeftClose } from "lucide-react";
|
|
2015
|
+
|
|
2016
|
+
// services/history.service.ts
|
|
1782
2017
|
function getHeaders() {
|
|
2018
|
+
const token = typeof window !== "undefined" ? localStorage.getItem("token") : null;
|
|
1783
2019
|
const apiKey = getApiKey();
|
|
1784
|
-
|
|
2020
|
+
return __spreadValues(__spreadValues({
|
|
1785
2021
|
"Content-Type": "application/json"
|
|
2022
|
+
}, token ? { Authorization: `Bearer ${token}` } : {}), apiKey ? { "x-api-key": apiKey } : {});
|
|
2023
|
+
}
|
|
2024
|
+
async function getHistory(page = 1, limit = 20) {
|
|
2025
|
+
const apiUrl = getApiBaseUrl();
|
|
2026
|
+
const res = await fetch(`${apiUrl}/contenify/history?page=${page}&limit=${limit}`, {
|
|
2027
|
+
credentials: "include",
|
|
2028
|
+
headers: getHeaders()
|
|
2029
|
+
});
|
|
2030
|
+
if (!res.ok) throw new Error("Failed to fetch history");
|
|
2031
|
+
const { data } = await res.json();
|
|
2032
|
+
return data;
|
|
2033
|
+
}
|
|
2034
|
+
async function getHistoryItem(id) {
|
|
2035
|
+
const apiUrl = getApiBaseUrl();
|
|
2036
|
+
const res = await fetch(`${apiUrl}/contenify/history/${id}`, {
|
|
2037
|
+
credentials: "include",
|
|
2038
|
+
headers: getHeaders()
|
|
2039
|
+
});
|
|
2040
|
+
if (!res.ok) throw new Error("Failed to fetch history item");
|
|
2041
|
+
const { data } = await res.json();
|
|
2042
|
+
return data;
|
|
2043
|
+
}
|
|
2044
|
+
async function deleteHistoryItem(id) {
|
|
2045
|
+
const apiUrl = getApiBaseUrl();
|
|
2046
|
+
const res = await fetch(`${apiUrl}/contenify/history/${id}`, {
|
|
2047
|
+
method: "DELETE",
|
|
2048
|
+
credentials: "include",
|
|
2049
|
+
headers: getHeaders()
|
|
2050
|
+
});
|
|
2051
|
+
if (!res.ok) throw new Error("Failed to delete history item");
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
// components/history/HistoryPanel.tsx
|
|
2055
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2056
|
+
function formatDate(iso) {
|
|
2057
|
+
const d = new Date(iso);
|
|
2058
|
+
const now = /* @__PURE__ */ new Date();
|
|
2059
|
+
const diffMs = now.getTime() - d.getTime();
|
|
2060
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
2061
|
+
if (diffDays === 0) return "Today";
|
|
2062
|
+
if (diffDays === 1) return "Yesterday";
|
|
2063
|
+
if (diffDays < 7) return `${diffDays} days ago`;
|
|
2064
|
+
return d.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
2065
|
+
}
|
|
2066
|
+
function groupByDate(items) {
|
|
2067
|
+
const groups = {};
|
|
2068
|
+
for (const item of items) {
|
|
2069
|
+
const label = formatDate(item.createdAt);
|
|
2070
|
+
if (!groups[label]) groups[label] = [];
|
|
2071
|
+
groups[label].push(item);
|
|
2072
|
+
}
|
|
2073
|
+
return Object.entries(groups).map(([label, items2]) => ({ label, items: items2 }));
|
|
2074
|
+
}
|
|
2075
|
+
function HistoryPanel({ onSelect, onNewChat }) {
|
|
2076
|
+
const [collapsed, setCollapsed] = useState5(false);
|
|
2077
|
+
const [items, setItems] = useState5([]);
|
|
2078
|
+
const [pagination, setPagination] = useState5(null);
|
|
2079
|
+
const [page, setPage] = useState5(1);
|
|
2080
|
+
const [loading, setLoading] = useState5(false);
|
|
2081
|
+
const [loadingMore, setLoadingMore] = useState5(false);
|
|
2082
|
+
const [error, setError] = useState5(null);
|
|
2083
|
+
const [deletingId, setDeletingId] = useState5(null);
|
|
2084
|
+
const [selectingId, setSelectingId] = useState5(null);
|
|
2085
|
+
const [hoveredId, setHoveredId] = useState5(null);
|
|
2086
|
+
const fetchPage = useCallback2(async (p, replace) => {
|
|
2087
|
+
if (p === 1) setLoading(true);
|
|
2088
|
+
else setLoadingMore(true);
|
|
2089
|
+
setError(null);
|
|
2090
|
+
try {
|
|
2091
|
+
const result = await getHistory(p, 20);
|
|
2092
|
+
setItems((prev) => replace ? result.items : [...prev, ...result.items]);
|
|
2093
|
+
setPagination(result.pagination);
|
|
2094
|
+
setPage(p);
|
|
2095
|
+
} catch (e) {
|
|
2096
|
+
setError("Failed to load history");
|
|
2097
|
+
} finally {
|
|
2098
|
+
setLoading(false);
|
|
2099
|
+
setLoadingMore(false);
|
|
2100
|
+
}
|
|
2101
|
+
}, []);
|
|
2102
|
+
useEffect6(() => {
|
|
2103
|
+
fetchPage(1, true);
|
|
2104
|
+
}, [fetchPage]);
|
|
2105
|
+
const handleDelete = async (e, id) => {
|
|
2106
|
+
e.stopPropagation();
|
|
2107
|
+
setDeletingId(id);
|
|
2108
|
+
try {
|
|
2109
|
+
await deleteHistoryItem(id);
|
|
2110
|
+
setItems((prev) => prev.filter((i) => i._id !== id));
|
|
2111
|
+
setPagination((prev) => prev ? __spreadProps(__spreadValues({}, prev), { total: prev.total - 1 }) : prev);
|
|
2112
|
+
} catch (e2) {
|
|
2113
|
+
} finally {
|
|
2114
|
+
setDeletingId(null);
|
|
2115
|
+
}
|
|
2116
|
+
};
|
|
2117
|
+
const handleSelect = async (id) => {
|
|
2118
|
+
setSelectingId(id);
|
|
2119
|
+
try {
|
|
2120
|
+
await onSelect(id);
|
|
2121
|
+
setCollapsed(true);
|
|
2122
|
+
} finally {
|
|
2123
|
+
setSelectingId(null);
|
|
2124
|
+
}
|
|
1786
2125
|
};
|
|
1787
|
-
|
|
1788
|
-
|
|
2126
|
+
const hasMore = pagination ? page < pagination.pages : false;
|
|
2127
|
+
const groups = groupByDate(items);
|
|
2128
|
+
if (collapsed) {
|
|
2129
|
+
return /* @__PURE__ */ jsxs7("div", { className: "cnfy-history-panel cnfy-history-panel--collapsed", children: [
|
|
2130
|
+
/* @__PURE__ */ jsx7(
|
|
2131
|
+
"button",
|
|
2132
|
+
{
|
|
2133
|
+
className: "cnfy-history-icon-btn",
|
|
2134
|
+
onClick: () => setCollapsed(false),
|
|
2135
|
+
title: "Expand history",
|
|
2136
|
+
children: /* @__PURE__ */ jsx7(PanelLeftOpen, { size: 18 })
|
|
2137
|
+
}
|
|
2138
|
+
),
|
|
2139
|
+
/* @__PURE__ */ jsx7(
|
|
2140
|
+
"button",
|
|
2141
|
+
{
|
|
2142
|
+
className: "cnfy-history-icon-btn",
|
|
2143
|
+
onClick: onNewChat,
|
|
2144
|
+
title: "New chat",
|
|
2145
|
+
children: /* @__PURE__ */ jsx7(SquarePen, { size: 18 })
|
|
2146
|
+
}
|
|
2147
|
+
),
|
|
2148
|
+
/* @__PURE__ */ jsx7("div", { className: "cnfy-history-icon-divider" }),
|
|
2149
|
+
/* @__PURE__ */ jsx7(
|
|
2150
|
+
"button",
|
|
2151
|
+
{
|
|
2152
|
+
className: "cnfy-history-icon-btn",
|
|
2153
|
+
onClick: () => setCollapsed(false),
|
|
2154
|
+
title: "History",
|
|
2155
|
+
children: /* @__PURE__ */ jsx7(History, { size: 18 })
|
|
2156
|
+
}
|
|
2157
|
+
)
|
|
2158
|
+
] });
|
|
2159
|
+
}
|
|
2160
|
+
return /* @__PURE__ */ jsxs7("div", { className: "cnfy-history-panel", children: [
|
|
2161
|
+
/* @__PURE__ */ jsxs7("div", { className: "cnfy-history-header", children: [
|
|
2162
|
+
/* @__PURE__ */ jsx7(
|
|
2163
|
+
"button",
|
|
2164
|
+
{
|
|
2165
|
+
className: "cnfy-history-icon-btn",
|
|
2166
|
+
onClick: () => setCollapsed(true),
|
|
2167
|
+
title: "Collapse sidebar",
|
|
2168
|
+
children: /* @__PURE__ */ jsx7(PanelLeftClose, { size: 18 })
|
|
2169
|
+
}
|
|
2170
|
+
),
|
|
2171
|
+
/* @__PURE__ */ jsx7(
|
|
2172
|
+
"button",
|
|
2173
|
+
{
|
|
2174
|
+
className: "cnfy-history-icon-btn",
|
|
2175
|
+
onClick: onNewChat,
|
|
2176
|
+
title: "New chat",
|
|
2177
|
+
children: /* @__PURE__ */ jsx7(SquarePen, { size: 18 })
|
|
2178
|
+
}
|
|
2179
|
+
)
|
|
2180
|
+
] }),
|
|
2181
|
+
/* @__PURE__ */ jsxs7("div", { className: "cnfy-history-body", children: [
|
|
2182
|
+
loading && /* @__PURE__ */ jsx7("div", { className: "cnfy-history-loading", children: /* @__PURE__ */ jsx7(Loader23, { size: 18, className: "cnfy-animate-spin" }) }),
|
|
2183
|
+
!loading && error && /* @__PURE__ */ jsxs7("div", { className: "cnfy-history-error", children: [
|
|
2184
|
+
/* @__PURE__ */ jsx7(AlertCircle, { size: 15 }),
|
|
2185
|
+
/* @__PURE__ */ jsx7("span", { children: error }),
|
|
2186
|
+
/* @__PURE__ */ jsx7("button", { onClick: () => fetchPage(1, true), className: "cnfy-history-retry-btn", children: "Retry" })
|
|
2187
|
+
] }),
|
|
2188
|
+
!loading && !error && items.length === 0 && /* @__PURE__ */ jsxs7("div", { className: "cnfy-history-empty", children: [
|
|
2189
|
+
/* @__PURE__ */ jsx7(FileText2, { size: 24, className: "cnfy-history-empty-icon" }),
|
|
2190
|
+
/* @__PURE__ */ jsx7("p", { children: "No history yet" })
|
|
2191
|
+
] }),
|
|
2192
|
+
!loading && groups.map((group) => /* @__PURE__ */ jsxs7("div", { className: "cnfy-history-group", children: [
|
|
2193
|
+
/* @__PURE__ */ jsx7("div", { className: "cnfy-history-group-label", children: group.label }),
|
|
2194
|
+
group.items.map((item) => /* @__PURE__ */ jsxs7(
|
|
2195
|
+
"div",
|
|
2196
|
+
{
|
|
2197
|
+
className: `cnfy-history-item${selectingId ? " cnfy-history-item--disabled" : ""}`,
|
|
2198
|
+
onClick: () => !selectingId && handleSelect(item._id),
|
|
2199
|
+
onMouseEnter: () => setHoveredId(item._id),
|
|
2200
|
+
onMouseLeave: () => setHoveredId(null),
|
|
2201
|
+
role: "button",
|
|
2202
|
+
tabIndex: 0,
|
|
2203
|
+
onKeyDown: (e) => e.key === "Enter" && !selectingId && handleSelect(item._id),
|
|
2204
|
+
children: [
|
|
2205
|
+
/* @__PURE__ */ jsxs7("span", { className: "cnfy-history-item-title", children: [
|
|
2206
|
+
selectingId === item._id ? /* @__PURE__ */ jsx7(Loader23, { size: 12, className: "cnfy-animate-spin cnfy-history-item-spinner" }) : null,
|
|
2207
|
+
item.title || "Untitled"
|
|
2208
|
+
] }),
|
|
2209
|
+
(hoveredId === item._id || deletingId === item._id) && /* @__PURE__ */ jsx7(
|
|
2210
|
+
"button",
|
|
2211
|
+
{
|
|
2212
|
+
className: "cnfy-history-delete-btn",
|
|
2213
|
+
onClick: (e) => handleDelete(e, item._id),
|
|
2214
|
+
disabled: deletingId === item._id,
|
|
2215
|
+
title: "Delete",
|
|
2216
|
+
children: deletingId === item._id ? /* @__PURE__ */ jsx7(Loader23, { size: 12, className: "cnfy-animate-spin" }) : /* @__PURE__ */ jsx7(Trash2, { size: 12 })
|
|
2217
|
+
}
|
|
2218
|
+
)
|
|
2219
|
+
]
|
|
2220
|
+
},
|
|
2221
|
+
item._id
|
|
2222
|
+
))
|
|
2223
|
+
] }, group.label)),
|
|
2224
|
+
hasMore && !loading && /* @__PURE__ */ jsx7(
|
|
2225
|
+
"button",
|
|
2226
|
+
{
|
|
2227
|
+
onClick: () => fetchPage(page + 1, false),
|
|
2228
|
+
disabled: loadingMore,
|
|
2229
|
+
className: "cnfy-history-load-more",
|
|
2230
|
+
children: loadingMore ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
2231
|
+
/* @__PURE__ */ jsx7(Loader23, { size: 13, className: "cnfy-animate-spin" }),
|
|
2232
|
+
" Loading\u2026"
|
|
2233
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
2234
|
+
/* @__PURE__ */ jsx7(ChevronDown3, { size: 13 }),
|
|
2235
|
+
" Load more"
|
|
2236
|
+
] })
|
|
2237
|
+
}
|
|
2238
|
+
)
|
|
2239
|
+
] })
|
|
2240
|
+
] });
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
// services/chat.service.ts
|
|
2244
|
+
function getHeaders2() {
|
|
2245
|
+
const apiKey = getApiKey();
|
|
2246
|
+
const headers = { "Content-Type": "application/json" };
|
|
2247
|
+
if (apiKey) headers["x-api-key"] = apiKey;
|
|
2248
|
+
if (typeof window !== "undefined") {
|
|
2249
|
+
const token = localStorage.getItem("token");
|
|
2250
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
1789
2251
|
}
|
|
1790
2252
|
return headers;
|
|
1791
2253
|
}
|
|
@@ -1793,7 +2255,7 @@ async function processSSEStream(reader, callbacks) {
|
|
|
1793
2255
|
const decoder = new TextDecoder();
|
|
1794
2256
|
let buffer = "";
|
|
1795
2257
|
const processLines = (lines) => {
|
|
1796
|
-
var _a, _b, _c, _d, _e;
|
|
2258
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1797
2259
|
for (const line of lines) {
|
|
1798
2260
|
const trimmed = line.trim();
|
|
1799
2261
|
if (!trimmed.startsWith("data: ")) continue;
|
|
@@ -1803,6 +2265,7 @@ async function processSSEStream(reader, callbacks) {
|
|
|
1803
2265
|
switch (event.type) {
|
|
1804
2266
|
case "start":
|
|
1805
2267
|
break;
|
|
2268
|
+
// Structured streaming (articleId present): field-scoped chunks
|
|
1806
2269
|
case "field_start":
|
|
1807
2270
|
(_a = callbacks.onFieldStart) == null ? void 0 : _a.call(callbacks, event.field);
|
|
1808
2271
|
break;
|
|
@@ -1818,8 +2281,12 @@ async function processSSEStream(reader, callbacks) {
|
|
|
1818
2281
|
case "done":
|
|
1819
2282
|
(_d = callbacks.onComplete) == null ? void 0 : _d.call(callbacks, event.data);
|
|
1820
2283
|
return true;
|
|
2284
|
+
// Plain token streaming (no articleId): route directly to article body
|
|
2285
|
+
case "token":
|
|
2286
|
+
callbacks.onContent("article", (_e = event.content) != null ? _e : "");
|
|
2287
|
+
break;
|
|
1821
2288
|
case "error":
|
|
1822
|
-
(
|
|
2289
|
+
(_f = callbacks.onError) == null ? void 0 : _f.call(callbacks, new Error(event.message));
|
|
1823
2290
|
return true;
|
|
1824
2291
|
}
|
|
1825
2292
|
} catch (e) {
|
|
@@ -1835,16 +2302,14 @@ async function processSSEStream(reader, callbacks) {
|
|
|
1835
2302
|
buffer = lines.pop() || "";
|
|
1836
2303
|
if (processLines(lines)) return;
|
|
1837
2304
|
}
|
|
1838
|
-
if (buffer.trim())
|
|
1839
|
-
processLines([buffer]);
|
|
1840
|
-
}
|
|
2305
|
+
if (buffer.trim()) processLines([buffer]);
|
|
1841
2306
|
}
|
|
1842
2307
|
var analyzeInputApi = async (input) => {
|
|
1843
|
-
const { data } = await api_default.post("/
|
|
2308
|
+
const { data } = await api_default.post("/contenify/analyze-input", { input });
|
|
1844
2309
|
return data.data;
|
|
1845
2310
|
};
|
|
1846
2311
|
var createContentApi = async (payload) => {
|
|
1847
|
-
const { data } = await api_default.post("/
|
|
2312
|
+
const { data } = await api_default.post("/contenify/create-content", payload);
|
|
1848
2313
|
return data.data;
|
|
1849
2314
|
};
|
|
1850
2315
|
var createContentStreamApi = async ({
|
|
@@ -1861,9 +2326,9 @@ var createContentStreamApi = async ({
|
|
|
1861
2326
|
}) => {
|
|
1862
2327
|
var _a;
|
|
1863
2328
|
const API_BASE_URL = getApiBaseUrl();
|
|
1864
|
-
const response = await fetch(`${API_BASE_URL}/
|
|
2329
|
+
const response = await fetch(`${API_BASE_URL}/contenify/create-content/stream`, {
|
|
1865
2330
|
method: "POST",
|
|
1866
|
-
headers:
|
|
2331
|
+
headers: getHeaders2(),
|
|
1867
2332
|
credentials: "include",
|
|
1868
2333
|
body: JSON.stringify({ url, content, actionId, settings })
|
|
1869
2334
|
});
|
|
@@ -1872,17 +2337,8 @@ var createContentStreamApi = async ({
|
|
|
1872
2337
|
throw new Error(`HTTP error! status: ${response.status} - ${errorText}`);
|
|
1873
2338
|
}
|
|
1874
2339
|
const reader = (_a = response.body) == null ? void 0 : _a.getReader();
|
|
1875
|
-
if (!reader)
|
|
1876
|
-
|
|
1877
|
-
}
|
|
1878
|
-
await processSSEStream(reader, {
|
|
1879
|
-
onFieldStart,
|
|
1880
|
-
onContent,
|
|
1881
|
-
onKeywords,
|
|
1882
|
-
onFieldEnd,
|
|
1883
|
-
onComplete,
|
|
1884
|
-
onError
|
|
1885
|
-
});
|
|
2340
|
+
if (!reader) throw new Error("No reader available");
|
|
2341
|
+
await processSSEStream(reader, { onFieldStart, onContent, onKeywords, onFieldEnd, onComplete, onError });
|
|
1886
2342
|
};
|
|
1887
2343
|
var rewriteNewsStreamApi = async ({
|
|
1888
2344
|
article,
|
|
@@ -1902,10 +2358,7 @@ var rewriteNewsStreamApi = async ({
|
|
|
1902
2358
|
onError
|
|
1903
2359
|
}) => {
|
|
1904
2360
|
var _a;
|
|
1905
|
-
const payload = {
|
|
1906
|
-
article,
|
|
1907
|
-
language
|
|
1908
|
-
};
|
|
2361
|
+
const payload = { article, language, temperature: 1 };
|
|
1909
2362
|
if (articleId) payload.articleId = articleId;
|
|
1910
2363
|
if (tone) payload.tone = tone;
|
|
1911
2364
|
if (style) payload.style = style;
|
|
@@ -1915,9 +2368,9 @@ var rewriteNewsStreamApi = async ({
|
|
|
1915
2368
|
if (targetAudience) payload.targetAudience = targetAudience;
|
|
1916
2369
|
try {
|
|
1917
2370
|
const API_BASE_URL = getApiBaseUrl();
|
|
1918
|
-
const response = await fetch(`${API_BASE_URL}/
|
|
2371
|
+
const response = await fetch(`${API_BASE_URL}/contenify/rewrite/stream`, {
|
|
1919
2372
|
method: "POST",
|
|
1920
|
-
headers:
|
|
2373
|
+
headers: getHeaders2(),
|
|
1921
2374
|
credentials: "include",
|
|
1922
2375
|
body: JSON.stringify(payload)
|
|
1923
2376
|
});
|
|
@@ -1928,33 +2381,56 @@ var rewriteNewsStreamApi = async ({
|
|
|
1928
2381
|
const contentType = response.headers.get("content-type") || "";
|
|
1929
2382
|
if (contentType.includes("application/json")) {
|
|
1930
2383
|
const json = await response.json();
|
|
1931
|
-
const
|
|
2384
|
+
const d = json.data || json;
|
|
1932
2385
|
onComplete == null ? void 0 : onComplete({
|
|
1933
|
-
title:
|
|
1934
|
-
subtitle:
|
|
1935
|
-
article:
|
|
1936
|
-
metaDescription:
|
|
1937
|
-
metaKeywords: Array.isArray(
|
|
2386
|
+
title: d.title || "",
|
|
2387
|
+
subtitle: d.subtitle || "",
|
|
2388
|
+
article: d.article || "",
|
|
2389
|
+
metaDescription: d.metaDescription || "",
|
|
2390
|
+
metaKeywords: Array.isArray(d.metaKeywords) ? d.metaKeywords : []
|
|
1938
2391
|
});
|
|
1939
2392
|
return;
|
|
1940
2393
|
}
|
|
1941
2394
|
const reader = (_a = response.body) == null ? void 0 : _a.getReader();
|
|
1942
|
-
if (!reader)
|
|
1943
|
-
|
|
1944
|
-
}
|
|
1945
|
-
await processSSEStream(reader, {
|
|
1946
|
-
onFieldStart,
|
|
1947
|
-
onContent,
|
|
1948
|
-
onKeywords,
|
|
1949
|
-
onFieldEnd,
|
|
1950
|
-
onComplete,
|
|
1951
|
-
onError
|
|
1952
|
-
});
|
|
2395
|
+
if (!reader) throw new Error("No reader available");
|
|
2396
|
+
await processSSEStream(reader, { onFieldStart, onContent, onKeywords, onFieldEnd, onComplete, onError });
|
|
1953
2397
|
} catch (error) {
|
|
1954
|
-
onError == null ? void 0 : onError(error);
|
|
2398
|
+
onError == null ? void 0 : onError(error instanceof Error ? error : new Error(String(error)));
|
|
1955
2399
|
throw error;
|
|
1956
2400
|
}
|
|
1957
2401
|
};
|
|
2402
|
+
var resolveSeoStreamApi = async ({
|
|
2403
|
+
historyId,
|
|
2404
|
+
title,
|
|
2405
|
+
subtitle,
|
|
2406
|
+
metaDescription,
|
|
2407
|
+
metaKeywords,
|
|
2408
|
+
article,
|
|
2409
|
+
language,
|
|
2410
|
+
seoAnalysis,
|
|
2411
|
+
onFieldStart,
|
|
2412
|
+
onContent,
|
|
2413
|
+
onKeywords,
|
|
2414
|
+
onFieldEnd,
|
|
2415
|
+
onComplete,
|
|
2416
|
+
onError
|
|
2417
|
+
}) => {
|
|
2418
|
+
var _a;
|
|
2419
|
+
const API_BASE_URL = getApiBaseUrl();
|
|
2420
|
+
const response = await fetch(`${API_BASE_URL}/seo-engine/resolve/stream`, {
|
|
2421
|
+
method: "POST",
|
|
2422
|
+
headers: getHeaders2(),
|
|
2423
|
+
credentials: "include",
|
|
2424
|
+
body: JSON.stringify({ historyId, title, subtitle, metaDescription, metaKeywords, article, language, seoAnalysis })
|
|
2425
|
+
});
|
|
2426
|
+
if (!response.ok) {
|
|
2427
|
+
const errorText = await response.text();
|
|
2428
|
+
throw new Error(`HTTP error! status: ${response.status} - ${errorText}`);
|
|
2429
|
+
}
|
|
2430
|
+
const reader = (_a = response.body) == null ? void 0 : _a.getReader();
|
|
2431
|
+
if (!reader) throw new Error("No reader available");
|
|
2432
|
+
await processSSEStream(reader, { onFieldStart, onContent, onKeywords, onFieldEnd, onComplete, onError });
|
|
2433
|
+
};
|
|
1958
2434
|
var rewriteNewsApi = async ({
|
|
1959
2435
|
article,
|
|
1960
2436
|
language = "English",
|
|
@@ -1966,10 +2442,7 @@ var rewriteNewsApi = async ({
|
|
|
1966
2442
|
includeFAQ,
|
|
1967
2443
|
targetAudience
|
|
1968
2444
|
}) => {
|
|
1969
|
-
const payload = {
|
|
1970
|
-
article,
|
|
1971
|
-
language
|
|
1972
|
-
};
|
|
2445
|
+
const payload = { article, language, temperature: 1 };
|
|
1973
2446
|
if (articleId) payload.articleId = articleId;
|
|
1974
2447
|
if (tone) payload.tone = tone;
|
|
1975
2448
|
if (style) payload.style = style;
|
|
@@ -1977,69 +2450,49 @@ var rewriteNewsApi = async ({
|
|
|
1977
2450
|
if (includeQuotes !== void 0) payload.includeQuotes = includeQuotes;
|
|
1978
2451
|
if (includeFAQ !== void 0) payload.includeFAQ = includeFAQ;
|
|
1979
2452
|
if (targetAudience) payload.targetAudience = targetAudience;
|
|
1980
|
-
const { data } = await api_default.post("/
|
|
2453
|
+
const { data } = await api_default.post("/contenify/rewrite", payload);
|
|
1981
2454
|
return data.data;
|
|
1982
2455
|
};
|
|
1983
2456
|
|
|
1984
2457
|
// components/chatbot/ChatBot.tsx
|
|
1985
2458
|
import toast2 from "react-hot-toast";
|
|
1986
|
-
import { Loader2 as
|
|
1987
|
-
import { jsx as
|
|
2459
|
+
import { Loader2 as Loader24 } from "lucide-react";
|
|
2460
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1988
2461
|
function buildStructuredContent(title, article, metaKeywords, subtitle = "", metaDescription = "") {
|
|
1989
2462
|
return JSON.stringify({ title, subtitle, article, metaDescription, metaKeywords });
|
|
1990
2463
|
}
|
|
1991
|
-
function ChatBot(
|
|
2464
|
+
function ChatBot() {
|
|
1992
2465
|
const { loading } = useTheme();
|
|
1993
|
-
const
|
|
1994
|
-
const [
|
|
1995
|
-
const [
|
|
1996
|
-
const [
|
|
1997
|
-
const [
|
|
1998
|
-
const [analyzedData, setAnalyzedData] = useState7(null);
|
|
2466
|
+
const [preferencesOpen, setPreferencesOpen] = useState6(false);
|
|
2467
|
+
const [messages, setMessages] = useState6([]);
|
|
2468
|
+
const [isStreaming, setIsStreaming] = useState6(false);
|
|
2469
|
+
const [activeField, setActiveField] = useState6(null);
|
|
2470
|
+
const [analyzedData, setAnalyzedData] = useState6(null);
|
|
1999
2471
|
const handleRecreate = async ({ title, content, id }) => {
|
|
2000
|
-
var _a;
|
|
2001
2472
|
const assistantId = crypto.randomUUID();
|
|
2002
2473
|
setMessages((prev) => [
|
|
2003
2474
|
...prev,
|
|
2004
|
-
{
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
content: `Recreate this news:
|
|
2008
|
-
${title}`
|
|
2009
|
-
},
|
|
2010
|
-
{
|
|
2011
|
-
id: assistantId,
|
|
2012
|
-
role: "assistant",
|
|
2013
|
-
content: ""
|
|
2014
|
-
}
|
|
2475
|
+
{ id: crypto.randomUUID(), role: "user", content: `Recreate this news:
|
|
2476
|
+
${title}` },
|
|
2477
|
+
{ id: assistantId, role: "assistant", content: "" }
|
|
2015
2478
|
]);
|
|
2016
2479
|
setIsStreaming(true);
|
|
2017
2480
|
try {
|
|
2018
2481
|
let hasStartedStreaming = false;
|
|
2482
|
+
let streamDone = false;
|
|
2483
|
+
let pendingError = null;
|
|
2019
2484
|
let titleBuffer = "";
|
|
2020
2485
|
let articleBuffer = "";
|
|
2021
2486
|
let keywordsBuffer = [];
|
|
2022
2487
|
const updateMessage = () => {
|
|
2023
2488
|
const structured = buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2024
|
-
setMessages(
|
|
2025
|
-
(prev) => prev.map(
|
|
2026
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2027
|
-
)
|
|
2028
|
-
);
|
|
2489
|
+
setMessages((prev) => prev.map((m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m));
|
|
2029
2490
|
};
|
|
2030
|
-
const contentPrefs = preferences == null ? void 0 : preferences.content;
|
|
2031
|
-
const lang = ((_a = preferences == null ? void 0 : preferences.localization) == null ? void 0 : _a.language) === "hi" ? "Hindi" : "English";
|
|
2032
2491
|
try {
|
|
2033
2492
|
await rewriteNewsStreamApi({
|
|
2034
2493
|
article: content || "",
|
|
2035
|
-
language:
|
|
2494
|
+
language: "English",
|
|
2036
2495
|
articleId: id,
|
|
2037
|
-
tone: contentPrefs == null ? void 0 : contentPrefs.tone,
|
|
2038
|
-
style: contentPrefs == null ? void 0 : contentPrefs.style,
|
|
2039
|
-
wordCount: contentPrefs == null ? void 0 : contentPrefs.wordCount,
|
|
2040
|
-
includeQuotes: contentPrefs == null ? void 0 : contentPrefs.includeQuotes,
|
|
2041
|
-
includeFAQ: contentPrefs == null ? void 0 : contentPrefs.includeFAQ,
|
|
2042
|
-
targetAudience: contentPrefs == null ? void 0 : contentPrefs.targetAudience,
|
|
2043
2496
|
onFieldStart: (field) => {
|
|
2044
2497
|
setActiveField(field);
|
|
2045
2498
|
},
|
|
@@ -2057,99 +2510,69 @@ function ChatBot({ onPost }) {
|
|
|
2057
2510
|
setActiveField(null);
|
|
2058
2511
|
},
|
|
2059
2512
|
onComplete: (data) => {
|
|
2513
|
+
streamDone = true;
|
|
2060
2514
|
const finalContent = data && (data.title || data.article) ? JSON.stringify(data) : buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2061
|
-
setMessages(
|
|
2062
|
-
(prev) => prev.map(
|
|
2063
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: finalContent }) : m
|
|
2064
|
-
)
|
|
2065
|
-
);
|
|
2515
|
+
setMessages((prev) => prev.map((m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: finalContent }) : m));
|
|
2066
2516
|
setIsStreaming(false);
|
|
2067
2517
|
setActiveField(null);
|
|
2068
2518
|
toast2.success("Article created successfully!");
|
|
2069
2519
|
},
|
|
2070
|
-
onError:
|
|
2071
|
-
console.error("Streaming error:", error);
|
|
2520
|
+
onError: (error) => {
|
|
2072
2521
|
if (!hasStartedStreaming) {
|
|
2073
|
-
|
|
2522
|
+
pendingError = error instanceof Error ? error : new Error(String(error));
|
|
2074
2523
|
} else {
|
|
2524
|
+
streamDone = true;
|
|
2075
2525
|
setIsStreaming(false);
|
|
2076
2526
|
setActiveField(null);
|
|
2077
2527
|
toast2.error("Failed to complete article generation");
|
|
2078
|
-
setMessages(
|
|
2079
|
-
(
|
|
2080
|
-
|
|
2081
|
-
)
|
|
2082
|
-
);
|
|
2528
|
+
setMessages((prev) => prev.map(
|
|
2529
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: titleBuffer || articleBuffer ? buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer) : "Failed to create article. Please try again." }) : m
|
|
2530
|
+
));
|
|
2083
2531
|
}
|
|
2084
2532
|
}
|
|
2085
2533
|
});
|
|
2086
|
-
if (
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2092
|
-
)
|
|
2093
|
-
);
|
|
2094
|
-
}
|
|
2534
|
+
if (pendingError) throw pendingError;
|
|
2535
|
+
if (!streamDone && (titleBuffer || articleBuffer)) {
|
|
2536
|
+
setMessages((prev) => prev.map(
|
|
2537
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer) }) : m
|
|
2538
|
+
));
|
|
2095
2539
|
setIsStreaming(false);
|
|
2096
2540
|
setActiveField(null);
|
|
2097
2541
|
}
|
|
2098
|
-
} catch (
|
|
2099
|
-
|
|
2100
|
-
setMessages(
|
|
2101
|
-
(prev) => prev.map(
|
|
2102
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "" }) : m
|
|
2103
|
-
)
|
|
2104
|
-
);
|
|
2542
|
+
} catch (e) {
|
|
2543
|
+
setMessages((prev) => prev.map((m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "" }) : m));
|
|
2105
2544
|
const result = await rewriteNewsApi({
|
|
2106
2545
|
article: content || "",
|
|
2107
|
-
language:
|
|
2108
|
-
articleId: id
|
|
2109
|
-
tone: contentPrefs == null ? void 0 : contentPrefs.tone,
|
|
2110
|
-
style: contentPrefs == null ? void 0 : contentPrefs.style,
|
|
2111
|
-
wordCount: contentPrefs == null ? void 0 : contentPrefs.wordCount,
|
|
2112
|
-
includeQuotes: contentPrefs == null ? void 0 : contentPrefs.includeQuotes,
|
|
2113
|
-
includeFAQ: contentPrefs == null ? void 0 : contentPrefs.includeFAQ,
|
|
2114
|
-
targetAudience: contentPrefs == null ? void 0 : contentPrefs.targetAudience
|
|
2546
|
+
language: "English",
|
|
2547
|
+
articleId: id
|
|
2115
2548
|
});
|
|
2116
|
-
setMessages(
|
|
2117
|
-
(
|
|
2118
|
-
|
|
2119
|
-
)
|
|
2120
|
-
);
|
|
2549
|
+
setMessages((prev) => prev.map(
|
|
2550
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: typeof result === "string" ? result : JSON.stringify(result) }) : m
|
|
2551
|
+
));
|
|
2121
2552
|
setIsStreaming(false);
|
|
2122
2553
|
toast2.success("Article created successfully!");
|
|
2123
2554
|
}
|
|
2124
2555
|
} catch (err) {
|
|
2556
|
+
if (err instanceof ApiKeyInvalidError) return;
|
|
2125
2557
|
console.error("Complete Error:", err);
|
|
2126
2558
|
setIsStreaming(false);
|
|
2127
2559
|
setActiveField(null);
|
|
2128
2560
|
toast2.error((err == null ? void 0 : err.message) || "An error occurred while creating the article");
|
|
2129
|
-
setMessages(
|
|
2130
|
-
(
|
|
2131
|
-
|
|
2132
|
-
)
|
|
2133
|
-
);
|
|
2561
|
+
setMessages((prev) => prev.map(
|
|
2562
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "Failed to create article. Please try again." }) : m
|
|
2563
|
+
));
|
|
2134
2564
|
}
|
|
2135
2565
|
};
|
|
2136
2566
|
const handleSendMessage = async (text) => {
|
|
2137
|
-
var _a
|
|
2567
|
+
var _a;
|
|
2138
2568
|
const userMsgId = crypto.randomUUID();
|
|
2139
2569
|
const assistantId = crypto.randomUUID();
|
|
2140
|
-
setMessages((prev) => [
|
|
2141
|
-
...prev,
|
|
2142
|
-
{ id: userMsgId, role: "user", content: text }
|
|
2143
|
-
]);
|
|
2570
|
+
setMessages((prev) => [...prev, { id: userMsgId, role: "user", content: text }]);
|
|
2144
2571
|
const urlRegex = /https?:\/\/[^\s]+/;
|
|
2145
2572
|
const hasUrl = urlRegex.test(text);
|
|
2146
2573
|
if (hasUrl) {
|
|
2147
|
-
setMessages((prev) => [
|
|
2148
|
-
...prev,
|
|
2149
|
-
{ id: assistantId, role: "assistant", content: "Analyzing your link..." }
|
|
2150
|
-
]);
|
|
2574
|
+
setMessages((prev) => [...prev, { id: assistantId, role: "assistant", content: "Analyzing your link..." }]);
|
|
2151
2575
|
try {
|
|
2152
|
-
return;
|
|
2153
2576
|
const result = await analyzeInputApi(text);
|
|
2154
2577
|
if (result.hasUrl && ((_a = result.options) == null ? void 0 : _a.length) > 0) {
|
|
2155
2578
|
setAnalyzedData({
|
|
@@ -2159,60 +2582,39 @@ function ChatBot({ onPost }) {
|
|
|
2159
2582
|
messageId: assistantId
|
|
2160
2583
|
});
|
|
2161
2584
|
const optionsList = result.options.map((opt) => `\u2022 **${opt.name}**${opt.description ? ` \u2013 ${opt.description}` : ""}`).join("\n");
|
|
2162
|
-
setMessages(
|
|
2163
|
-
(
|
|
2164
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), {
|
|
2165
|
-
content: `I found an article (${result.wordCount || 0} words). What would you like to do?
|
|
2585
|
+
setMessages((prev) => prev.map(
|
|
2586
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: `I found an article (${result.wordCount || 0} words). What would you like to do?
|
|
2166
2587
|
|
|
2167
|
-
${optionsList}`
|
|
2168
|
-
|
|
2169
|
-
)
|
|
2170
|
-
);
|
|
2588
|
+
${optionsList}` }) : m
|
|
2589
|
+
));
|
|
2171
2590
|
} else {
|
|
2172
|
-
setMessages(
|
|
2173
|
-
(
|
|
2174
|
-
|
|
2175
|
-
)
|
|
2176
|
-
);
|
|
2591
|
+
setMessages((prev) => prev.map(
|
|
2592
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "Could not extract content from that URL. Please try a different link." }) : m
|
|
2593
|
+
));
|
|
2177
2594
|
}
|
|
2178
2595
|
} catch (err) {
|
|
2596
|
+
if (err instanceof ApiKeyInvalidError) return;
|
|
2179
2597
|
console.error("Analyze input error:", err);
|
|
2180
2598
|
toast2.error("Failed to analyze the link");
|
|
2181
|
-
setMessages(
|
|
2182
|
-
(
|
|
2183
|
-
|
|
2184
|
-
)
|
|
2185
|
-
);
|
|
2599
|
+
setMessages((prev) => prev.map(
|
|
2600
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "Failed to analyze the link. Please try again." }) : m
|
|
2601
|
+
));
|
|
2186
2602
|
}
|
|
2187
2603
|
} else {
|
|
2188
|
-
setMessages((prev) => [
|
|
2189
|
-
...prev,
|
|
2190
|
-
{ id: assistantId, role: "assistant", content: "" }
|
|
2191
|
-
]);
|
|
2604
|
+
setMessages((prev) => [...prev, { id: assistantId, role: "assistant", content: "" }]);
|
|
2192
2605
|
setIsStreaming(true);
|
|
2193
2606
|
try {
|
|
2194
|
-
|
|
2195
|
-
const lang = ((_b = preferences == null ? void 0 : preferences.localization) == null ? void 0 : _b.language) === "hi" ? "Hindi" : "English";
|
|
2607
|
+
let streamDone = false;
|
|
2196
2608
|
let titleBuffer = "";
|
|
2197
2609
|
let articleBuffer = "";
|
|
2198
2610
|
let keywordsBuffer = [];
|
|
2199
2611
|
const updateMessage = () => {
|
|
2200
2612
|
const structured = buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2201
|
-
setMessages(
|
|
2202
|
-
(prev) => prev.map(
|
|
2203
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2204
|
-
)
|
|
2205
|
-
);
|
|
2613
|
+
setMessages((prev) => prev.map((m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m));
|
|
2206
2614
|
};
|
|
2207
2615
|
await rewriteNewsStreamApi({
|
|
2208
2616
|
article: text,
|
|
2209
|
-
language:
|
|
2210
|
-
tone: contentPrefs == null ? void 0 : contentPrefs.tone,
|
|
2211
|
-
style: contentPrefs == null ? void 0 : contentPrefs.style,
|
|
2212
|
-
wordCount: contentPrefs == null ? void 0 : contentPrefs.wordCount,
|
|
2213
|
-
includeQuotes: contentPrefs == null ? void 0 : contentPrefs.includeQuotes,
|
|
2214
|
-
includeFAQ: contentPrefs == null ? void 0 : contentPrefs.includeFAQ,
|
|
2215
|
-
targetAudience: contentPrefs == null ? void 0 : contentPrefs.targetAudience,
|
|
2617
|
+
language: "English",
|
|
2216
2618
|
onFieldStart: (field) => {
|
|
2217
2619
|
setActiveField(field);
|
|
2218
2620
|
},
|
|
@@ -2229,44 +2631,37 @@ ${optionsList}`
|
|
|
2229
2631
|
setActiveField(null);
|
|
2230
2632
|
},
|
|
2231
2633
|
onComplete: (data) => {
|
|
2634
|
+
streamDone = true;
|
|
2232
2635
|
const finalContent = data && (data.title || data.article) ? JSON.stringify(data) : buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2233
|
-
setMessages(
|
|
2234
|
-
(prev) => prev.map(
|
|
2235
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: finalContent }) : m
|
|
2236
|
-
)
|
|
2237
|
-
);
|
|
2636
|
+
setMessages((prev) => prev.map((m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: finalContent }) : m));
|
|
2238
2637
|
setIsStreaming(false);
|
|
2239
2638
|
setActiveField(null);
|
|
2240
2639
|
toast2.success("Content generated!");
|
|
2241
2640
|
},
|
|
2242
2641
|
onError: (error) => {
|
|
2642
|
+
if (error instanceof ApiKeyInvalidError) return;
|
|
2243
2643
|
console.error("Stream error:", error);
|
|
2644
|
+
streamDone = true;
|
|
2244
2645
|
setIsStreaming(false);
|
|
2245
2646
|
setActiveField(null);
|
|
2246
2647
|
toast2.error("Failed to generate content");
|
|
2247
2648
|
}
|
|
2248
2649
|
});
|
|
2249
|
-
if (
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
(prev) => prev.map(
|
|
2254
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2255
|
-
)
|
|
2256
|
-
);
|
|
2257
|
-
}
|
|
2650
|
+
if (!streamDone && (titleBuffer || articleBuffer)) {
|
|
2651
|
+
setMessages((prev) => prev.map(
|
|
2652
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer) }) : m
|
|
2653
|
+
));
|
|
2258
2654
|
setIsStreaming(false);
|
|
2259
2655
|
setActiveField(null);
|
|
2260
2656
|
}
|
|
2261
2657
|
} catch (err) {
|
|
2658
|
+
if (err instanceof ApiKeyInvalidError) return;
|
|
2262
2659
|
console.error("Send message error:", err);
|
|
2263
2660
|
setIsStreaming(false);
|
|
2264
2661
|
setActiveField(null);
|
|
2265
|
-
setMessages(
|
|
2266
|
-
(
|
|
2267
|
-
|
|
2268
|
-
)
|
|
2269
|
-
);
|
|
2662
|
+
setMessages((prev) => prev.map(
|
|
2663
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "Failed to generate content. Please try again." }) : m
|
|
2664
|
+
));
|
|
2270
2665
|
}
|
|
2271
2666
|
}
|
|
2272
2667
|
};
|
|
@@ -2282,28 +2677,20 @@ ${optionsList}`
|
|
|
2282
2677
|
]);
|
|
2283
2678
|
setIsStreaming(true);
|
|
2284
2679
|
try {
|
|
2285
|
-
|
|
2680
|
+
let streamDone = false;
|
|
2286
2681
|
let titleBuffer = "";
|
|
2287
2682
|
let articleBuffer = "";
|
|
2288
2683
|
let keywordsBuffer = [];
|
|
2289
2684
|
const updateMessage = () => {
|
|
2290
2685
|
const structured = buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2291
|
-
setMessages(
|
|
2292
|
-
(prev) => prev.map(
|
|
2293
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2294
|
-
)
|
|
2295
|
-
);
|
|
2686
|
+
setMessages((prev) => prev.map((m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m));
|
|
2296
2687
|
};
|
|
2297
2688
|
try {
|
|
2298
2689
|
await createContentStreamApi({
|
|
2299
2690
|
url,
|
|
2300
2691
|
content,
|
|
2301
2692
|
actionId,
|
|
2302
|
-
settings: {
|
|
2303
|
-
tone: contentPrefs == null ? void 0 : contentPrefs.tone,
|
|
2304
|
-
style: contentPrefs == null ? void 0 : contentPrefs.style,
|
|
2305
|
-
wordCount: contentPrefs == null ? void 0 : contentPrefs.wordCount
|
|
2306
|
-
},
|
|
2693
|
+
settings: {},
|
|
2307
2694
|
onFieldStart: (field) => {
|
|
2308
2695
|
setActiveField(field);
|
|
2309
2696
|
},
|
|
@@ -2320,71 +2707,146 @@ ${optionsList}`
|
|
|
2320
2707
|
setActiveField(null);
|
|
2321
2708
|
},
|
|
2322
2709
|
onComplete: (data) => {
|
|
2710
|
+
streamDone = true;
|
|
2323
2711
|
const finalContent = data && (data.title || data.article) ? JSON.stringify(data) : buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2324
|
-
setMessages(
|
|
2325
|
-
(prev) => prev.map(
|
|
2326
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: finalContent }) : m
|
|
2327
|
-
)
|
|
2328
|
-
);
|
|
2712
|
+
setMessages((prev) => prev.map((m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: finalContent }) : m));
|
|
2329
2713
|
setIsStreaming(false);
|
|
2330
2714
|
setActiveField(null);
|
|
2331
2715
|
toast2.success("Content created!");
|
|
2332
2716
|
},
|
|
2333
2717
|
onError: (error) => {
|
|
2718
|
+
if (error instanceof ApiKeyInvalidError) return;
|
|
2334
2719
|
console.error("Stream error:", error);
|
|
2720
|
+
streamDone = true;
|
|
2335
2721
|
setIsStreaming(false);
|
|
2336
2722
|
setActiveField(null);
|
|
2337
2723
|
toast2.error("Failed to create content");
|
|
2338
2724
|
}
|
|
2339
2725
|
});
|
|
2340
|
-
if (
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
(prev) => prev.map(
|
|
2345
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: structured }) : m
|
|
2346
|
-
)
|
|
2347
|
-
);
|
|
2348
|
-
}
|
|
2726
|
+
if (!streamDone && (titleBuffer || articleBuffer)) {
|
|
2727
|
+
setMessages((prev) => prev.map(
|
|
2728
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer) }) : m
|
|
2729
|
+
));
|
|
2349
2730
|
setIsStreaming(false);
|
|
2350
2731
|
setActiveField(null);
|
|
2351
2732
|
}
|
|
2352
2733
|
} catch (e) {
|
|
2353
|
-
const result = await createContentApi({ url, content, actionId, settings: {
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
} });
|
|
2358
|
-
setMessages(
|
|
2359
|
-
(prev) => prev.map(
|
|
2360
|
-
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: typeof result === "string" ? result : JSON.stringify(result) }) : m
|
|
2361
|
-
)
|
|
2362
|
-
);
|
|
2734
|
+
const result = await createContentApi({ url, content, actionId, settings: {} });
|
|
2735
|
+
setMessages((prev) => prev.map(
|
|
2736
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: typeof result === "string" ? result : JSON.stringify(result) }) : m
|
|
2737
|
+
));
|
|
2363
2738
|
setIsStreaming(false);
|
|
2364
2739
|
setActiveField(null);
|
|
2365
2740
|
toast2.success("Content created!");
|
|
2366
2741
|
}
|
|
2367
2742
|
} catch (err) {
|
|
2743
|
+
if (err instanceof ApiKeyInvalidError) return;
|
|
2368
2744
|
console.error("Create content error:", err);
|
|
2369
2745
|
setIsStreaming(false);
|
|
2370
2746
|
setActiveField(null);
|
|
2371
|
-
setMessages(
|
|
2372
|
-
(
|
|
2373
|
-
|
|
2374
|
-
|
|
2747
|
+
setMessages((prev) => prev.map(
|
|
2748
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "Failed to create content. Please try again." }) : m
|
|
2749
|
+
));
|
|
2750
|
+
}
|
|
2751
|
+
};
|
|
2752
|
+
const handleResolveSeo = async (articleData) => {
|
|
2753
|
+
const assistantId = crypto.randomUUID();
|
|
2754
|
+
setMessages((prev) => [
|
|
2755
|
+
...prev,
|
|
2756
|
+
{ id: crypto.randomUUID(), role: "user", content: "Resolve SEO issues" },
|
|
2757
|
+
{ id: assistantId, role: "assistant", content: "" }
|
|
2758
|
+
]);
|
|
2759
|
+
setIsStreaming(true);
|
|
2760
|
+
try {
|
|
2761
|
+
let streamDone = false;
|
|
2762
|
+
let titleBuffer = "";
|
|
2763
|
+
let articleBuffer = "";
|
|
2764
|
+
let keywordsBuffer = [];
|
|
2765
|
+
const updateMessage = () => {
|
|
2766
|
+
setMessages((prev) => prev.map(
|
|
2767
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer) }) : m
|
|
2768
|
+
));
|
|
2769
|
+
};
|
|
2770
|
+
await resolveSeoStreamApi(__spreadProps(__spreadValues({}, articleData), {
|
|
2771
|
+
onFieldStart: (field) => {
|
|
2772
|
+
setActiveField(field);
|
|
2773
|
+
},
|
|
2774
|
+
onContent: (field, chunk) => {
|
|
2775
|
+
if (field === "title") titleBuffer += chunk;
|
|
2776
|
+
else articleBuffer += chunk;
|
|
2777
|
+
updateMessage();
|
|
2778
|
+
},
|
|
2779
|
+
onKeywords: (keywords) => {
|
|
2780
|
+
keywordsBuffer = keywords;
|
|
2781
|
+
updateMessage();
|
|
2782
|
+
},
|
|
2783
|
+
onFieldEnd: () => {
|
|
2784
|
+
setActiveField(null);
|
|
2785
|
+
},
|
|
2786
|
+
onComplete: (data) => {
|
|
2787
|
+
streamDone = true;
|
|
2788
|
+
const finalContent = data && (data.title || data.article) ? JSON.stringify(data) : buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer);
|
|
2789
|
+
setMessages((prev) => prev.map((m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: finalContent }) : m));
|
|
2790
|
+
setIsStreaming(false);
|
|
2791
|
+
setActiveField(null);
|
|
2792
|
+
toast2.success("SEO issues resolved!");
|
|
2793
|
+
},
|
|
2794
|
+
onError: () => {
|
|
2795
|
+
streamDone = true;
|
|
2796
|
+
setIsStreaming(false);
|
|
2797
|
+
setActiveField(null);
|
|
2798
|
+
toast2.error("Failed to resolve SEO issues");
|
|
2799
|
+
}
|
|
2800
|
+
}));
|
|
2801
|
+
if (!streamDone && (titleBuffer || articleBuffer)) {
|
|
2802
|
+
setMessages((prev) => prev.map(
|
|
2803
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: buildStructuredContent(titleBuffer, articleBuffer, keywordsBuffer) }) : m
|
|
2804
|
+
));
|
|
2805
|
+
setIsStreaming(false);
|
|
2806
|
+
setActiveField(null);
|
|
2807
|
+
}
|
|
2808
|
+
} catch (err) {
|
|
2809
|
+
if (err instanceof ApiKeyInvalidError) return;
|
|
2810
|
+
console.error("Resolve SEO error:", err);
|
|
2811
|
+
setIsStreaming(false);
|
|
2812
|
+
setActiveField(null);
|
|
2813
|
+
toast2.error((err == null ? void 0 : err.message) || "Failed to resolve SEO issues");
|
|
2814
|
+
setMessages((prev) => prev.map(
|
|
2815
|
+
(m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "Failed to resolve SEO issues. Please try again." }) : m
|
|
2816
|
+
));
|
|
2817
|
+
}
|
|
2818
|
+
};
|
|
2819
|
+
const handleHistorySelect = async (id) => {
|
|
2820
|
+
try {
|
|
2821
|
+
const item = await getHistoryItem(id);
|
|
2822
|
+
const content = buildStructuredContent(
|
|
2823
|
+
item.title,
|
|
2824
|
+
item.article || "",
|
|
2825
|
+
item.metaKeywords || [],
|
|
2826
|
+
item.subtitle,
|
|
2827
|
+
item.metaDescription
|
|
2375
2828
|
);
|
|
2829
|
+
setMessages((prev) => [...prev, { id: crypto.randomUUID(), role: "assistant", content }]);
|
|
2830
|
+
} catch (e) {
|
|
2831
|
+
toast2.error("Failed to load article");
|
|
2376
2832
|
}
|
|
2377
2833
|
};
|
|
2378
2834
|
if (loading) {
|
|
2379
|
-
return /* @__PURE__ */
|
|
2380
|
-
/* @__PURE__ */
|
|
2381
|
-
/* @__PURE__ */
|
|
2835
|
+
return /* @__PURE__ */ jsx8("div", { className: "cnfy-loading", children: /* @__PURE__ */ jsxs8("div", { className: "cnfy-loading-inner", children: [
|
|
2836
|
+
/* @__PURE__ */ jsx8(Loader24, { className: "cnfy-loading-spinner cnfy-animate-spin" }),
|
|
2837
|
+
/* @__PURE__ */ jsx8("p", { className: "cnfy-loading-text", children: "Loading..." })
|
|
2382
2838
|
] }) });
|
|
2383
2839
|
}
|
|
2384
2840
|
return /* @__PURE__ */ jsxs8("div", { className: "cnfy-root", children: [
|
|
2385
|
-
/* @__PURE__ */
|
|
2386
|
-
|
|
2387
|
-
|
|
2841
|
+
/* @__PURE__ */ jsx8("div", { className: "cnfy-main", children: /* @__PURE__ */ jsx8("section", { className: "cnfy-chat-section cnfy-chat-section--full", children: /* @__PURE__ */ jsxs8("div", { className: "cnfy-chat-inner cnfy-chat-inner--with-history", children: [
|
|
2842
|
+
/* @__PURE__ */ jsx8(
|
|
2843
|
+
HistoryPanel,
|
|
2844
|
+
{
|
|
2845
|
+
onSelect: handleHistorySelect,
|
|
2846
|
+
onNewChat: () => setMessages([])
|
|
2847
|
+
}
|
|
2848
|
+
),
|
|
2849
|
+
/* @__PURE__ */ jsx8(
|
|
2388
2850
|
ChatWindow,
|
|
2389
2851
|
{
|
|
2390
2852
|
messages,
|
|
@@ -2394,33 +2856,39 @@ ${optionsList}`
|
|
|
2394
2856
|
activeField,
|
|
2395
2857
|
analyzedData,
|
|
2396
2858
|
onSelectAction: handleSelectAction,
|
|
2397
|
-
|
|
2859
|
+
onResolveSeo: handleResolveSeo
|
|
2398
2860
|
}
|
|
2399
|
-
)
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
/* @__PURE__ */ jsx11("p", { className: "cnfy-empty-state-subtitle", children: "Type a message or paste a link to begin" })
|
|
2403
|
-
] }) })
|
|
2404
|
-
] }) }),
|
|
2405
|
-
/* @__PURE__ */ jsx11(
|
|
2861
|
+
)
|
|
2862
|
+
] }) }) }),
|
|
2863
|
+
/* @__PURE__ */ jsx8(
|
|
2406
2864
|
Drawer,
|
|
2407
2865
|
{
|
|
2408
2866
|
open: preferencesOpen,
|
|
2409
2867
|
onClose: () => setPreferencesOpen(false),
|
|
2410
2868
|
title: "Settings",
|
|
2411
|
-
children: /* @__PURE__ */
|
|
2869
|
+
children: /* @__PURE__ */ jsx8(PreferencesPage, {})
|
|
2412
2870
|
}
|
|
2413
2871
|
)
|
|
2414
2872
|
] });
|
|
2415
2873
|
}
|
|
2416
2874
|
|
|
2417
2875
|
// src/index.tsx
|
|
2418
|
-
import { jsx as
|
|
2876
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
2419
2877
|
function ContenifyChatBot({ apiUrl, apiKey, domain, onPost }) {
|
|
2420
|
-
|
|
2878
|
+
useEffect7(() => {
|
|
2421
2879
|
setConfig({ apiUrl, apiKey, domain });
|
|
2422
2880
|
}, [apiUrl, apiKey, domain]);
|
|
2423
|
-
|
|
2881
|
+
useEffect7(() => {
|
|
2882
|
+
if (!onPost) return;
|
|
2883
|
+
const handler = (e) => {
|
|
2884
|
+
var _a, _b;
|
|
2885
|
+
const detail = e.detail;
|
|
2886
|
+
onPost((_a = detail.article) != null ? _a : "", (_b = detail.keywords) != null ? _b : []);
|
|
2887
|
+
};
|
|
2888
|
+
window.addEventListener("contenify-post-article", handler);
|
|
2889
|
+
return () => window.removeEventListener("contenify-post-article", handler);
|
|
2890
|
+
}, [onPost]);
|
|
2891
|
+
return /* @__PURE__ */ jsx9(ChatBot, {});
|
|
2424
2892
|
}
|
|
2425
2893
|
var index_default = ContenifyChatBot;
|
|
2426
2894
|
export {
|