mirror of
https://github.com/deiucanta/chatpad.git
synced 2026-03-11 09:04:31 +00:00
feat: chat settings
This commit is contained in:
parent
0d265e51ff
commit
e22f50bfc4
4 changed files with 154 additions and 17 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ export function ChatRoute() {
|
|||
})
|
||||
|
||||
const updates = {
|
||||
prompt: prompt.key,
|
||||
writingInstructions: prompt.content,
|
||||
writingCharacter: prompt.writingCharacter,
|
||||
writingTone: prompt.writingTone,
|
||||
|
|
|
|||
Loading…
Reference in a new issue