Skip to content

Commit

Permalink
532 uiux add slash command modal (#555)
Browse files Browse the repository at this point in the history
* WIP slash commands

* add slash command image

* WIP slash commands

* slash command menu feature complete

* move icons to slash command local

* update how slash command component works

* relint with new linter

* Finalize slash command input
Change empty workspace text layout
Patch dev unmount issues on Chatworkspace/index.jsx

---------

Co-authored-by: timothycarambat <[email protected]>
  • Loading branch information
shatfield4 and timothycarambat authored Jan 9, 2024
1 parent 58971e8 commit 5c3bb4b
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 38 deletions.
28 changes: 14 additions & 14 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,28 @@ const AdminInvites = lazy(() => import("@/pages/Admin/Invitations"));
const AdminWorkspaces = lazy(() => import("@/pages/Admin/Workspaces"));
const AdminSystem = lazy(() => import("@/pages/Admin/System"));
const GeneralChats = lazy(() => import("@/pages/GeneralSettings/Chats"));
const GeneralAppearance = lazy(() =>
import("@/pages/GeneralSettings/Appearance")
const GeneralAppearance = lazy(
() => import("@/pages/GeneralSettings/Appearance")
);
const GeneralApiKeys = lazy(() => import("@/pages/GeneralSettings/ApiKeys"));
const GeneralLLMPreference = lazy(() =>
import("@/pages/GeneralSettings/LLMPreference")
const GeneralLLMPreference = lazy(
() => import("@/pages/GeneralSettings/LLMPreference")
);
const GeneralEmbeddingPreference = lazy(() =>
import("@/pages/GeneralSettings/EmbeddingPreference")
const GeneralEmbeddingPreference = lazy(
() => import("@/pages/GeneralSettings/EmbeddingPreference")
);
const GeneralVectorDatabase = lazy(() =>
import("@/pages/GeneralSettings/VectorDatabase")
const GeneralVectorDatabase = lazy(
() => import("@/pages/GeneralSettings/VectorDatabase")
);
const GeneralExportImport = lazy(() =>
import("@/pages/GeneralSettings/ExportImport")
const GeneralExportImport = lazy(
() => import("@/pages/GeneralSettings/ExportImport")
);
const GeneralSecurity = lazy(() => import("@/pages/GeneralSettings/Security"));
const DataConnectors = lazy(() =>
import("@/pages/GeneralSettings/DataConnectors")
const DataConnectors = lazy(
() => import("@/pages/GeneralSettings/DataConnectors")
);
const DataConnectorSetup = lazy(() =>
import("@/pages/GeneralSettings/DataConnectors/Connectors")
const DataConnectorSetup = lazy(
() => import("@/pages/GeneralSettings/DataConnectors/Connectors")
);
const OnboardingFlow = lazy(() => import("@/pages/OnboardingFlow"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,14 @@ export default function ChatHistory({ history = [], workspace }) {
};

const debouncedScroll = debounce(handleScroll, 100);

useEffect(() => {
if (!chatHistoryRef.current) return null;
const chatHistoryElement = chatHistoryRef.current;
chatHistoryElement.addEventListener("scroll", debouncedScroll);

return () => {
chatHistoryElement.removeEventListener("scroll", debouncedScroll);
debouncedScroll.cancel();
};
function watchScrollEvent() {
if (!chatHistoryRef.current) return null;
const chatHistoryElement = chatHistoryRef.current;
if (!chatHistoryElement) return null;
chatHistoryElement.addEventListener("scroll", debouncedScroll);
}
watchScrollEvent();
}, []);

const scrollToBottom = () => {
Expand All @@ -49,11 +47,11 @@ export default function ChatHistory({ history = [], workspace }) {
return (
<div className="flex flex-col h-full md:mt-0 pb-48 w-full justify-end items-center">
<div className="flex flex-col items-start">
<p className="text-white/60 text-lg font-base -ml-6 py-4">
<p className="text-white/60 text-lg font-base py-4">
Welcome to your new workspace.
</p>
<div className="w-full text-center">
<p className="text-white/60 text-lg font-base inline-flex items-center gap-x-2">
<p className="text-white/60 text-lg font-base inline-grid md:inline-flex items-center gap-x-2">
To get started either{" "}
<span
className="underline font-medium cursor-pointer"
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useEffect, useRef, useState } from "react";
import SlashCommandIcon from "./icons/slash-commands-icon.svg";

export default function SlashCommandsButton({ showing, setShowSlashCommand }) {
return (
<div
id="slash-cmd-btn"
onClick={() => setShowSlashCommand(!showing)}
className={`flex justify-center items-center opacity-60 hover:opacity-100 cursor-pointer ${
showing ? "!opacity-100" : ""
}`}
>
<img
src={SlashCommandIcon}
className="w-6 h-6 pointer-events-none"
alt="Slash commands button"
/>
</div>
);
}

export function SlashCommands({ showing, setShowing, sendCommand }) {
const cmdRef = useRef(null);
useEffect(() => {
function listenForOutsideClick() {
if (!showing || !cmdRef.current) return false;
document.addEventListener("click", closeIfOutside);
}
listenForOutsideClick();
}, [showing, cmdRef.current]);

if (!showing) return null;
const closeIfOutside = ({ target }) => {
if (target.id === "slash-cmd-btn") return;
const isOutside = !cmdRef?.current?.contains(target);
if (!isOutside) return;
setShowing(false);
};

return (
<div className="w-full flex justify-center absolute bottom-[130px] md:bottom-[150px] left-0 z-10 px-4">
<div
ref={cmdRef}
className="w-[600px] p-2 bg-zinc-800 rounded-2xl shadow flex-col justify-center items-start gap-2.5 inline-flex"
>
<button
onClick={() => {
setShowing(false);
sendCommand("/reset", true);
}}
className="w-full hover:cursor-pointer hover:bg-zinc-700 px-2 py-2 rounded-xl flex flex-col justify-start"
>
<div className="w-full flex-col text-left flex pointer-events-none">
<div className="text-white text-sm font-bold">/reset</div>
<div className="text-white text-opacity-60 text-sm">
Clear your chat history and begin a new chat
</div>
</div>
</button>
</div>
</div>
);
}

export function useSlashCommands() {
const [showSlashCommand, setShowSlashCommand] = useState(false);
return { showSlashCommand, setShowSlashCommand };
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import ManageWorkspace, {
useManageWorkspaceModal,
} from "../../../Modals/MangeWorkspace";
import useUser from "@/hooks/useUser";
import SlashCommandsButton, {
SlashCommands,
useSlashCommands,
} from "./SlashCommands";

export default function PromptInput({
workspace,
Expand All @@ -19,7 +23,9 @@ export default function PromptInput({
onChange,
inputDisabled,
buttonDisabled,
sendCommand,
}) {
const { showSlashCommand, setShowSlashCommand } = useSlashCommands();
const { showing, showModal, hideModal } = useManageWorkspaceModal();
const formRef = useRef(null);
const [_, setFocused] = useState(false);
Expand Down Expand Up @@ -49,7 +55,12 @@ export default function PromptInput({
};

return (
<div className="w-full fixed md:absolute bottom-0 left-0 z-10 md:z-0 flex justify-center items-center overflow-hidden">
<div className="w-full fixed md:absolute bottom-0 left-0 z-10 md:z-0 flex justify-center items-center">
<SlashCommands
showing={showSlashCommand}
setShowing={setShowSlashCommand}
sendCommand={sendCommand}
/>
<form
onSubmit={handleSubmit}
className="flex flex-col gap-y-1 rounded-t-lg md:w-3/4 w-full mx-auto max-w-xl"
Expand Down Expand Up @@ -95,17 +106,12 @@ export default function PromptInput({
weight="fill"
/>
)}

<ChatModeSelector workspace={workspace} />
{/* <TextT
className="w-7 h-7 text-white/30 cursor-not-allowed"
weight="fill"
/> */}
<SlashCommandsButton
showing={showSlashCommand}
setShowSlashCommand={setShowSlashCommand}
/>
</div>
{/* <Microphone
className="w-7 h-7 text-white/30 cursor-not-allowed"
weight="fill"
/> */}
</div>
</div>
</div>
Expand Down
26 changes: 25 additions & 1 deletion frontend/src/components/WorkspaceChat/ChatContainer/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export default function ChatContainer({ workspace, knownHistory = [] }) {
const [message, setMessage] = useState("");
const [loadingResponse, setLoadingResponse] = useState(false);
const [chatHistory, setChatHistory] = useState(knownHistory);

const handleMessageChange = (event) => {
setMessage(event.target.value);
};
Expand All @@ -36,6 +35,30 @@ export default function ChatContainer({ workspace, knownHistory = [] }) {
setLoadingResponse(true);
};

const sendCommand = async (command, submit = false) => {
if (!command || command === "") return false;
if (!submit) {
setMessage(command);
return;
}

const prevChatHistory = [
...chatHistory,
{ content: command, role: "user" },
{
content: "",
role: "assistant",
pending: true,
userMessage: command,
animate: true,
},
];

setChatHistory(prevChatHistory);
setMessage("");
setLoadingResponse(true);
};

useEffect(() => {
async function fetchReply() {
const promptMessage =
Expand Down Expand Up @@ -97,6 +120,7 @@ export default function ChatContainer({ workspace, knownHistory = [] }) {
onChange={handleMessageChange}
inputDisabled={loadingResponse}
buttonDisabled={loadingResponse}
sendCommand={sendCommand}
/>
</div>
</div>
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,18 @@ html,
body {
padding: 0;
margin: 0;
font-family: "plus-jakarta-sans", -apple-system, BlinkMacSystemFont, Segoe UI,
Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue,
font-family:
"plus-jakarta-sans",
-apple-system,
BlinkMacSystemFont,
Segoe UI,
Roboto,
Oxygen,
Ubuntu,
Cantarell,
Fira Sans,
Droid Sans,
Helvetica Neue,
sans-serif;
background-color: white;
}
Expand Down

0 comments on commit 5c3bb4b

Please sign in to comment.