diff --git a/bun.lockb b/bun.lockb index 4cc67c8..484185f 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 955c3b6..d70d36a 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-icons": "1.3.0", "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-portal": "^1.1.2", "@radix-ui/react-scroll-area": "^1.0.3", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-slot": "^1.0.2", diff --git a/src/components/databrowser/components/add-key-modal.tsx b/src/components/databrowser/components/add-key-modal.tsx index 02c49e4..a3658cd 100644 --- a/src/components/databrowser/components/add-key-modal.tsx +++ b/src/components/databrowser/components/add-key-modal.tsx @@ -23,7 +23,6 @@ import { SelectValue, } from "@/components/ui/select" import { Spinner } from "@/components/ui/spinner" -import { toast } from "@/components/ui/use-toast" import { TypeTag } from "@/components/databrowser/components/type-tag" import { useAddKey } from "@/components/databrowser/hooks/use-add-key" @@ -43,23 +42,16 @@ export function AddKeyModal() { }) const onSubmit = handleSubmit(async ({ key, type }) => { - try { - await addKey({ key, type }) - setSelectedKey(key) - setOpen(false) - setTimeout(() => { - window.document.querySelector(`[data-key="${key}"]`)?.scrollIntoView({ - behavior: "smooth", - block: "start", - inline: "nearest", - }) - }, 100) - } catch (error) { - toast({ - description: error instanceof Error ? error.message : "An error occurred", - variant: "destructive", + await addKey({ key, type }) + setSelectedKey(key) + setOpen(false) + setTimeout(() => { + window.document.querySelector(`[data-key="${key}"]`)?.scrollIntoView({ + behavior: "smooth", + block: "start", + inline: "nearest", }) - } + }, 100) }) return ( diff --git a/src/components/databrowser/components/display/display-list-edit.tsx b/src/components/databrowser/components/display/display-list-edit.tsx index ec908a1..b772776 100644 --- a/src/components/databrowser/components/display/display-list-edit.tsx +++ b/src/components/databrowser/components/display/display-list-edit.tsx @@ -65,14 +65,24 @@ const ListEditForm = ({
{type !== "list" && ( - + )} {type === "zset" ? ( ) : ( type !== "set" && ( - + ) )}
@@ -131,11 +141,13 @@ const FormItem = ({ name, label, height, + readOnly, }: { name: string label: string isNumber?: boolean height?: number + readOnly?: boolean }) => { const form = useFormContext() const { editor, selector } = useField({ @@ -143,6 +155,7 @@ const FormItem = ({ form, height: height, showCopyButton: true, + readOnly, }) return ( diff --git a/src/components/databrowser/components/display/input/custom-editor.tsx b/src/components/databrowser/components/display/input/custom-editor.tsx index 554f4c4..401d3f4 100644 --- a/src/components/databrowser/components/display/input/custom-editor.tsx +++ b/src/components/databrowser/components/display/input/custom-editor.tsx @@ -10,12 +10,14 @@ export const CustomEditor = ({ onChange, height, showCopyButton, + readOnly, }: { language: string value: string onChange: (value: string) => void height?: number showCopyButton?: boolean + readOnly?: boolean }) => { const monaco = useMonaco() const editorRef = useRef() @@ -48,6 +50,7 @@ export const CustomEditor = ({ }} defaultLanguage={language} options={{ + readOnly: readOnly, wordWrap: "on", overviewRulerBorder: false, overviewRulerLanes: 0, diff --git a/src/components/databrowser/components/display/input/use-field.tsx b/src/components/databrowser/components/display/input/use-field.tsx index 49d12d7..3a143d5 100644 --- a/src/components/databrowser/components/display/input/use-field.tsx +++ b/src/components/databrowser/components/display/input/use-field.tsx @@ -9,11 +9,13 @@ export const useField = ({ form, height, showCopyButton, + readOnly, }: { name: string form: UseFormReturn height?: number showCopyButton?: boolean + readOnly?: boolean }) => { const { field, fieldState } = useController>({ name, @@ -60,6 +62,7 @@ export const useField = ({ onChange={field.onChange} height={height} showCopyButton={showCopyButton} + readOnly={readOnly} /> ), diff --git a/src/components/databrowser/hooks/use-add-key.ts b/src/components/databrowser/hooks/use-add-key.ts index daf72b4..a69e946 100644 --- a/src/components/databrowser/hooks/use-add-key.ts +++ b/src/components/databrowser/hooks/use-add-key.ts @@ -13,6 +13,8 @@ export const useAddKey = () => { const mutation = useMutation({ mutationFn: async ({ key, type }: { key: string; type: DataType }) => { + if (await redis.exists(key)) throw new Error(`Key "${key}" already exists`) + switch (type) { case "set": { await redis.sadd(key, "value") diff --git a/src/components/databrowser/index.tsx b/src/components/databrowser/index.tsx index 4bc6665..c48e0c6 100644 --- a/src/components/databrowser/index.tsx +++ b/src/components/databrowser/index.tsx @@ -1,6 +1,6 @@ import "@/globals.css" -import { useMemo } from "react" +import { useEffect, useMemo } from "react" import { DatabrowserProvider, type RedisCredentials } from "@/store" import { TooltipProvider } from "@radix-ui/react-tooltip" import { IconDotsVertical } from "@tabler/icons-react" @@ -17,6 +17,10 @@ import { KeysProvider } from "./hooks/use-keys" export const RedisBrowser = ({ token, url }: RedisCredentials) => { const credentials = useMemo(() => ({ token, url }), [token, url]) + useEffect(() => { + queryClient.resetQueries() + }, [credentials.url]) + return ( diff --git a/src/components/ui/toaster.tsx b/src/components/ui/toaster.tsx index 6d643e7..e780c49 100644 --- a/src/components/ui/toaster.tsx +++ b/src/components/ui/toaster.tsx @@ -1,3 +1,6 @@ +import { Portal } from "@radix-ui/react-portal" + +import { portalRoot } from "@/lib/portal-root" import { Toast, ToastClose, @@ -12,18 +15,20 @@ export function Toaster() { const { toasts } = useToast() return ( - - {toasts.map(({ id, title, description, action, ...props }) => ( - -
- {title && {title}} - {description && {description}} -
- {action} - -
- ))} - -
+ + + {toasts.map(({ id, title, description, action, ...props }) => ( + +
+ {title && {title}} + {description && {description}} +
+ {action} + +
+ ))} + +
+
) }