Implemented toast messages for all system settings ()

* implemented toast for appearance settings changes

* linting

* implemented toast on system settings changes
This commit is contained in:
Sean Hatfield 2023-08-23 20:35:34 -07:00 committed by GitHub
parent 761500c42f
commit 3274d5ab6b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 101 deletions
frontend/src
components/Modals/Settings
Appearance
LLMSelection
PasswordProtection
pages/Admin
Appearance
System

View file

@ -5,13 +5,12 @@ import System from "../../../../models/system";
import EditingChatBubble from "../../../EditingChatBubble";
import AnythingLLMLight from "../../../../media/logo/anything-llm-light.png";
import AnythingLLMDark from "../../../../media/logo/anything-llm-dark.png";
import showToast from "../../../../utils/toast";
export default function Appearance() {
const { logo: _initLogo } = useLogo();
const prefersDarkMode = usePrefersDarkMode();
const [logo, setLogo] = useState("");
const [errorMsg, setErrorMsg] = useState("");
const [successMsg, setSuccessMsg] = useState("");
const [hasChanges, setHasChanges] = useState(false);
const [messages, setMessages] = useState([]);
@ -30,20 +29,6 @@ export default function Appearance() {
setInitLogo();
}, [_initLogo]);
useEffect(() => {
if (!!successMsg) {
setTimeout(() => {
setSuccessMsg("");
}, 3_500);
}
if (!!errorMsg) {
setTimeout(() => {
setErrorMsg("");
}, 3_500);
}
}, [successMsg, errorMsg]);
const handleFileUpload = async (event) => {
const file = event.target.files[0];
if (!file) return false;
@ -53,30 +38,26 @@ export default function Appearance() {
const { success, error } = await System.uploadLogo(formData);
if (!success) {
console.error("Failed to upload logo:", error);
setErrorMsg(error);
setSuccessMsg("");
showToast(`Failed to upload logo: ${error}`, "error");
return;
}
const logoURL = await System.fetchLogo();
setLogo(logoURL);
setSuccessMsg("Image uploaded successfully");
setErrorMsg("");
showToast("Image uploaded successfully.", "success");
};
const handleRemoveLogo = async () => {
const { success, error } = await System.removeCustomLogo();
if (!success) {
console.error("Failed to remove logo:", error);
setErrorMsg(error);
setSuccessMsg("");
showToast(`Failed to remove logo: ${error}`, "error");
return;
}
const logoURL = await System.fetchLogo();
setLogo(logoURL);
setSuccessMsg("Image successfully removed");
setErrorMsg("");
showToast("Image successfully removed.", "success");
};
const addMessage = (type) => {
@ -108,10 +89,10 @@ export default function Appearance() {
const handleMessageSave = async () => {
const { success, error } = await System.setWelcomeMessages(messages);
if (!success) {
setErrorMsg(error);
showToast(`Failed to update welcome messages: ${error}`, "error");
return;
}
setSuccessMsg("Successfully updated welcome messages.");
showToast("Successfully updated welcome messages.", "success");
setHasChanges(false);
};
@ -227,16 +208,6 @@ export default function Appearance() {
</div>
)}
</div>
{errorMsg && (
<div className="mt-4 text-sm text-red-600 dark:text-red-400 text-center">
{errorMsg}
</div>
)}
{successMsg && (
<div className="mt-4 text-sm text-green-600 dark:text-green-400 text-center">
{successMsg}
</div>
)}
</div>
</div>
</div>

View file

@ -3,6 +3,7 @@ import System from "../../../../models/system";
import OpenAiLogo from "../../../../media/llmprovider/openai.png";
import AzureOpenAiLogo from "../../../../media/llmprovider/azure.png";
import AnthropicLogo from "../../../../media/llmprovider/anthropic.png";
import showToast from "../../../../utils/toast";
const noop = () => false;
export default function LLMSelection({
@ -13,7 +14,6 @@ export default function LLMSelection({
const [hasChanges, setHasChanges] = useState(false);
const [llmChoice, setLLMChoice] = useState(settings?.LLMProvider || "openai");
const [saving, setSaving] = useState(false);
const [error, setError] = useState(null);
const canDebug = settings.MultiUserMode
? settings?.CanDebug && user?.role === "admin"
: settings?.CanDebug;
@ -27,12 +27,15 @@ export default function LLMSelection({
const handleSubmit = async (e) => {
e.preventDefault();
setSaving(true);
setError(null);
const data = {};
const form = new FormData(e.target);
for (var [key, value] of form.entries()) data[key] = value;
const { error } = await System.updateSystem(data);
setError(error);
if (error) {
showToast(`Failed to save LLM settings: ${error}`, "error");
} else {
showToast("LLM settings saved successfully.", "success");
}
setSaving(false);
setHasChanges(!!error ? true : false);
};
@ -47,12 +50,6 @@ export default function LLMSelection({
</p>
</div>
{!!error && (
<div className="mb-8 bg-red-700 dark:bg-orange-800 bg-opacity-30 border border-red-800 dark:border-orange-600 p-4 rounded-lg w-[90%] flex mx-auto">
<p className="text-red-800 dark:text-orange-300 text-sm">{error}</p>
</div>
)}
<form onSubmit={handleSubmit} onChange={() => setHasChanges(true)}>
<div className="px-6 space-y-6 flex h-full w-full">
<div className="w-full flex flex-col gap-y-4">

View file

@ -1,6 +1,7 @@
import React, { useState } from "react";
import System from "../../../../models/system";
import { AUTH_TOKEN, AUTH_USER } from "../../../../utils/constants";
import showToast from "../../../../utils/toast";
const noop = () => false;
export default function PasswordProtection({
@ -8,15 +9,11 @@ export default function PasswordProtection({
settings = {},
}) {
const [saving, setSaving] = useState(false);
const [success, setSuccess] = useState(false);
const [error, setError] = useState(null);
const [usePassword, setUsePassword] = useState(settings?.RequiresAuth);
const handleSubmit = async (e) => {
e.preventDefault();
setSaving(true);
setSuccess(false);
setError(null);
const form = new FormData(e.target);
const data = {
@ -26,17 +23,18 @@ export default function PasswordProtection({
const { success, error } = await System.updateSystemPassword(data);
if (success) {
setSuccess(true);
showToast("Your page will refresh in a few seconds.", "success");
setSaving(false);
setTimeout(() => {
window.localStorage.removeItem(AUTH_USER);
window.localStorage.removeItem(AUTH_TOKEN);
window.location.reload();
}, 2_000);
}, 3_000);
return;
} else {
showToast(`Failed to update password: ${error}`, "error");
}
setError(error);
setSaving(false);
};
@ -49,20 +47,6 @@ export default function PasswordProtection({
this there is no recovery method so ensure you save this password.
</p>
</div>
{(error || success) && (
<div className="w-full flex px-6">
{error && (
<div className="w-full bg-red-300 text-red-800 font-semibold px-4 py-2 rounded-lg">
{error}
</div>
)}
{success && (
<div className="w-full bg-green-300 text-green-800 font-semibold px-4 py-2 rounded-lg">
Your page will refresh in a few seconds.
</div>
)}
</div>
)}
<div className="p-6 space-y-6 flex h-full w-full">
<div className="w-full flex flex-col gap-y-4">
<form onSubmit={handleSubmit}>

View file

@ -8,13 +8,12 @@ import usePrefersDarkMode from "../../../hooks/usePrefersDarkMode";
import useLogo from "../../../hooks/useLogo";
import System from "../../../models/system";
import EditingChatBubble from "../../../components/EditingChatBubble";
import showToast from "../../../utils/toast";
export default function Appearance() {
const { logo: _initLogo } = useLogo();
const [logo, setLogo] = useState("");
const prefersDarkMode = usePrefersDarkMode();
const [errorMsg, setErrorMsg] = useState("");
const [successMsg, setSuccessMsg] = useState("");
const [hasChanges, setHasChanges] = useState(false);
const [messages, setMessages] = useState([]);
@ -25,20 +24,6 @@ export default function Appearance() {
setInitLogo();
}, [_initLogo]);
useEffect(() => {
if (!!errorMsg) {
setTimeout(() => {
setErrorMsg("");
}, 3_500);
}
if (!!successMsg) {
setTimeout(() => {
setSuccessMsg("");
}, 3_500);
}
}, [errorMsg, successMsg]);
useEffect(() => {
async function fetchMessages() {
const messages = await System.getWelcomeMessages();
@ -55,29 +40,26 @@ export default function Appearance() {
formData.append("logo", file);
const { success, error } = await Admin.uploadLogo(formData);
if (!success) {
setErrorMsg(error);
showToast(`Failed to upload logo: ${error}`, "error");
return;
}
const logoURL = await System.fetchLogo();
setLogo(logoURL);
setErrorMsg("");
window.location.reload();
showToast("Image uploaded successfully.", "success");
};
const handleRemoveLogo = async () => {
const { success, error } = await Admin.removeCustomLogo();
if (!success) {
console.error("Failed to remove logo:", error);
setErrorMsg(error);
showToast(`Failed to remove logo: ${error}`, "error");
return;
}
const logoURL = await System.fetchLogo();
setLogo(logoURL);
setErrorMsg("");
window.location.reload();
showToast("Image successfully removed.", "success");
};
const addMessage = (type) => {
@ -109,10 +91,10 @@ export default function Appearance() {
const handleMessageSave = async () => {
const { success, error } = await Admin.setWelcomeMessages(messages);
if (!success) {
setErrorMsg(error);
showToast(`Failed to update welcome messages: ${error}`, "error");
return;
}
setSuccessMsg("Successfully updated welcome messages.");
showToast("Successfully updated welcome messages.", "success");
setHasChanges(false);
};
@ -235,16 +217,6 @@ export default function Appearance() {
</div>
)}
</div>
{errorMsg && (
<div className="mt-4 text-sm text-red-600 dark:text-red-400 text-center">
{errorMsg}
</div>
)}
{successMsg && (
<div className="mt-4 text-sm text-green-600 dark:text-green-400 text-center">
{successMsg}
</div>
)}
</div>
</div>
</div>

View file

@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
import Sidebar, { SidebarMobileHeader } from "../../../components/AdminSidebar";
import { isMobile } from "react-device-detect";
import Admin from "../../../models/admin";
import showToast from "../../../utils/toast";
export default function AdminSystem() {
const [saving, setSaving] = useState(false);
@ -21,6 +22,7 @@ export default function AdminSystem() {
});
setSaving(false);
setHasChanges(false);
showToast("System preferences updated successfully.", "success");
};
useEffect(() => {