Skip to content

Commit

Permalink
#93 Adding placeholders for conversation starters
Browse files Browse the repository at this point in the history
  • Loading branch information
santthosh committed Jun 27, 2024
1 parent 5e491ee commit e6f171e
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 15 deletions.
36 changes: 22 additions & 14 deletions src/app/assistants/[id]/chat/useChatContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,29 @@ export const useChatContext = () => {

useEffect(() => {
if (reset) {
setMessages([
{
created_at: Date.now() / 1000,
role: 'assistant',
content: [
{
type: 'text',
text: {
value: getInitialPrompt(assistant),
annotations: [],
let initialPrompt = getInitialPrompt(assistant);
let initialMessages:any = [];

// Hide the initial prompt if there is none set
if (initialPrompt && initialPrompt.trim()) {
initialMessages = [
{
created_at: Date.now() / 1000,
role: 'assistant',
content: [
{
type: 'text',
text: {
value: getInitialPrompt(assistant),
annotations: [],
},
},
},
],
},
]);
],
},
];
}

setMessages(initialMessages);
setReset(false);
}
}, [assistant, reset]);
Expand Down
2 changes: 1 addition & 1 deletion src/app/assistants/[id]/customize/DebounceInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const DebouncedInput: React.FC<DebouncedInputProps> = (
<div className='grid grid-cols-6'>
<TextInput
value={text}
sizing='lg'
sizing='md'
className='col-span-5'
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setText(e.target.value)
Expand Down
62 changes: 62 additions & 0 deletions src/app/assistants/[id]/customize/DebounceInputWithActions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { useState, useEffect } from 'react';
import { useDebounce } from '@/app/utils/useDebounce';
import { Button, Spinner, TextInput } from 'flowbite-react';
import { HiCheck, HiTrash } from 'react-icons/hi';

export interface DebouncedInputWithActionsProps {
value?: string;
placeholder?: string;
onDebounceTextChange?: (text: string) => void;
onDebounceTextDelete?: (text: string) => void;
}

export const DebouncedInputWithActions: React.FC<
DebouncedInputWithActionsProps
> = (props: DebouncedInputWithActionsProps) => {
const [text, setText] = useState<string>(props.value ? props.value : '');
const [loading, setLoading] = useState<boolean>(false);
const debouncedText = useDebounce<string>(text, 300); // 300ms delay

useEffect(() => {
// This function will run after debouncedText changes and the 300ms delay passes
if (debouncedText && debouncedText !== props.value) {
setLoading(true);
props.onDebounceTextChange
? props.onDebounceTextChange(debouncedText)
: null;
setLoading(false);
}
}, [debouncedText]); // Only re-run if debouncedText changes

return (
<div className='grid grid-cols-12'>
<TextInput
value={text}
sizing='md'
className='col-span-10'
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setText(e.target.value)
}
placeholder={props.placeholder ? props.placeholder : ''}
/>
<div className='col-span-1 ml-3 mt-2 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-green-100 text-green-500 dark:bg-green-800 dark:text-green-200'>
{loading ? (
<Spinner aria-label='saving..' size='xs' />
) : (
<HiCheck className='h-5 w-5' />
)}
</div>
<Button
size='sm'
color={'gray'}
disabled={!prompt}
onClick={props.onDebounceTextDelete as any}
className={'col-span-1 border-0 pb-1'}
>
<HiTrash className='h-5 w-5' color={'gray'} />
</Button>
</div>
);
};

export default DebouncedInputWithActions;
111 changes: 111 additions & 0 deletions src/app/assistants/[id]/customize/EditConversationStarters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { Button, Label, Modal, TextInput } from 'flowbite-react';
import React, { useContext, useEffect, useState } from 'react';
import DebouncedInput from '@/app/assistants/[id]/customize/DebounceInput';
import { getInitialConversationStarter } from '@/app/utils/assistant';
import AssistantContext from '@/app/assistants/[id]/AssistantContext';
import { ulid } from 'ulidx';
import { HiCheck, HiPlus, HiTrash } from 'react-icons/hi';
import DebouncedInputWithActions from '@/app/assistants/[id]/customize/DebounceInputWithActions';

export interface ConversationStarter {
id: string;
prompt: string;
}

export const EditConversationStarters: React.FC = () => {
const { assistant, setAssistant } = useContext(AssistantContext);

const [conversationStarters, setConversationStarters] = useState<
ConversationStarter[]
>([]);
const [saveConversationStarter, setSaveConversationStarter] =
useState<ConversationStarter | null>(null);
const [dirtyConversationStarter, setdirtyConversationStarter] =
useState<ConversationStarter | null>(null);
const [selectedConversationStarter, setSelectedConversationStarter] =
useState<ConversationStarter | null>(null);
const [deleteConversationStarter, setDeleteConversationStarter] =
useState<ConversationStarter | null>(null);

useEffect(() => {
console.log('changed');
console.log(conversationStarters);
}, [conversationStarters]);

useEffect(() => {}, [dirtyConversationStarter]);

useEffect(() => {}, [saveConversationStarter]);

useEffect(() => {
if (deleteConversationStarter) {
// TODO: Remove through API
const indexToRemove = conversationStarters.findIndex(
(key) => key.id === deleteConversationStarter.id
);
if (indexToRemove !== -1) {
conversationStarters.splice(indexToRemove, 1);
}
setConversationStarters(conversationStarters);
setDeleteConversationStarter(null);
}
}, [deleteConversationStarter]);

const handleAddConversationStarter = function () {
setConversationStarters([
...conversationStarters,
{ id: ulid(), prompt: '' },
]);
};

const handleSaveConversationStarter = function () {};

const onConversationStarterChange = function (event: any) {
conversationStarters.forEach((iterationConversationStarter) => {});
};

const handleDeleteConversationStarter = function (id: string) {
conversationStarters.forEach((iterationConversationStarter) => {
if (iterationConversationStarter.id === id) {
console.log(iterationConversationStarter);
setDeleteConversationStarter(iterationConversationStarter);
}
});
};

return (
<div className={'stack space-y-1'}>
<div id='conversationStarters' className='grid max-w-4xl'>
<div className='mb-2 block'>
<Label value='Conversation Starters for Assistant' />
</div>
{conversationStarters && conversationStarters.length ? (
conversationStarters.map((starter: any, index: number) => (
<div key={index} className={'overflow-y-auto'}>
<div className='gap-2 pt-5'>
<DebouncedInputWithActions
onDebounceTextChange={onConversationStarterChange as any}
onDebounceTextDelete={() => {
handleDeleteConversationStarter(starter.id);
}}
value={starter.prompt}
/>
</div>
</div>
))
) : (
<></>
)}
<div className='flex justify-center pt-4'>
<Button
size={'md'}
color={'gray'}
onClick={handleAddConversationStarter}
>
<HiPlus className='mr-2 h-5 w-5' />
Add
</Button>
</div>
</div>
</div>
);
};
6 changes: 6 additions & 0 deletions src/app/assistants/[id]/customize/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { EditInitialPrompt } from '@/app/assistants/[id]/customize/EditInitialPr
import { EditMessageLabel } from '@/app/assistants/[id]/customize/EditMessageLabel';
import ChatPopupFrame from '@/app/assistants/[id]/chat/ChatPopupFrame';
import ChatPage from '@/app/assistants/[id]/chat/ChatPage';
import { EditConversationStarters } from '@/app/assistants/[id]/customize/EditConversationStarters';

export default function Customize() {
const { assistant, setAssistant } = useContext(AssistantContext);
Expand Down Expand Up @@ -43,6 +44,11 @@ export default function Customize() {
<ThemeSelections />
</Table.Cell>
</Table.Row>
<Table.Row className='bg-white dark:border-gray-700 dark:bg-gray-800'>
<Table.Cell>
<EditConversationStarters />
</Table.Cell>
</Table.Row>
<Table.Row className='bg-white dark:border-gray-700 dark:bg-gray-800'>
<Table.Cell>
<EditInitialPrompt />
Expand Down
1 change: 1 addition & 0 deletions src/app/types/assistant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface AssistantTheme {
secondaryTextColor?: string;
initialPrompt?: string;
messageLabel?: string;
conversationStarters?: string[];
}

export interface Assistant {
Expand Down
8 changes: 8 additions & 0 deletions src/app/utils/assistant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,11 @@ export function getInputMessageLabel(assistant: Assistant) {

return 'Your message...';
}

export function getInitialConversationStarter(assistant: Assistant) {
if (assistant.theme && assistant.theme.conversationStarters) {
return assistant.theme.conversationStarters;
}

return [];
}

0 comments on commit e6f171e

Please sign in to comment.