diff --git a/frontend/src/pages/GeneralSettings/Appearance/CustomLogo/index.jsx b/frontend/src/pages/GeneralSettings/Appearance/CustomLogo/index.jsx new file mode 100644 index 00000000..274bcfa3 --- /dev/null +++ b/frontend/src/pages/GeneralSettings/Appearance/CustomLogo/index.jsx @@ -0,0 +1,120 @@ +import useLogo from "@/hooks/useLogo"; +import System from "@/models/system"; +import showToast from "@/utils/toast"; +import { useEffect, useState } from "react"; +import AnythingLLM from "@/media/logo/anything-llm.png"; +import { Plus } from "@phosphor-icons/react"; + +export default function CustomLogo() { + const { logo: _initLogo, setLogo: _setLogo } = useLogo(); + const [logo, setLogo] = useState(""); + const [isDefaultLogo, setIsDefaultLogo] = useState(true); + + useEffect(() => { + async function logoInit() { + setLogo(_initLogo || ""); + const _isDefaultLogo = await System.isDefaultLogo(); + setIsDefaultLogo(_isDefaultLogo); + } + logoInit(); + }, [_initLogo]); + + const handleFileUpload = async (event) => { + const file = event.target.files[0]; + if (!file) return false; + + const objectURL = URL.createObjectURL(file); + setLogo(objectURL); + + const formData = new FormData(); + formData.append("logo", file); + const { success, error } = await System.uploadLogo(formData); + if (!success) { + showToast(`Failed to upload logo: ${error}`, "error"); + setLogo(_initLogo); + return; + } + + const logoURL = await System.fetchLogo(); + _setLogo(logoURL); + + showToast("Image uploaded successfully.", "success"); + setIsDefaultLogo(false); + }; + + const handleRemoveLogo = async () => { + setLogo(""); + setIsDefaultLogo(true); + + const { success, error } = await System.removeCustomLogo(); + if (!success) { + console.error("Failed to remove logo:", error); + showToast(`Failed to remove logo: ${error}`, "error"); + const logoURL = await System.fetchLogo(); + setLogo(logoURL); + setIsDefaultLogo(false); + return; + } + + const logoURL = await System.fetchLogo(); + _setLogo(logoURL); + + showToast("Image successfully removed.", "success"); + }; + + return ( +
+
+

Custom Logo

+

+ Upload your custom logo to make your chatbot yours. +

+
+
+ (e.target.src = AnythingLLM)} + /> +
+ + +
+
+
+ ); +} diff --git a/frontend/src/pages/GeneralSettings/Appearance/CustomMessages/index.jsx b/frontend/src/pages/GeneralSettings/Appearance/CustomMessages/index.jsx new file mode 100644 index 00000000..42df5b9d --- /dev/null +++ b/frontend/src/pages/GeneralSettings/Appearance/CustomMessages/index.jsx @@ -0,0 +1,119 @@ +import EditingChatBubble from "@/components/EditingChatBubble"; +import System from "@/models/system"; +import showToast from "@/utils/toast"; +import { Plus } from "@phosphor-icons/react"; +import { useEffect, useState } from "react"; + +export default function CustomMessages() { + const [hasChanges, setHasChanges] = useState(false); + const [messages, setMessages] = useState([]); + + useEffect(() => { + async function fetchMessages() { + const messages = await System.getWelcomeMessages(); + setMessages(messages); + } + fetchMessages(); + }, []); + + const addMessage = (type) => { + if (type === "user") { + setMessages([ + ...messages, + { user: "Double click to edit...", response: "" }, + ]); + } else { + setMessages([ + ...messages, + { user: "", response: "Double click to edit..." }, + ]); + } + }; + + const removeMessage = (index) => { + setHasChanges(true); + setMessages(messages.filter((_, i) => i !== index)); + }; + + const handleMessageChange = (index, type, value) => { + setHasChanges(true); + const newMessages = [...messages]; + newMessages[index][type] = value; + setMessages(newMessages); + }; + + const handleMessageSave = async () => { + const { success, error } = await System.setWelcomeMessages(messages); + if (!success) { + showToast(`Failed to update welcome messages: ${error}`, "error"); + return; + } + showToast("Successfully updated welcome messages.", "success"); + setHasChanges(false); + }; + + return ( +
+
+

+ Custom Messages +

+

+ Customize the automatic messages displayed to your users. +

+
+
+ {messages.map((message, index) => ( +
+ {message.user && ( + + )} + {message.response && ( + + )} +
+ ))} +
+ + +
+
+ {hasChanges && ( +
+ +
+ )} +
+ ); +} diff --git a/frontend/src/pages/GeneralSettings/Appearance/index.jsx b/frontend/src/pages/GeneralSettings/Appearance/index.jsx index 2ac04208..9aed853b 100644 --- a/frontend/src/pages/GeneralSettings/Appearance/index.jsx +++ b/frontend/src/pages/GeneralSettings/Appearance/index.jsx @@ -1,118 +1,11 @@ -import React, { useState, useEffect } from "react"; import Sidebar from "@/components/SettingsSidebar"; import { isMobile } from "react-device-detect"; -import AnythingLLM from "@/media/logo/anything-llm.png"; -import useLogo from "@/hooks/useLogo"; -import System from "@/models/system"; -import EditingChatBubble from "@/components/EditingChatBubble"; -import showToast from "@/utils/toast"; -import { Plus } from "@phosphor-icons/react"; import FooterCustomization from "./FooterCustomization"; import SupportEmail from "./SupportEmail"; +import CustomLogo from "./CustomLogo"; +import CustomMessages from "./CustomMessages"; export default function Appearance() { - const { logo: _initLogo, setLogo: _setLogo } = useLogo(); - const [logo, setLogo] = useState(""); - const [hasChanges, setHasChanges] = useState(false); - const [messages, setMessages] = useState([]); - const [isDefaultLogo, setIsDefaultLogo] = useState(true); - - useEffect(() => { - async function logoInit() { - setLogo(_initLogo || ""); - const _isDefaultLogo = await System.isDefaultLogo(); - setIsDefaultLogo(_isDefaultLogo); - } - logoInit(); - }, [_initLogo]); - - useEffect(() => { - async function fetchMessages() { - const messages = await System.getWelcomeMessages(); - setMessages(messages); - } - fetchMessages(); - }, []); - - const handleFileUpload = async (event) => { - const file = event.target.files[0]; - if (!file) return false; - - const objectURL = URL.createObjectURL(file); - setLogo(objectURL); - - const formData = new FormData(); - formData.append("logo", file); - const { success, error } = await System.uploadLogo(formData); - if (!success) { - showToast(`Failed to upload logo: ${error}`, "error"); - setLogo(_initLogo); - return; - } - - const logoURL = await System.fetchLogo(); - _setLogo(logoURL); - - showToast("Image uploaded successfully.", "success"); - setIsDefaultLogo(false); - }; - - const handleRemoveLogo = async () => { - setLogo(""); - setIsDefaultLogo(true); - - const { success, error } = await System.removeCustomLogo(); - if (!success) { - console.error("Failed to remove logo:", error); - showToast(`Failed to remove logo: ${error}`, "error"); - const logoURL = await System.fetchLogo(); - setLogo(logoURL); - setIsDefaultLogo(false); - return; - } - - const logoURL = await System.fetchLogo(); - _setLogo(logoURL); - - showToast("Image successfully removed.", "success"); - }; - - const addMessage = (type) => { - if (type === "user") { - setMessages([ - ...messages, - { user: "Double click to edit...", response: "" }, - ]); - } else { - setMessages([ - ...messages, - { user: "", response: "Double click to edit..." }, - ]); - } - }; - - const removeMessage = (index) => { - setHasChanges(true); - setMessages(messages.filter((_, i) => i !== index)); - }; - - const handleMessageChange = (index, type, value) => { - setHasChanges(true); - const newMessages = [...messages]; - newMessages[index][type] = value; - setMessages(newMessages); - }; - - const handleMessageSave = async () => { - const { success, error } = await System.setWelcomeMessages(messages); - if (!success) { - showToast(`Failed to update welcome messages: ${error}`, "error"); - return; - } - showToast("Successfully updated welcome messages.", "success"); - setHasChanges(false); - }; - return (
@@ -131,125 +24,8 @@ export default function Appearance() { Customize the appearance settings of your platform.

-
-
-

- Custom Logo -

-

- Upload your custom logo to make your chatbot yours. -

-
-
- (e.target.src = AnythingLLM)} - /> -
- - -
-
-
-
-
-

- Custom Messages -

-

- Customize the automatic messages displayed to your users. -

-
-
- {messages.map((message, index) => ( -
- {message.user && ( - - )} - {message.response && ( - - )} -
- ))} -
- - -
-
- {hasChanges && ( -
- -
- )} -
+ +