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 && (
-
-
-
- )}
-
+
+