Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add prompt trigger through # #1023

Merged
merged 12 commits into from
Aug 29, 2023
6 changes: 4 additions & 2 deletions frontend/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@ import { NavBar } from "@/lib/components/NavBar";
import { TrackingWrapper } from "@/lib/components/TrackingWrapper";
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
import { useSupabase } from "@/lib/context/SupabaseProvider";
import '../lib/config/LocaleConfig/i18n'
import { UpdateMetadata } from "@/lib/helpers/updateMetadata";
import "../lib/config/LocaleConfig/i18n";

// This wrapper is used to make effect calls at a high level in app rendering.
export const App = ({ children }: PropsWithChildren): JSX.Element => {
const { fetchAllBrains, fetchAndSetActiveBrain } = useBrainContext();
const { fetchAllBrains, fetchAndSetActiveBrain, fetchPublicPrompts } =
useBrainContext();
const { session } = useSupabase();

useEffect(() => {
void fetchAllBrains();
void fetchAndSetActiveBrain();
void fetchPublicPrompts();
}, [session?.user]);

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"use client";

import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";

import { MentionInput } from "./components";
import { MentionItem } from "./components/MentionItem";

type ChatBarProps = {
onSubmit: () => void;
Expand All @@ -13,11 +16,36 @@ export const ChatBar = ({
setMessage,
message,
}: ChatBarProps): JSX.Element => {
const { currentBrain, setCurrentBrainId, currentPrompt, setCurrentPromptId } =
useBrainContext();

return (
<MentionInput
message={message}
setMessage={setMessage}
onSubmit={onSubmit}
/>
<div className="flex flex-row flex-1 w-full item-start">
{currentBrain !== undefined && (
<MentionItem
text={currentBrain.name}
onRemove={() => {
setCurrentBrainId(null);
}}
trigger={"@"}
/>
)}
{currentPrompt !== undefined && (
<MentionItem
text={currentPrompt.title}
onRemove={() => {
setCurrentPromptId(null);
}}
trigger={"#"}
/>
)}
<div className="flex-1">
<MentionInput
message={message}
setMessage={setMessage}
onSubmit={onSubmit}
/>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
import Editor from "@draft-js-plugins/editor";
import { ReactElement } from "react";
import { PopoverProps } from "@draft-js-plugins/mention/lib/MentionSuggestions/Popover";
import { ComponentType, ReactElement } from "react";
import { useTranslation } from "react-i18next";

import "@draft-js-plugins/mention/lib/plugin.css";
import "draft-js/dist/Draft.css";

import { MentionTriggerType } from "@/app/chat/[chatId]/components/ActionsBar/types";

import { BrainSuggestionsContainer } from "./components/BrainSuggestionsContainer";
import { PromptSuggestionsContainer } from "./components/PromptSuggestionsContainer";
import { SuggestionRow } from "./components/SuggestionRow";
import { SuggestionsContainer } from "./components/SuggestionsContainer";
import { useMentionInput } from "./hooks/useMentionInput";

type MentionInputProps = {
onSubmit: () => void;
setMessage: (text: string) => void;
message: string;
};

const triggerToSuggestionsContainer: Record<
MentionTriggerType,
ComponentType<PopoverProps>
> = {
"@": BrainSuggestionsContainer,
"#": PromptSuggestionsContainer,
};

export const MentionInput = ({
onSubmit,
setMessage,
Expand All @@ -24,13 +37,14 @@ export const MentionInput = ({
MentionSuggestions,
keyBindingFn,
editorState,
onOpenChange,
setOpen,
onSearchChange,
open,
plugins,
suggestions,
onAddMention,
handleEditorChange,
currentTrigger,
} = useMentionInput({
message,
onSubmit,
Expand All @@ -50,15 +64,24 @@ export const MentionInput = ({
placeholder={t("actions_bar_placeholder")}
keyBindingFn={keyBindingFn}
/>
<MentionSuggestions
open={open}
onOpenChange={onOpenChange}
suggestions={suggestions}
onSearchChange={onSearchChange}
popoverContainer={SuggestionsContainer}
onAddMention={onAddMention}
entryComponent={SuggestionRow}
/>
<div
style={{
// `open` should be directly passed to the MentionSuggestions component.
// However, it is not working as expected since we are not able to click on button in custom suggestion renderer.
// So, we are using this hack to make it work.
visibility: open ? "visible" : "hidden",
}}
>
<MentionSuggestions
open
onOpenChange={setOpen}
suggestions={suggestions}
onSearchChange={onSearchChange}
popoverContainer={triggerToSuggestionsContainer[currentTrigger]}
onAddMention={onAddMention}
entryComponent={SuggestionRow}
/>
</div>
</div>
);
};

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Link from "next/link";
import { useTranslation } from "react-i18next";
import { MdAdd } from "react-icons/md";

export const AddNewPromptButton = (): JSX.Element => {
const { t } = useTranslation(["chat"]);

return (
<Link
href={"/brains-management"}
className="flex px-5 py-3 text-sm decoration-none text-center w-full justify-between items-center"
>
{t("new_prompt")}
<MdAdd />
</Link>
);
};
Original file line number Diff line number Diff line change
@@ -1,23 +1,8 @@
type BrainSuggestionProps = {
content: string;
id: string;
};
export const BrainSuggestion = ({
content,
id,
}: BrainSuggestionProps): JSX.Element => {
//TODO: use this id for ShareBrain component
console.log({ id });

return (
<div className="relative flex group items-center">
<div
className={
"flex flex-1 items-center gap-2 w-full text-left px-5 py-2 text-sm leading-5 text-gray-900 dark:text-gray-300 group-hover:bg-gray-100 dark:group-hover:bg-gray-700 group-focus:bg-gray-100 dark:group-focus:bg-gray-700 group-focus:outline-none transition-colors"
}
>
<span className="flex-1">{content}</span>
</div>
</div>
);
return <span>{content}</span>;
};
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { Popover } from "@draft-js-plugins/mention";
import { PopoverProps } from "@draft-js-plugins/mention/lib/MentionSuggestions/Popover";

export const SuggestionsContainer = ({
import { AddBrainModal } from "@/lib/components/AddBrainModal";

export const BrainSuggestionsContainer = ({
children,
...popoverProps
}: PopoverProps): JSX.Element => (
<Popover {...popoverProps}>
<div
style={{
maxWidth: "max-content",
width: "max-content",
}}
className="bg-white dark:bg-black border border-black/10 dark:border-white/25 rounded-md shadow-md overflow-y-auto"
>
{children}
<AddBrainModal />
</div>
</Popover>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type PromptSuggestionProps = {
content: string;
};
export const PromptSuggestion = ({
content,
}: PromptSuggestionProps): JSX.Element => {
return (
<div className="flex flex-1 flex-row gap-2 w-full text-left px-5 py-2 text-sm text-gray-900 dark:text-gray-300">
<div className="flex flex-1">
<span>{content}</span>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Popover } from "@draft-js-plugins/mention";
import { PopoverProps } from "@draft-js-plugins/mention/lib/MentionSuggestions/Popover";

import { AddNewPromptButton } from "./AddNewPromptButton";

export const PromptSuggestionsContainer = ({
children,
...popoverProps
}: PopoverProps): JSX.Element => (
<Popover {...popoverProps}>
<div
style={{
width: "max-content",
}}
className="bg-white dark:bg-black border border-black/10 dark:border-white/25 rounded-md shadow-md overflow-y-auto"
>
{children}
<AddNewPromptButton />
</div>
</Popover>
);
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
import { EntryComponentProps } from "@draft-js-plugins/mention/lib/MentionSuggestions/Entry/Entry";
import { UUID } from "crypto";

import { MentionTriggerType } from "@/app/chat/[chatId]/components/ActionsBar/types";
import { ShareBrain } from "@/lib/components/ShareBrain";

import { BrainSuggestion } from "./BrainSuggestion";
import { PromptSuggestion } from "./PromptSuggestion";

export const SuggestionRow = ({
mention,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
className,
...otherProps
}: EntryComponentProps): JSX.Element => (
<div {...otherProps}>
<BrainSuggestion id={mention.id as string} content={mention.name} />
</div>
);
}: EntryComponentProps): JSX.Element => {
if ((mention.trigger as MentionTriggerType) === "@") {
return (
<div {...otherProps}>
<div className="relative flex group px-4">
<BrainSuggestion content={mention.name} />
<div className="absolute right-0 flex flex-row">
<ShareBrain brainId={mention.id as UUID} />
</div>
</div>
</div>
);
}

return (
<div {...otherProps}>
<PromptSuggestion content={mention.name} />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export * from "./AddNewBrainButton";
export * from "./AddNewPromptButton";
export * from "./BrainSuggestion";
export * from "./BrainSuggestionsContainer";
export * from "./PromptSuggestion";
export * from "./SuggestionRow";
Original file line number Diff line number Diff line change
@@ -1,31 +1,13 @@
import createMentionPlugin from "@draft-js-plugins/mention";
import { useMemo } from "react";

import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";

import { BrainMentionItem } from "../../../BrainMentionItem";

interface MentionPluginProps {
removeMention: (entityKeyToRemove: string) => void;
}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const useMentionPlugin = (props: MentionPluginProps) => {
const { removeMention } = props;
const { setCurrentBrainId } = useBrainContext();

export const useMentionPlugin = () => {
const { MentionSuggestions, plugins } = useMemo(() => {
const mentionPlugin = createMentionPlugin({
mentionComponent: ({ entityKey, mention: { name } }) => (
<BrainMentionItem
text={name}
onRemove={() => {
setCurrentBrainId(null);
removeMention(entityKey);
}}
/>
),
mentionComponent: () => <span />,

mentionTrigger: ["@", "#"],
popperOptions: {
placement: "top-end",
modifiers: [
Expand Down
Loading
Loading