feat: chat settings

This commit is contained in:
BetaHuhn 2023-08-30 16:21:40 +02:00
parent 0d265e51ff
commit e22f50bfc4
4 changed files with 154 additions and 17 deletions

View file

@ -1,9 +1,10 @@
import { Button, Modal, Stack, TextInput } from "@mantine/core";
import { Button, Modal, Select, SimpleGrid, Stack, TextInput, Textarea } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { notifications } from "@mantine/notifications";
import { cloneElement, ReactElement, useEffect, useState } from "react";
import { Chat, detaDB } from "../db";
import { useChat, useChats } from "../hooks/contexts";
import { useChat, useChats, usePrompts } from "../hooks/contexts";
import { config } from "../utils/config";
export function EditChatModal({
chat,
@ -15,35 +16,91 @@ export function EditChatModal({
const [opened, { open, close }] = useDisclosure(false);
const [submitting, setSubmitting] = useState(false);
const { prompts } = usePrompts()
const { setChats } = useChats()
const { setChat } = useChat()
const [promptKey, setPromptKey] = useState<string | null>(null);
const [writingInstructions, setWritingInstructions] = useState<string | null>(null);
const [writingCharacter, setWritingCharacter] = useState<string | null>(null);
const [writingTone, setWritingTone] = useState<string | null>(null);
const [writingStyle, setWritingStyle] = useState<string | null>(null);
const [writingFormat, setWritingFormat] = useState<string | null>(null);
const [value, setValue] = useState("");
useEffect(() => {
setValue(chat?.description ?? "");
if (chat.prompt) {
setPromptKey(chat.prompt)
} else {
setPromptKey(null)
if (chat.writingInstructions) setWritingInstructions(chat.writingInstructions)
if (chat.writingCharacter) setWritingCharacter(chat.writingCharacter)
if (chat.writingTone) setWritingTone(chat.writingTone)
if (chat.writingStyle) setWritingStyle(chat.writingStyle)
if (chat.writingFormat) setWritingFormat(chat.writingFormat)
}
}, [chat]);
useEffect(() => {
const prompt = prompts.find(prompt => prompt.key === promptKey)
if (prompt) {
setWritingInstructions(prompt.content ?? null)
setWritingCharacter(prompt.writingCharacter ?? null)
setWritingTone(prompt.writingTone ?? null)
setWritingStyle(prompt.writingStyle ?? null)
setWritingFormat(prompt.writingFormat ?? null)
}
}, [promptKey]);
useEffect(() => {
const prompt = prompts.find(prompt => prompt.key === promptKey)
if (prompt) {
// compare current values with saved values and update if different
if (prompt.content !== writingInstructions
|| prompt.writingCharacter !== writingCharacter
|| prompt.writingTone !== writingTone
|| prompt.writingStyle !== writingStyle
|| prompt.writingFormat !== writingFormat
) {
setPromptKey(null)
}
}
}, [writingInstructions, writingCharacter, writingFormat, writingStyle, writingTone]);
return (
<>
{cloneElement(children, { onClick: open })}
<Modal opened={opened} onClose={close} title="Edit Chat" withinPortal>
<Modal opened={opened} onClose={close} title="Edit Chat" withinPortal size="lg">
<form
onSubmit={async (event) => {
try {
setSubmitting(true);
event.preventDefault();
await detaDB.chats.update({ description: value }, chat.key);
const updates: Partial<Chat> = {
description: value,
prompt: promptKey,
writingInstructions,
writingCharacter,
writingFormat,
writingStyle,
writingTone
}
await detaDB.chats.update(updates, chat.key);
setChats(current => (current || []).map(item => {
if (item.key === chat.key) {
return { ...item, description: value };
return { ...item, ...updates };
}
return item;
}));
setChat(current => {
if (current?.key === chat.key) {
return { ...current, description: value };
return { ...current, ...updates };
}
return current;
@ -83,6 +140,72 @@ export function EditChatModal({
formNoValidate
data-autofocus
/>
<Select
value={promptKey}
onChange={setPromptKey}
data={prompts.map(prompt => ({ value: prompt.key, label: prompt.title }))}
placeholder="Select Prompt"
variant="filled"
searchable
clearable
/>
<SimpleGrid
spacing="xs"
breakpoints={[
{ minWidth: "sm", cols: 4 },
{ maxWidth: "sm", cols: 2 },
]}
>
<Select
value={writingCharacter}
onChange={setWritingCharacter}
data={config.writingCharacters}
placeholder="Character"
variant="filled"
searchable
clearable
sx={{ flex: 1 }}
/>
<Select
value={writingTone}
onChange={setWritingTone}
data={config.writingTones}
placeholder="Tone"
variant="filled"
searchable
clearable
sx={{ flex: 1 }}
/>
<Select
value={writingStyle}
onChange={setWritingStyle}
data={config.writingStyles}
placeholder="Style"
variant="filled"
searchable
clearable
sx={{ flex: 1 }}
/>
<Select
value={writingFormat}
onChange={setWritingFormat}
data={config.writingFormats}
placeholder="Format"
variant="filled"
searchable
clearable
sx={{ flex: 1 }}
/>
</SimpleGrid>
<Textarea
label="Instructions"
placeholder="Further instructions..."
autosize
minRows={5}
maxRows={10}
value={writingInstructions || ''}
onChange={(event) => setWritingInstructions(event.currentTarget.value)}
/>
<Button type="submit" loading={submitting}>
Save
</Button>

View file

@ -16,6 +16,7 @@ import {
useMantineTheme,
} from "@mantine/core";
import {
IconAdjustments,
IconPlus,
IconSearch,
IconSettings,
@ -32,6 +33,7 @@ import { Prompts } from "./Prompts";
import { SettingsModal } from "./SettingsModal";
import { config } from "../utils/config";
import { ChatContext, ChatsContext, PromptsContext, SettingsContext } from "../hooks/contexts";
import { EditChatModal } from "./EditChatModal";
declare global {
interface Window {
@ -343,16 +345,27 @@ export function Layout() {
header={
chat ? (
<Header height={60} p="xs" className="app-region-drag">
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "100%",
}}
>
{chat.description}
</div>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div></div>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "100%",
}}
>
{chat.description}
</div>
<EditChatModal chat={chat}>
<Tooltip label="Chat Settings">
<ActionIcon size="xl">
<IconAdjustments size={20} />
</ActionIcon>
</Tooltip>
</EditChatModal>
</Box>
</Header>
) : undefined
}

View file

@ -6,7 +6,7 @@ export interface Chat {
key: string;
description: string;
totalTokens: number;
prompt?: string;
prompt?: string | null;
writingInstructions?: string | null;
writingCharacter?: string | null;
writingTone?: string | null;

View file

@ -123,6 +123,7 @@ export function ChatRoute() {
})
const updates = {
prompt: prompt.key,
writingInstructions: prompt.content,
writingCharacter: prompt.writingCharacter,
writingTone: prompt.writingTone,