diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 07ff2badb7..6c8a64234c 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -63,10 +63,10 @@ const GeneralBrowserExtension = lazy( () => import("@/pages/GeneralSettings/BrowserExtensionApiKey") ); const WorkspaceSettings = lazy(() => import("@/pages/WorkspaceSettings")); -const EmbedConfigSetup = lazy( - () => import("@/pages/GeneralSettings/EmbedConfigs") + +const ChatEmbedWidgets = lazy( + () => import("@/pages/GeneralSettings/ChatEmbedWidgets") ); -const EmbedChats = lazy(() => import("@/pages/GeneralSettings/EmbedChats")); const PrivacyAndData = lazy( () => import("@/pages/GeneralSettings/PrivacyAndData") ); @@ -178,12 +178,8 @@ export default function App() { element={} /> } - /> - } + path="/settings/embed-chat-widgets" + element={} /> {/* Manager */} ( childOptions={[ { hidden: !canViewChatHistory, - btnText: t("settings.embed-chats"), - href: paths.settings.embedChats(), - flex: true, - roles: ["admin"], - }, - { btnText: t("settings.embeds"), - href: paths.settings.embedSetup(), + href: paths.settings.embedChatWidgets(), flex: true, roles: ["admin"], }, diff --git a/frontend/src/index.css b/frontend/src/index.css index 7c9c547dce..b8109f4113 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -94,6 +94,14 @@ --theme-attachment-icon: #ffffff; --theme-attachment-icon-spinner: #ffffff; --theme-attachment-icon-spinner-bg: #27282a; + + --theme-button-text: #a8a9ab; + --theme-button-code-hover-text: #7cd4fd; + --theme-button-code-hover-bg: #22343f; + --theme-button-disable-hover-text: #fec84b; + --theme-button-disable-hover-bg: #3a3128; + --theme-button-delete-hover-text: #f97066; + --theme-button-delete-hover-bg: #37282b; } [data-theme="light"] { @@ -187,6 +195,14 @@ --theme-attachment-icon: #ffffff; --theme-attachment-icon-spinner: #7cd4fd; --theme-attachment-icon-spinner-bg: #ffffff; + + --theme-button-text: #a8a9ab; + --theme-button-code-hover-text: #0ba5ec; + --theme-button-code-hover-bg: #e8f7fe; + --theme-button-disable-hover-text: #854708; + --theme-button-disable-hover-bg: #fef7e6; + --theme-button-delete-hover-text: #b42318; + --theme-button-delete-hover-bg: #fee4e2; } [data-theme="light"] .text-white { diff --git a/frontend/src/locales/ar/common.js b/frontend/src/locales/ar/common.js index 702cad3b7d..315d81bc29 100644 --- a/frontend/src/locales/ar/common.js +++ b/frontend/src/locales/ar/common.js @@ -444,7 +444,8 @@ const TRANSLATIONS = { table: { workspace: "مساحة العمل", chats: "المحادثات المرسلة", - Active: "المجالات النشطة", + active: "المجالات النشطة", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/da/common.js b/frontend/src/locales/da/common.js index 888ae4156a..30fbf86552 100644 --- a/frontend/src/locales/da/common.js +++ b/frontend/src/locales/da/common.js @@ -446,7 +446,8 @@ const TRANSLATIONS = { table: { workspace: "Arbejdsområde", chats: "Sendte chats", - Active: "Aktive domæner", + active: "Aktive domæner", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/de/common.js b/frontend/src/locales/de/common.js index 34a9000b79..23435faff0 100644 --- a/frontend/src/locales/de/common.js +++ b/frontend/src/locales/de/common.js @@ -440,7 +440,8 @@ const TRANSLATIONS = { table: { workspace: "Arbeitsbereich", chats: "Gesendete Chats", - Active: "Aktive Domains", + active: "Aktive Domains", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/en/common.js b/frontend/src/locales/en/common.js index 2a9bb4d47b..422ab91520 100644 --- a/frontend/src/locales/en/common.js +++ b/frontend/src/locales/en/common.js @@ -663,12 +663,13 @@ const TRANSLATIONS = { table: { workspace: "Workspace", chats: "Sent Chats", - Active: "Active Domains", + active: "Active Domains", + created: "Created", }, }, "embed-chats": { - title: "Embed Chats", + title: "Embed Chat History", export: "Export", description: "These are all the recorded chats and messages from any embed that you have published.", diff --git a/frontend/src/locales/es/common.js b/frontend/src/locales/es/common.js index 02c8c898f1..21e1afb0e8 100644 --- a/frontend/src/locales/es/common.js +++ b/frontend/src/locales/es/common.js @@ -443,7 +443,8 @@ const TRANSLATIONS = { table: { workspace: "Espacio de trabajo", chats: "Chats enviados", - Active: "Dominios activos", + active: "Dominios activos", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/fa/common.js b/frontend/src/locales/fa/common.js index c4406723e0..401da20dd0 100644 --- a/frontend/src/locales/fa/common.js +++ b/frontend/src/locales/fa/common.js @@ -436,7 +436,8 @@ const TRANSLATIONS = { table: { workspace: "فضای کاری", chats: "گفتگوهای ارسال شده", - Active: "دامنه‌های فعال", + active: "دامنه‌های فعال", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/fr/common.js b/frontend/src/locales/fr/common.js index 0ec4769562..1a1af610c9 100644 --- a/frontend/src/locales/fr/common.js +++ b/frontend/src/locales/fr/common.js @@ -444,7 +444,8 @@ const TRANSLATIONS = { table: { workspace: "Espace de travail", chats: "Chats envoyés", - Active: "Domaines actifs", + active: "Domaines actifs", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/he/common.js b/frontend/src/locales/he/common.js index af74793651..0fda5628f3 100644 --- a/frontend/src/locales/he/common.js +++ b/frontend/src/locales/he/common.js @@ -431,7 +431,8 @@ const TRANSLATIONS = { table: { workspace: "סביבת עבודה", chats: "שיחות שנשלחו", - Active: "תחומים פעילים", + active: "תחומים פעילים", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/it/common.js b/frontend/src/locales/it/common.js index 9de47c9f01..f59be7f804 100644 --- a/frontend/src/locales/it/common.js +++ b/frontend/src/locales/it/common.js @@ -442,7 +442,8 @@ const TRANSLATIONS = { table: { workspace: "Area di lavoro", chats: "Chat inviate", - Active: "Domini attivi", + active: "Domini attivi", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/ja/common.js b/frontend/src/locales/ja/common.js index 767f3132f9..c8c2df458e 100644 --- a/frontend/src/locales/ja/common.js +++ b/frontend/src/locales/ja/common.js @@ -442,7 +442,8 @@ const TRANSLATIONS = { table: { workspace: "ワークスペース", chats: "送信済みチャット", - Active: "有効なドメイン", + active: "有効なドメイン", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/ko/common.js b/frontend/src/locales/ko/common.js index 0393e277b3..ab85f55716 100644 --- a/frontend/src/locales/ko/common.js +++ b/frontend/src/locales/ko/common.js @@ -430,7 +430,8 @@ const TRANSLATIONS = { table: { workspace: "워크스페이스", chats: "보낸 채팅", - Active: "활성 도메인", + active: "활성 도메인", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/lv/common.js b/frontend/src/locales/lv/common.js index 32f2f0ee4d..bca0cb8654 100644 --- a/frontend/src/locales/lv/common.js +++ b/frontend/src/locales/lv/common.js @@ -630,7 +630,8 @@ const TRANSLATIONS = { table: { workspace: "Darba vieta", chats: "Nosūtītie čati", - Active: "Aktīvie domēni", + active: "Aktīvie domēni", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/nl/common.js b/frontend/src/locales/nl/common.js index 48d233ca81..b4c9625fa0 100644 --- a/frontend/src/locales/nl/common.js +++ b/frontend/src/locales/nl/common.js @@ -439,7 +439,8 @@ const TRANSLATIONS = { table: { workspace: "Werkruimte", chats: "Verzonden Chats", - Active: "Actieve Domeinen", + active: "Actieve Domeinen", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/pt_BR/common.js b/frontend/src/locales/pt_BR/common.js index 4ddab4cb9e..d2ad4f0ba9 100644 --- a/frontend/src/locales/pt_BR/common.js +++ b/frontend/src/locales/pt_BR/common.js @@ -615,7 +615,8 @@ const TRANSLATIONS = { table: { workspace: "Workspace", chats: "Chats Enviados", - Active: "Domínios Ativos", + active: "Domínios Ativos", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/ru/common.js b/frontend/src/locales/ru/common.js index ad399934f8..84e247abbc 100644 --- a/frontend/src/locales/ru/common.js +++ b/frontend/src/locales/ru/common.js @@ -448,7 +448,8 @@ const TRANSLATIONS = { table: { workspace: "Рабочее пространство", chats: "Отправленные чаты", - Active: "Активные домены", + active: "Активные домены", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/tr/common.js b/frontend/src/locales/tr/common.js index bdade51f8c..784aa82916 100644 --- a/frontend/src/locales/tr/common.js +++ b/frontend/src/locales/tr/common.js @@ -439,7 +439,8 @@ const TRANSLATIONS = { table: { workspace: "Çalışma Alanı", chats: "Gönderilen Sohbetler", - Active: "Aktif Alan Adları", + active: "Aktif Alan Adları", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/vn/common.js b/frontend/src/locales/vn/common.js index 4916321398..ed01dd8f3b 100644 --- a/frontend/src/locales/vn/common.js +++ b/frontend/src/locales/vn/common.js @@ -438,7 +438,8 @@ const TRANSLATIONS = { table: { workspace: "Workspace", chats: "Sent Chats", - Active: "Active Domains", + active: "Active Domains", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/zh/common.js b/frontend/src/locales/zh/common.js index 52696e8313..9bdf04f32d 100644 --- a/frontend/src/locales/zh/common.js +++ b/frontend/src/locales/zh/common.js @@ -590,7 +590,8 @@ const TRANSLATIONS = { table: { workspace: "工作区", chats: "已发送聊天", - Active: "活动域", + active: "活动域", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/locales/zh_TW/common.js b/frontend/src/locales/zh_TW/common.js index dc60bc0070..721f33697f 100644 --- a/frontend/src/locales/zh_TW/common.js +++ b/frontend/src/locales/zh_TW/common.js @@ -423,7 +423,8 @@ const TRANSLATIONS = { table: { workspace: "工作區", chats: "已傳送對話", - Active: "已啟用網域", + active: "已啟用網域", + created: null, }, }, "embed-chats": { diff --git a/frontend/src/pages/GeneralSettings/EmbedChats/ChatRow/index.jsx b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedChats/ChatRow/index.jsx similarity index 87% rename from frontend/src/pages/GeneralSettings/EmbedChats/ChatRow/index.jsx rename to frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedChats/ChatRow/index.jsx index 4b25eb6db2..115b09a9e7 100644 --- a/frontend/src/pages/GeneralSettings/EmbedChats/ChatRow/index.jsx +++ b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedChats/ChatRow/index.jsx @@ -38,18 +38,17 @@ export default function ChatRow({ chat, onDelete }) { - {" "} {chat.embed_config.workspace.name}

{truncate(chat.session_id, 20)}

@@ -57,13 +56,13 @@ export default function ChatRow({ chat, onDelete }) { {truncate(chat.prompt, 40)} {truncate(JSON.parse(chat.response)?.text, 40)} @@ -71,9 +70,11 @@ export default function ChatRow({ chat, onDelete }) { diff --git a/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedChats/index.jsx b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedChats/index.jsx new file mode 100644 index 0000000000..154094e297 --- /dev/null +++ b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedChats/index.jsx @@ -0,0 +1,232 @@ +import { useEffect, useState, useRef } from "react"; +import * as Skeleton from "react-loading-skeleton"; +import "react-loading-skeleton/dist/skeleton.css"; +import useQuery from "@/hooks/useQuery"; +import ChatRow from "./ChatRow"; +import Embed from "@/models/embed"; +import { useTranslation } from "react-i18next"; +import { CaretDown, Download } from "@phosphor-icons/react"; +import showToast from "@/utils/toast"; +import { saveAs } from "file-saver"; +import System from "@/models/system"; + +const exportOptions = { + csv: { + name: "CSV", + mimeType: "text/csv", + fileExtension: "csv", + filenameFunc: () => { + return `anythingllm-embed-chats-${new Date().toLocaleDateString()}`; + }, + }, + json: { + name: "JSON", + mimeType: "application/json", + fileExtension: "json", + filenameFunc: () => { + return `anythingllm-embed-chats-${new Date().toLocaleDateString()}`; + }, + }, + jsonl: { + name: "JSONL", + mimeType: "application/jsonl", + fileExtension: "jsonl", + filenameFunc: () => { + return `anythingllm-embed-chats-${new Date().toLocaleDateString()}-lines`; + }, + }, + jsonAlpaca: { + name: "JSON (Alpaca)", + mimeType: "application/json", + fileExtension: "json", + filenameFunc: () => { + return `anythingllm-embed-chats-${new Date().toLocaleDateString()}-alpaca`; + }, + }, +}; + +export default function EmbedChatsView() { + const [showMenu, setShowMenu] = useState(false); + const menuRef = useRef(); + const openMenuButton = useRef(); + const { t } = useTranslation(); + const [loading, setLoading] = useState(true); + const [chats, setChats] = useState([]); + const query = useQuery(); + const [offset, setOffset] = useState(Number(query.get("offset") || 0)); + const [canNext, setCanNext] = useState(false); + + const handleDumpChats = async (exportType) => { + const chats = await System.exportChats(exportType, "embed"); + if (!!chats) { + const { name, mimeType, fileExtension, filenameFunc } = + exportOptions[exportType]; + const blob = new Blob([chats], { type: mimeType }); + saveAs(blob, `${filenameFunc()}.${fileExtension}`); + showToast(`Embed chats exported successfully as ${name}.`, "success"); + } else { + showToast("Failed to export embed chats.", "error"); + } + }; + + const toggleMenu = () => { + setShowMenu(!showMenu); + }; + + useEffect(() => { + function handleClickOutside(event) { + if ( + menuRef.current && + !menuRef.current.contains(event.target) && + !openMenuButton.current.contains(event.target) + ) { + setShowMenu(false); + } + } + + document.addEventListener("mousedown", handleClickOutside); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, []); + + useEffect(() => { + async function fetchChats() { + const { chats: _chats, hasPages = false } = await Embed.chats(offset); + setChats(_chats); + setCanNext(hasPages); + setLoading(false); + } + fetchChats(); + }, [offset]); + + const handlePrevious = () => { + setOffset(Math.max(offset - 1, 0)); + }; + + const handleNext = () => { + setOffset(offset + 1); + }; + + const handleDeleteChat = (chatId) => { + setChats((prevChats) => prevChats.filter((chat) => chat.id !== chatId)); + }; + + if (loading) { + return ( + + ); + } + + return ( +
+
+
+

+ {t("embed-chats.title")} +

+
+ +
+
+ {Object.entries(exportOptions).map(([key, data]) => ( + + ))} +
+
+
+
+

+ {t("embed-chats.description")} +

+
+
+ + + + + + + + + + + + + {chats.map((chat) => ( + + ))} + +
+ {t("embed-chats.table.embed")} + + {t("embed-chats.table.sender")} + + {t("embed-chats.table.message")} + + {t("embed-chats.table.response")} + + {t("embed-chats.table.at")} + + {" "} +
+ {(offset > 0 || canNext) && ( +
+ + +
+ )} +
+
+ ); +} diff --git a/frontend/src/pages/GeneralSettings/EmbedConfigs/EmbedRow/CodeSnippetModal/index.jsx b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/EmbedRow/CodeSnippetModal/index.jsx similarity index 99% rename from frontend/src/pages/GeneralSettings/EmbedConfigs/EmbedRow/CodeSnippetModal/index.jsx rename to frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/EmbedRow/CodeSnippetModal/index.jsx index 76fda358c9..8ac4e9d0ac 100644 --- a/frontend/src/pages/GeneralSettings/EmbedConfigs/EmbedRow/CodeSnippetModal/index.jsx +++ b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/EmbedRow/CodeSnippetModal/index.jsx @@ -92,6 +92,7 @@ const ScriptTag = ({ embed }) => { View all style and configuration options → diff --git a/frontend/src/pages/GeneralSettings/EmbedConfigs/EmbedRow/EditEmbedModal/index.jsx b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/EmbedRow/EditEmbedModal/index.jsx similarity index 100% rename from frontend/src/pages/GeneralSettings/EmbedConfigs/EmbedRow/EditEmbedModal/index.jsx rename to frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/EmbedRow/EditEmbedModal/index.jsx diff --git a/frontend/src/pages/GeneralSettings/EmbedConfigs/EmbedRow/index.jsx b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/EmbedRow/index.jsx similarity index 72% rename from frontend/src/pages/GeneralSettings/EmbedConfigs/EmbedRow/index.jsx rename to frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/EmbedRow/index.jsx index 4579884e4b..10fa42db1a 100644 --- a/frontend/src/pages/GeneralSettings/EmbedConfigs/EmbedRow/index.jsx +++ b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/EmbedRow/index.jsx @@ -1,5 +1,5 @@ import { useRef, useState } from "react"; -import { DotsThreeOutline, LinkSimple, Trash } from "@phosphor-icons/react"; +import { DotsThreeOutline } from "@phosphor-icons/react"; import showToast from "@/utils/toast"; import { useModal } from "@/hooks/useModal"; import ModalWrapper from "@/components/ModalWrapper"; @@ -8,6 +8,7 @@ import paths from "@/utils/paths"; import { nFormatter } from "@/utils/numbers"; import EditEmbedModal from "./EditEmbedModal"; import CodeSnippetModal from "./CodeSnippetModal"; +import moment from "moment"; export default function EmbedRow({ embed }) { const rowRef = useRef(null); @@ -75,7 +76,7 @@ export default function EmbedRow({ embed }) { rel="noreferrer" className="text-white flex items-center hover:underline" > - {embed.workspace.name} + {embed.workspace.name} @@ -84,30 +85,47 @@ export default function EmbedRow({ embed }) { + + { + // If the embed was created more than a day ago, show the date, otherwise show the time ago + moment(embed.createdAt).diff(moment(), "days") > 0 + ? moment(embed.createdAt).format("MMM D, YYYY") + : moment(embed.createdAt).fromNow() + } + - + diff --git a/frontend/src/pages/GeneralSettings/EmbedConfigs/NewEmbedModal/index.jsx b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/NewEmbedModal/index.jsx similarity index 100% rename from frontend/src/pages/GeneralSettings/EmbedConfigs/NewEmbedModal/index.jsx rename to frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/NewEmbedModal/index.jsx diff --git a/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/index.jsx b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/index.jsx new file mode 100644 index 0000000000..236c95a798 --- /dev/null +++ b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/EmbedConfigs/index.jsx @@ -0,0 +1,97 @@ +import { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import * as Skeleton from "react-loading-skeleton"; +import "react-loading-skeleton/dist/skeleton.css"; +import { CodeBlock } from "@phosphor-icons/react"; +import EmbedRow from "./EmbedRow"; +import NewEmbedModal from "./NewEmbedModal"; +import { useModal } from "@/hooks/useModal"; +import ModalWrapper from "@/components/ModalWrapper"; +import Embed from "@/models/embed"; +import CTAButton from "@/components/lib/CTAButton"; + +export default function EmbedConfigsView() { + const { isOpen, openModal, closeModal } = useModal(); + const { t } = useTranslation(); + const [loading, setLoading] = useState(true); + const [embeds, setEmbeds] = useState([]); + + useEffect(() => { + async function fetchUsers() { + const _embeds = await Embed.embeds(); + setEmbeds(_embeds); + setLoading(false); + } + fetchUsers(); + }, []); + + if (loading) { + return ( + + ); + } + + return ( +
+
+
+

+ {t("embeddable.title")} +

+
+ +
+

+ {t("embeddable.description")} +

+ +
+ + {" "} + {t("embeddable.create")} + +
+
+
+
+ + + + + + + + + + + + {embeds.map((embed) => ( + + ))} + +
+ {t("embeddable.table.workspace")} + + {t("embeddable.table.chats")} + + {t("embeddable.table.active")} + + {t("embeddable.table.created")} + + {" "} +
+
+ + + +
+ ); +} diff --git a/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/index.jsx b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/index.jsx new file mode 100644 index 0000000000..d094579715 --- /dev/null +++ b/frontend/src/pages/GeneralSettings/ChatEmbedWidgets/index.jsx @@ -0,0 +1,156 @@ +import { useState } from "react"; +import Sidebar from "@/components/SettingsSidebar"; +import { isMobile } from "react-device-detect"; +import { CaretLeft, CaretRight } from "@phosphor-icons/react"; +import { useTranslation } from "react-i18next"; +import EmbedConfigsView from "./EmbedConfigs"; +import EmbedChatsView from "./EmbedChats"; + +export default function ChatEmbedWidgets() { + const { t } = useTranslation(); + const [selectedView, setSelectedView] = useState("configs"); + const [showViewModal, setShowViewModal] = useState(false); + + if (isMobile) { + return ( + +
+ + {showViewModal && ( +
+
+
+ +
+
+
+ {selectedView === "configs" ? ( + + ) : ( + + )} +
+
+
+
+ )} +
+
+ ); + } + + return ( + +
+
+
+
+

Chat Embed

+
+
+ +
+
+ +
+
+
+
+
+ {selectedView === "configs" ? ( + + ) : ( + + )} +
+
+
+
+ ); +} + +function WidgetLayout({ children }) { + return ( +
+ +
+ {children} +
+
+ ); +} + +function WidgetList({ selectedView, handleClick }) { + const views = { + configs: { + title: "Widgets", + }, + chats: { + title: "History", + }, + }; + + return ( +
+ {Object.entries(views).map(([view, settings], index) => ( +
handleClick?.(view)} + > +
{settings.title}
+ +
+ ))} +
+ ); +} diff --git a/frontend/src/pages/GeneralSettings/EmbedChats/index.jsx b/frontend/src/pages/GeneralSettings/EmbedChats/index.jsx deleted file mode 100644 index f04ad10869..0000000000 --- a/frontend/src/pages/GeneralSettings/EmbedChats/index.jsx +++ /dev/null @@ -1,246 +0,0 @@ -import { useEffect, useState, useRef } from "react"; -import Sidebar from "@/components/SettingsSidebar"; -import { isMobile } from "react-device-detect"; -import * as Skeleton from "react-loading-skeleton"; -import "react-loading-skeleton/dist/skeleton.css"; -import useQuery from "@/hooks/useQuery"; -import ChatRow from "./ChatRow"; -import Embed from "@/models/embed"; -import { useTranslation } from "react-i18next"; -import { CaretDown, Download } from "@phosphor-icons/react"; -import showToast from "@/utils/toast"; -import { saveAs } from "file-saver"; -import System from "@/models/system"; -import { CanViewChatHistory } from "@/components/CanViewChatHistory"; - -const exportOptions = { - csv: { - name: "CSV", - mimeType: "text/csv", - fileExtension: "csv", - filenameFunc: () => { - return `anythingllm-embed-chats-${new Date().toLocaleDateString()}`; - }, - }, - json: { - name: "JSON", - mimeType: "application/json", - fileExtension: "json", - filenameFunc: () => { - return `anythingllm-embed-chats-${new Date().toLocaleDateString()}`; - }, - }, - jsonl: { - name: "JSONL", - mimeType: "application/jsonl", - fileExtension: "jsonl", - filenameFunc: () => { - return `anythingllm-embed-chats-${new Date().toLocaleDateString()}-lines`; - }, - }, - jsonAlpaca: { - name: "JSON (Alpaca)", - mimeType: "application/json", - fileExtension: "json", - filenameFunc: () => { - return `anythingllm-embed-chats-${new Date().toLocaleDateString()}-alpaca`; - }, - }, -}; - -export default function EmbedChats() { - const [showMenu, setShowMenu] = useState(false); - const menuRef = useRef(); - const openMenuButton = useRef(); - const { t } = useTranslation(); - - const handleDumpChats = async (exportType) => { - const chats = await System.exportChats(exportType, "embed"); - if (!!chats) { - const { name, mimeType, fileExtension, filenameFunc } = - exportOptions[exportType]; - const blob = new Blob([chats], { type: mimeType }); - saveAs(blob, `${filenameFunc()}.${fileExtension}`); - showToast(`Embed chats exported successfully as ${name}.`, "success"); - } else { - showToast("Failed to export embed chats.", "error"); - } - }; - - const toggleMenu = () => { - setShowMenu(!showMenu); - }; - - useEffect(() => { - function handleClickOutside(event) { - if ( - menuRef.current && - !menuRef.current.contains(event.target) && - !openMenuButton.current.contains(event.target) - ) { - setShowMenu(false); - } - } - - document.addEventListener("mousedown", handleClickOutside); - return () => { - document.removeEventListener("mousedown", handleClickOutside); - }; - }, []); - - return ( - -
- -
-
-
-
-

- {t("embed-chats.title")} -

-
- -
-
- {Object.entries(exportOptions).map(([key, data]) => ( - - ))} -
-
-
-
-

- {t("embed-chats.description")} -

-
-
- -
-
-
-
-
- ); -} - -function ChatsContainer() { - const query = useQuery(); - const [loading, setLoading] = useState(true); - const [chats, setChats] = useState([]); - const [offset, setOffset] = useState(Number(query.get("offset") || 0)); - const [canNext, setCanNext] = useState(false); - const { t } = useTranslation(); - - const handlePrevious = () => { - setOffset(Math.max(offset - 1, 0)); - }; - const handleNext = () => { - setOffset(offset + 1); - }; - - const handleDeleteChat = (chatId) => { - setChats((prevChats) => prevChats.filter((chat) => chat.id !== chatId)); - }; - - useEffect(() => { - async function fetchChats() { - const { chats: _chats, hasPages = false } = await Embed.chats(offset); - setChats(_chats); - setCanNext(hasPages); - setLoading(false); - } - fetchChats(); - }, [offset]); - - if (loading) { - return ( - - ); - } - - return ( - <> - - - - - - - - - - - - - {!!chats && - chats.map((chat) => ( - - ))} - -
- {t("embed-chats.table.embed")} - - {t("embed-chats.table.sender")} - - {t("embed-chats.table.message")} - - {t("embed-chats.table.response")} - - {t("embed-chats.table.at")} - - {" "} -
-
- - -
- - ); -} diff --git a/frontend/src/pages/GeneralSettings/EmbedConfigs/index.jsx b/frontend/src/pages/GeneralSettings/EmbedConfigs/index.jsx deleted file mode 100644 index 5decb6b1ae..0000000000 --- a/frontend/src/pages/GeneralSettings/EmbedConfigs/index.jsx +++ /dev/null @@ -1,110 +0,0 @@ -import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import Sidebar from "@/components/SettingsSidebar"; -import { isMobile } from "react-device-detect"; -import * as Skeleton from "react-loading-skeleton"; -import "react-loading-skeleton/dist/skeleton.css"; -import { CodeBlock } from "@phosphor-icons/react"; -import EmbedRow from "./EmbedRow"; -import NewEmbedModal from "./NewEmbedModal"; -import { useModal } from "@/hooks/useModal"; -import ModalWrapper from "@/components/ModalWrapper"; -import Embed from "@/models/embed"; -import CTAButton from "@/components/lib/CTAButton"; - -export default function EmbedConfigs() { - const { isOpen, openModal, closeModal } = useModal(); - const { t } = useTranslation(); - return ( -
- -
-
-
-
-

- {t("embeddable.title")} -

-
-

- {t("embeddable.description")} -

-
-
- - {" "} - {t("embeddable.create")} - -
-
- -
-
- - - -
-
- ); -} - -function EmbedContainer() { - const [loading, setLoading] = useState(true); - const [embeds, setEmbeds] = useState([]); - const { t } = useTranslation(); - - useEffect(() => { - async function fetchUsers() { - const _embeds = await Embed.embeds(); - setEmbeds(_embeds); - setLoading(false); - } - fetchUsers(); - }, []); - - if (loading) { - return ( - - ); - } - - return ( - - - - - - - - - - - {embeds.map((embed) => ( - - ))} - -
- {t("embeddable.table.workspace")} - - {t("embeddable.table.chats")} - - {t("embeddable.table.Active")} - - {" "} -
- ); -} diff --git a/frontend/src/utils/paths.js b/frontend/src/utils/paths.js index 48c28141b3..bf3a9ef91a 100644 --- a/frontend/src/utils/paths.js +++ b/frontend/src/utils/paths.js @@ -147,11 +147,8 @@ export default { privacy: () => { return "/settings/privacy"; }, - embedSetup: () => { - return `/settings/embed-config`; - }, - embedChats: () => { - return `/settings/embed-chats`; + embedChatWidgets: () => { + return `/settings/embed-chat-widgets`; }, browserExtension: () => { return `/settings/browser-extension`; diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index b9cc37fe4a..47d7b4c2ed 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -142,7 +142,16 @@ export default { "button-text": 'var(--theme-checklist-button-text)', "button-hover-bg": 'var(--theme-checklist-button-hover-bg)', "button-hover-border": 'var(--theme-checklist-button-hover-border)', - } + }, + button: { + text: 'var(--theme-button-text)', + 'code-hover-text': 'var(--theme-button-code-hover-text)', + 'code-hover-bg': 'var(--theme-button-code-hover-bg)', + 'disable-hover-text': 'var(--theme-button-disable-hover-text)', + 'disable-hover-bg': 'var(--theme-button-disable-hover-bg)', + 'delete-hover-text': 'var(--theme-button-delete-hover-text)', + 'delete-hover-bg': 'var(--theme-button-delete-hover-bg)', + }, }, }, backgroundImage: { diff --git a/package.json b/package.json index d59d6a4793..91188e0957 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "generate:cloudformation": "node cloud-deployments/aws/cloudformation/generate.mjs", "generate::gcp_deployment": "node cloud-deployments/gcp/deployment/generate.mjs", "verify:translations": "cd frontend/src/locales && node verifyTranslations.mjs", - "normalize:translations": "cd frontend/src/locales && node normalizeEn.mjs" + "normalize:translations": "cd frontend/src/locales && node normalizeEn.mjs && cd ../../.. && yarn lint && yarn verify:translations" }, "private": false, "devDependencies": {