From 3a8d197437868ca10d294f0174afa013f138ec33 Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Sat, 5 Oct 2024 16:35:47 +0000 Subject: feature(web): Change the settings page to be tabbed --- .../components/dashboard/settings/AISettings.tsx | 325 +++++++++++++++++++++ .../components/dashboard/settings/ImportExport.tsx | 14 +- .../components/dashboard/settings/UserDetails.tsx | 2 +- 3 files changed, 330 insertions(+), 11 deletions(-) create mode 100644 apps/web/components/dashboard/settings/AISettings.tsx (limited to 'apps/web/components/dashboard/settings') diff --git a/apps/web/components/dashboard/settings/AISettings.tsx b/apps/web/components/dashboard/settings/AISettings.tsx new file mode 100644 index 00000000..12f656ba --- /dev/null +++ b/apps/web/components/dashboard/settings/AISettings.tsx @@ -0,0 +1,325 @@ +"use client"; + +import { ActionButton } from "@/components/ui/action-button"; +import { + Form, + FormControl, + FormField, + FormItem, + FormMessage, +} from "@/components/ui/form"; +import { FullPageSpinner } from "@/components/ui/full-page-spinner"; +import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { toast } from "@/components/ui/use-toast"; +import { useClientConfig } from "@/lib/clientConfig"; +import { api } from "@/lib/trpc"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { Plus, Save, Trash2 } from "lucide-react"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; + +import { buildImagePrompt, buildTextPrompt } from "@hoarder/shared/prompts"; +import { + zNewPromptSchema, + ZPrompt, + zUpdatePromptSchema, +} from "@hoarder/shared/types/prompts"; + +export function PromptEditor() { + const apiUtils = api.useUtils(); + + const form = useForm>({ + resolver: zodResolver(zNewPromptSchema), + defaultValues: { + text: "", + appliesTo: "all", + }, + }); + + const { mutateAsync: createPrompt, isPending: isCreating } = + api.prompts.create.useMutation({ + onSuccess: () => { + toast({ + description: "Prompt has been created!", + }); + apiUtils.prompts.list.invalidate(); + }, + }); + + return ( +
+ { + await createPrompt(value); + form.resetField("text"); + })} + > + { + return ( + + + + + + + ); + }} + /> + + { + return ( + + + + + + + ); + }} + /> + + + Add + + + + ); +} + +export function PromptRow({ prompt }: { prompt: ZPrompt }) { + const apiUtils = api.useUtils(); + const { mutateAsync: updatePrompt, isPending: isUpdating } = + api.prompts.update.useMutation({ + onSuccess: () => { + toast({ + description: "Prompt has been updated!", + }); + apiUtils.prompts.list.invalidate(); + }, + }); + const { mutate: deletePrompt, isPending: isDeleting } = + api.prompts.delete.useMutation({ + onSuccess: () => { + toast({ + description: "Prompt has been deleted!", + }); + apiUtils.prompts.list.invalidate(); + }, + }); + + const form = useForm>({ + resolver: zodResolver(zUpdatePromptSchema), + defaultValues: { + promptId: prompt.id, + text: prompt.text, + appliesTo: prompt.appliesTo, + }, + }); + + return ( +
+ { + await updatePrompt(value); + })} + > + { + return ( + + + + + + + ); + }} + /> + { + return ( + + + + + + + ); + }} + /> + + { + return ( + + + + + + + ); + }} + /> + + + Save + + deletePrompt({ promptId: prompt.id })} + className="items-center" + type="button" + > + + Delete + + + + ); +} + +export function TaggingRules() { + const { data: prompts, isLoading } = api.prompts.list.useQuery(); + + return ( +
+
Tagging Rules
+

+ Prompts that you add here will be included as rules to the model during + tag generation. You can view the final prompts in the prompt preview + section. +

+ {isLoading && } + {prompts && prompts.length == 0 && ( +

+ You don't have any custom prompts yet. +

+ )} + {prompts && + prompts.map((prompt) => )} + +
+ ); +} + +export function PromptDemo() { + const { data: prompts } = api.prompts.list.useQuery(); + const clientConfig = useClientConfig(); + return ( +
+
+ Prompt Preview +
+

Text Prompt

+ + {buildTextPrompt( + clientConfig.inference.inferredTagLang, + (prompts ?? []) + .filter((p) => p.appliesTo == "text" || p.appliesTo == "all") + .map((p) => p.text), + "\n\n", + ).trim()} + +

Image Prompt

+ + {buildImagePrompt( + clientConfig.inference.inferredTagLang, + (prompts ?? []) + .filter((p) => p.appliesTo == "images" || p.appliesTo == "all") + .map((p) => p.text), + ).trim()} + +
+ ); +} + +export default function AISettings() { + return ( + <> +
+
+
+ AI Settings +
+ +
+
+
+ +
+ + ); +} diff --git a/apps/web/components/dashboard/settings/ImportExport.tsx b/apps/web/components/dashboard/settings/ImportExport.tsx index 25b2073c..2bc930f7 100644 --- a/apps/web/components/dashboard/settings/ImportExport.tsx +++ b/apps/web/components/dashboard/settings/ImportExport.tsx @@ -187,7 +187,7 @@ export function ImportExportRow() { return (
-
+
-
-
- Import / Export Bookmarks -
-
-
- -
+
+

Import / Export Bookmarks

+
); } diff --git a/apps/web/components/dashboard/settings/UserDetails.tsx b/apps/web/components/dashboard/settings/UserDetails.tsx index 3915782b..471a6e09 100644 --- a/apps/web/components/dashboard/settings/UserDetails.tsx +++ b/apps/web/components/dashboard/settings/UserDetails.tsx @@ -16,7 +16,7 @@ export default async function UserDetails() { ]; return ( -
+
Basic Details
-- cgit v1.2.3-70-g09d2