diff --git a/frontend/.gitignore b/frontend/.gitignore index 196c8f69185..78720603424 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -12,6 +12,7 @@ dist lib dist-ssr *.local +!frontend/components/lib # Editor directories and files .vscode/* diff --git a/frontend/src/components/lib/CTAButton/index.jsx b/frontend/src/components/lib/CTAButton/index.jsx new file mode 100644 index 00000000000..93427f0f945 --- /dev/null +++ b/frontend/src/components/lib/CTAButton/index.jsx @@ -0,0 +1,16 @@ +export default function CTAButton({ + children, + disabled = false, + onClick, + className = "", +}) { + return ( + + ); +} diff --git a/frontend/src/pages/Admin/Invitations/index.jsx b/frontend/src/pages/Admin/Invitations/index.jsx index f81ccae52d5..599271ad989 100644 --- a/frontend/src/pages/Admin/Invitations/index.jsx +++ b/frontend/src/pages/Admin/Invitations/index.jsx @@ -10,6 +10,7 @@ import InviteRow from "./InviteRow"; import NewInviteModal from "./NewInviteModal"; import { useModal } from "@/hooks/useModal"; import ModalWrapper from "@/components/ModalWrapper"; +import CTAButton from "@/components/lib/CTAButton"; export default function AdminInvites() { const { isOpen, openModal, closeModal } = useModal(); @@ -21,25 +22,24 @@ export default function AdminInvites() { style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }} className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-main-gradient w-full h-full overflow-y-scroll" > -
+

Invitations

-

Create invitation links for people in your organization to accept and sign up with. Invitations can only be used by a single user.

+
+ + Create Invite + Link + +
diff --git a/frontend/src/pages/Admin/Logging/index.jsx b/frontend/src/pages/Admin/Logging/index.jsx index 5d8a90acba5..69a81ab56cb 100644 --- a/frontend/src/pages/Admin/Logging/index.jsx +++ b/frontend/src/pages/Admin/Logging/index.jsx @@ -6,6 +6,7 @@ import { isMobile } from "react-device-detect"; import * as Skeleton from "react-loading-skeleton"; import LogRow from "./LogRow"; import showToast from "@/utils/toast"; +import CTAButton from "@/components/lib/CTAButton"; export default function AdminLogs() { const handleResetLogs = async () => { @@ -32,24 +33,26 @@ export default function AdminLogs() { style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }} className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-main-gradient w-full h-full overflow-y-scroll" > -
+

Event Logs

-

View all actions and events happening on this instance for monitoring.

+
+ + Clear Event Logs + +
diff --git a/frontend/src/pages/Admin/System/index.jsx b/frontend/src/pages/Admin/System/index.jsx index 867276b0efb..bdab765a5a7 100644 --- a/frontend/src/pages/Admin/System/index.jsx +++ b/frontend/src/pages/Admin/System/index.jsx @@ -3,6 +3,7 @@ import Sidebar from "@/components/SettingsSidebar"; import { isMobile } from "react-device-detect"; import Admin from "@/models/admin"; import showToast from "@/utils/toast"; +import CTAButton from "@/components/lib/CTAButton"; export default function AdminSystem() { const [saving, setSaving] = useState(false); @@ -49,7 +50,7 @@ export default function AdminSystem() {
setHasChanges(true)} - className="flex flex-col w-full px-1 md:pl-6 md:pr-[86px] md:py-6 py-16" + className="flex flex-col w-full px-1 md:pl-6 md:pr-[50px] md:py-6 py-16" >
@@ -62,8 +63,14 @@ export default function AdminSystem() { instance.

- -
+ {hasChanges && ( +
+ + {saving ? "Saving..." : "Save changes"} + +
+ )} +

Users can delete workspaces @@ -141,18 +148,6 @@ export default function AdminSystem() {

)}
- - {hasChanges && ( -
- -
- )}
diff --git a/frontend/src/pages/Admin/Users/index.jsx b/frontend/src/pages/Admin/Users/index.jsx index 6824ee219be..408e794aaeb 100644 --- a/frontend/src/pages/Admin/Users/index.jsx +++ b/frontend/src/pages/Admin/Users/index.jsx @@ -10,6 +10,7 @@ import useUser from "@/hooks/useUser"; import NewUserModal from "./NewUserModal"; import { useModal } from "@/hooks/useModal"; import ModalWrapper from "@/components/ModalWrapper"; +import CTAButton from "@/components/lib/CTAButton"; export default function AdminUsers() { const { isOpen, openModal, closeModal } = useModal(); @@ -21,16 +22,10 @@ export default function AdminUsers() { style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }} className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-main-gradient w-full h-full overflow-y-scroll" > -
+

Users

-

These are all the accounts which have an account on this instance. @@ -38,6 +33,11 @@ export default function AdminUsers() { instance.

+
+ + Add user + +
diff --git a/frontend/src/pages/Admin/Workspaces/index.jsx b/frontend/src/pages/Admin/Workspaces/index.jsx index 63b9fb346bb..5a7b128d2e2 100644 --- a/frontend/src/pages/Admin/Workspaces/index.jsx +++ b/frontend/src/pages/Admin/Workspaces/index.jsx @@ -9,6 +9,7 @@ import WorkspaceRow from "./WorkspaceRow"; import NewWorkspaceModal from "./NewWorkspaceModal"; import { useModal } from "@/hooks/useModal"; import ModalWrapper from "@/components/ModalWrapper"; +import CTAButton from "@/components/lib/CTAButton"; export default function AdminWorkspaces() { const { isOpen, openModal, closeModal } = useModal(); @@ -20,24 +21,23 @@ export default function AdminWorkspaces() { style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }} className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-main-gradient w-full h-full overflow-y-scroll" > -
+

Instance Workspaces

-

These are all the workspaces that exist on this instance. Removing a workspace will delete all of it's associated chats and settings.

+
+ + New Workspace + +
diff --git a/frontend/src/pages/GeneralSettings/ApiKeys/index.jsx b/frontend/src/pages/GeneralSettings/ApiKeys/index.jsx index 6df1d09dd33..4cf3fa39765 100644 --- a/frontend/src/pages/GeneralSettings/ApiKeys/index.jsx +++ b/frontend/src/pages/GeneralSettings/ApiKeys/index.jsx @@ -12,6 +12,7 @@ import { userFromStorage } from "@/utils/request"; import System from "@/models/system"; import ModalWrapper from "@/components/ModalWrapper"; import { useModal } from "@/hooks/useModal"; +import CTAButton from "@/components/lib/CTAButton"; export default function AdminApiKeys() { const { isOpen, openModal, closeModal } = useModal(); @@ -23,16 +24,10 @@ export default function AdminApiKeys() { style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }} className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-main-gradient w-full h-full overflow-y-scroll" > -
+

API Keys

-

API keys allow the holder to programmatically access and manage @@ -47,6 +42,12 @@ export default function AdminApiKeys() { Read the API documentation →

+
+ + Generate New API + Key + +
diff --git a/frontend/src/pages/GeneralSettings/Chats/index.jsx b/frontend/src/pages/GeneralSettings/Chats/index.jsx index e5da1a8884e..d5b3d50932d 100644 --- a/frontend/src/pages/GeneralSettings/Chats/index.jsx +++ b/frontend/src/pages/GeneralSettings/Chats/index.jsx @@ -90,7 +90,7 @@ export default function WorkspaceChats() { style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }} className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-main-gradient w-full h-full overflow-y-scroll" > -
+

diff --git a/frontend/src/pages/GeneralSettings/EmbedConfigs/index.jsx b/frontend/src/pages/GeneralSettings/EmbedConfigs/index.jsx index a46a9d5e09c..4d65e0d0398 100644 --- a/frontend/src/pages/GeneralSettings/EmbedConfigs/index.jsx +++ b/frontend/src/pages/GeneralSettings/EmbedConfigs/index.jsx @@ -9,6 +9,7 @@ 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(); @@ -20,18 +21,12 @@ export default function EmbedConfigs() { style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }} className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-main-gradient w-full h-full overflow-y-scroll" > -

+

Embeddable Chat Widgets

-

Embeddable chat widgets are public facing chat interfaces that are @@ -39,6 +34,11 @@ export default function EmbedConfigs() { that then you can publish to the world.

+
+ + Create embed + +
diff --git a/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx b/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx index d2b265560de..ad7c08d35c2 100644 --- a/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx +++ b/frontend/src/pages/GeneralSettings/EmbeddingPreference/index.jsx @@ -19,6 +19,7 @@ import EmbedderItem from "@/components/EmbeddingSelection/EmbedderItem"; import { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react"; import { useModal } from "@/hooks/useModal"; import ModalWrapper from "@/components/ModalWrapper"; +import CTAButton from "@/components/lib/CTAButton"; export default function GeneralEmbeddingPreference() { const [saving, setSaving] = useState(false); @@ -165,21 +166,12 @@ export default function GeneralEmbeddingPreference() { onSubmit={handleSubmit} className="flex w-full" > -
+

Embedding Preference

- {hasChanges && ( - - )}

When using an LLM that does not natively support an embedding @@ -191,6 +183,16 @@ export default function GeneralEmbeddingPreference() { format which AnythingLLM can use to process.

+
+ {hasChanges && ( + handleSubmit()} + className="mt-3 mr-0 -mb-14 z-10" + > + {saving ? "Saving..." : "Save changes"} + + )} +
Embedding Provider
diff --git a/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx b/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx index b9525c92561..04018aea1f3 100644 --- a/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx +++ b/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx @@ -35,6 +35,7 @@ import GroqAiOptions from "@/components/LLMSelection/GroqAiOptions"; import LLMItem from "@/components/LLMSelection/LLMItem"; import { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react"; +import CTAButton from "@/components/lib/CTAButton"; export default function GeneralLLMPreference() { const [saving, setSaving] = useState(false); @@ -226,21 +227,12 @@ export default function GeneralLLMPreference() { className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-main-gradient w-full h-full overflow-y-scroll" >
-
+

LLM Preference

- {hasChanges && ( - - )}

These are the credentials and settings for your preferred LLM @@ -249,6 +241,16 @@ export default function GeneralLLMPreference() { properly.

+
+ {hasChanges && ( + handleSubmit()} + className="mt-3 mr-0 -mb-14 z-10" + > + {saving ? "Saving..." : "Save changes"} + + )} +
LLM Provider
diff --git a/frontend/src/pages/GeneralSettings/PrivacyAndData/index.jsx b/frontend/src/pages/GeneralSettings/PrivacyAndData/index.jsx index dfc4b29f929..c0cd2b19916 100644 --- a/frontend/src/pages/GeneralSettings/PrivacyAndData/index.jsx +++ b/frontend/src/pages/GeneralSettings/PrivacyAndData/index.jsx @@ -29,16 +29,16 @@ export default function PrivacyAndDataHandling() {
-
+
-

+

Privacy & Data-Handling

-

+

This is your configuration for how connected third party providers and AnythingLLM handle your data.

diff --git a/frontend/src/pages/GeneralSettings/Security/index.jsx b/frontend/src/pages/GeneralSettings/Security/index.jsx index 298a81ad789..7d60aadadaf 100644 --- a/frontend/src/pages/GeneralSettings/Security/index.jsx +++ b/frontend/src/pages/GeneralSettings/Security/index.jsx @@ -6,6 +6,7 @@ import System from "@/models/system"; import paths from "@/utils/paths"; import { AUTH_TIMESTAMP, AUTH_TOKEN, AUTH_USER } from "@/utils/constants"; import PreLoader from "@/components/Preloader"; +import CTAButton from "@/components/lib/CTAButton"; export default function GeneralSecurity() { return ( @@ -13,7 +14,7 @@ export default function GeneralSecurity() {
@@ -32,7 +33,7 @@ function MultiUserMode() { const handleSubmit = async (e) => { e.preventDefault(); setSaving(true); - + setHasChanges(false); if (useMultiUserMode) { const form = new FormData(e.target); const data = { @@ -83,27 +84,30 @@ function MultiUserMode() { setHasChanges(true)} - className="flex w-full" + className="flex flex-col w-full px-1 md:pl-6 md:pr-[50px] md:py-6 py-16" > -
-
+
+
-

Multi-User Mode

- {hasChanges && ( - - )} +

+ Multi-User Mode +

-

+

Set up your instance to support your team by activating Multi-User Mode.

+ {hasChanges && ( +
+ handleSubmit()} + className="mt-3 mr-0 -mb-20 z-10" + > + {saving ? "Saving..." : "Save changes"} + +
+ )}
@@ -198,6 +202,7 @@ function PasswordProtection() { if (multiUserModeEnabled) return false; setSaving(true); + setHasChanges(false); const form = new FormData(e.target); const data = { usePassword, @@ -248,29 +253,30 @@ function PasswordProtection() { setHasChanges(true)} - className="flex w-full" + className="flex flex-col w-full px-1 md:pl-6 md:pr-[50px] md:py-6 py-16" > -
-
+
+
-

+

Password Protection

- {hasChanges && ( - - )}
-

+

Protect your AnythingLLM instance with a password. If you forget this there is no recovery method so ensure you save this password.

+ {hasChanges && ( +
+ handleSubmit()} + className="mt-3 mr-0 -mb-20 z-10" + > + {saving ? "Saving..." : "Save changes"} + +
+ )}
diff --git a/frontend/src/pages/GeneralSettings/TranscriptionPreference/index.jsx b/frontend/src/pages/GeneralSettings/TranscriptionPreference/index.jsx index c4d20ef4ba9..5fbd196c328 100644 --- a/frontend/src/pages/GeneralSettings/TranscriptionPreference/index.jsx +++ b/frontend/src/pages/GeneralSettings/TranscriptionPreference/index.jsx @@ -10,6 +10,7 @@ import OpenAiWhisperOptions from "@/components/TranscriptionSelection/OpenAiOpti import NativeTranscriptionOptions from "@/components/TranscriptionSelection/NativeTranscriptionOptions"; import LLMItem from "@/components/LLMSelection/LLMItem"; import { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react"; +import CTAButton from "@/components/lib/CTAButton"; export default function TranscriptionModelPreference() { const [saving, setSaving] = useState(false); @@ -114,21 +115,12 @@ export default function TranscriptionModelPreference() { className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-main-gradient w-full h-full overflow-y-scroll" > -
+

Transcription Model Preference

- {hasChanges && ( - - )}

These are the credentials and settings for your preferred @@ -137,6 +129,16 @@ export default function TranscriptionModelPreference() { transcribe.

+
+ {hasChanges && ( + handleSubmit()} + className="mt-3 mr-0 -mb-14 z-10" + > + {saving ? "Saving..." : "Save changes"} + + )} +
Transcription Provider
diff --git a/frontend/src/pages/GeneralSettings/VectorDatabase/index.jsx b/frontend/src/pages/GeneralSettings/VectorDatabase/index.jsx index df0307d1136..a782410e52d 100644 --- a/frontend/src/pages/GeneralSettings/VectorDatabase/index.jsx +++ b/frontend/src/pages/GeneralSettings/VectorDatabase/index.jsx @@ -25,6 +25,7 @@ import ZillizCloudOptions from "@/components/VectorDBSelection/ZillizCloudOption import { useModal } from "@/hooks/useModal"; import ModalWrapper from "@/components/ModalWrapper"; import AstraDBOptions from "@/components/VectorDBSelection/AstraDBOptions"; +import CTAButton from "@/components/lib/CTAButton"; export default function GeneralVectorDatabase() { const [saving, setSaving] = useState(false); @@ -189,21 +190,12 @@ export default function GeneralVectorDatabase() { onSubmit={handleSubmit} className="flex w-full" > -
+

Vector Database

- {hasChanges && ( - - )}

These are the credentials and settings for how your @@ -211,6 +203,16 @@ export default function GeneralVectorDatabase() { are current and correct.

+
+ {hasChanges && ( + handleSubmit()} + className="mt-3 mr-0 -mb-14 z-10" + > + {saving ? "Saving..." : "Save changes"} + + )} +
Vector Database Provider
diff --git a/frontend/src/pages/WorkspaceSettings/Members/AddMemberModal/index.jsx b/frontend/src/pages/WorkspaceSettings/Members/AddMemberModal/index.jsx index 0799e5486dc..e5410f40307 100644 --- a/frontend/src/pages/WorkspaceSettings/Members/AddMemberModal/index.jsx +++ b/frontend/src/pages/WorkspaceSettings/Members/AddMemberModal/index.jsx @@ -138,15 +138,17 @@ export default function AddMemberModal({ closeModal, workspace, users }) {

Select All

- + {selectedUsers.length > 0 && ( + + )}
- + Manage Users