Skip to content

DX-1802: apply refresh to simple keys #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 14, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ export const DisplayHeader = ({
const { setSelectedListItem } = useDatabrowserStore()

const handleAddItem = () => {
setSelectedListItem({ key: type === "stream" ? "*" : "", value: "", isNew: true })
setSelectedListItem({ key: type === "stream" ? "*" : "", isNew: true })
}

return (
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useEffect } from "react"
import type { SelectedItem } from "@/store"
import { useDatabrowserStore } from "@/store"
import type { ListDataType } from "@/types"
@@ -7,6 +8,7 @@ import { Button } from "@/components/ui/button"
import { Spinner } from "@/components/ui/spinner"
import { SimpleTooltip } from "@/components/ui/tooltip"

import { useFetchListItems } from "../../hooks"
import { useEditListItem } from "../../hooks/use-edit-list-item"
import { headerLabels } from "./display-list"
import { useField } from "./input/use-field"
@@ -30,19 +32,41 @@ export const ListEditDisplay = ({
const ListEditForm = ({
type,
dataKey,
item: { key: itemKey, value: itemValue, isNew },
item: { key: itemKey, isNew },
}: {
type: ListDataType
dataKey: string
item: SelectedItem
}) => {
const query = useFetchListItems({
type,
dataKey,
})
// Search in pages for item value
const findValue = () => {
for (const page of query.data?.pages ?? []) {
const item = page.keys.find((item) => item.key === itemKey)
// Check if item has a value property before returning it
if (item && "value" in item) return item.value as string
}
return
}
const itemValue = findValue()

const form = useForm({
defaultValues: {
key: itemKey,
value: itemValue,
},
})

useEffect(() => {
form.reset({
key: itemKey,
value: itemValue,
})
}, [itemKey, itemValue])

const { mutateAsync: editItem, isPending } = useEditListItem()
const { setSelectedListItem } = useDatabrowserStore()

@@ -70,6 +94,7 @@ const ListEditForm = ({
name="key"
height={type === "set" ? 250 : 100}
label={keyLabel}
data={itemKey}
/>
)}

@@ -82,6 +107,7 @@ const ListEditForm = ({
name="value"
height={type === "list" ? 250 : 100}
label={valueLabel}
data={itemValue ?? ""}
/>
)
)}
@@ -142,12 +168,14 @@ const FormItem = ({
label,
height,
readOnly,
data,
}: {
name: string
label: string
isNumber?: boolean
height?: number
readOnly?: boolean
data: string
}) => {
const form = useFormContext()
const { editor, selector } = useField({
@@ -156,6 +184,7 @@ const FormItem = ({
height: height,
showCopyButton: true,
readOnly,
data,
})

return (
Original file line number Diff line number Diff line change
@@ -82,7 +82,7 @@ export const ListItems = ({
data-item-key={key}
data-item-value={value}
onClick={() => {
setSelectedListItem({ key, value })
setSelectedListItem({ key })
}}
className="h-10 border-b border-b-zinc-100 hover:bg-zinc-50"
>
Original file line number Diff line number Diff line change
@@ -45,20 +45,21 @@ const EditorDisplayForm = ({
const form = useForm({
defaultValues: { value: data },
})
const { editor, selector } = useField({ name: "value", form })

const { mutateAsync: setKey, isPending: isSettingKey } = useSetSimpleKey(dataKey, type)

// Updates default values after submit
useEffect(() => {
form.reset(
{ value: data },
{
keepValues: true,
keepValues: false,
}
)
}, [data])

const { editor, selector } = useField({ name: "value", form, data })

const { mutateAsync: setKey, isPending: isSettingKey } = useSetSimpleKey(dataKey, type)

const handleCancel = () => {
form.reset()
}
Original file line number Diff line number Diff line change
@@ -10,12 +10,14 @@ export const useField = ({
height,
showCopyButton,
readOnly,
data,
}: {
name: string
form: UseFormReturn<any>
height?: number
showCopyButton?: boolean
readOnly?: boolean
data: string
}) => {
const { field, fieldState } = useController<Record<string, string>>({
name,
@@ -26,16 +28,16 @@ export const useField = ({
checkIsValidJSON(field.value) ? "JSON" : "Text"
)

// Attempt to format JSON on initial load
// Attempt to format JSON everytime the underlying data changes
useEffect(() => {
if (!checkIsValidJSON(field.value)) {
if (!checkIsValidJSON(data)) {
return
}

form.setValue(name, formatJSON(field.value), {
form.setValue(name, formatJSON(data), {
shouldDirty: false,
})
}, [])
}, [data])

const handleTypeChange = (type: ContentType) => {
setContentType(type)
5 changes: 4 additions & 1 deletion src/components/databrowser/components/sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ import { queryClient } from "@/lib/clients"
import { Button } from "@/components/ui/button"
import { Spinner } from "@/components/ui/spinner"

import { FETCH_LIST_ITEMS_QUERY_KEY } from "../../hooks"
import { FETCH_LIST_ITEMS_QUERY_KEY, FETCH_SIMPLE_KEY_QUERY_KEY } from "../../hooks"
import { useKeys } from "../../hooks/use-keys"
import { AddKeyModal } from "../add-key-modal"
import { DisplayDbSize, FETCH_DB_SIZE_QUERY_KEY } from "./db-size"
@@ -32,6 +32,9 @@ export function Sidebar() {
queryClient.invalidateQueries({
queryKey: [FETCH_LIST_ITEMS_QUERY_KEY],
})
queryClient.invalidateQueries({
queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY],
})
queryClient.invalidateQueries({
queryKey: [FETCH_DB_SIZE_QUERY_KEY],
})
17 changes: 17 additions & 0 deletions src/components/databrowser/hooks/use-fetch-simple-key.tsx
Original file line number Diff line number Diff line change
@@ -19,9 +19,26 @@ export const useFetchSimpleKey = (dataKey: string, type: DataType) => {
else if (type === "json") result = (await redis.json.get(dataKey)) as string | null
else throw new Error(`Invalid type when fetching simple key: ${type}`)

if (type === "json" && result !== null)
result = JSON.stringify(sortObject(JSON.parse(result)))

if (result === null) deleteKeyCache(dataKey)

return result
},
})
}

// Add recursive key sorting to a JSON object
const sortObject = (obj: unknown): unknown => {
if (typeof obj !== "object" || obj === null) return obj
return Object.fromEntries(
Object.entries(obj)
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([key, value]) =>
typeof value === "object" && !Array.isArray(value) && value !== null
? [key, sortObject(value)]
: [key, value]
)
)
}
3 changes: 1 addition & 2 deletions src/store.tsx
Original file line number Diff line number Diff line change
@@ -59,7 +59,6 @@ export type SearchFilter = {

export type SelectedItem = {
key: string
value?: string
isNew?: boolean
}

@@ -68,7 +67,7 @@ type DatabrowserStore = {
setSelectedKey: (key: string | undefined) => void

selectedListItem?: SelectedItem
setSelectedListItem: (item?: { key: string; value?: string; isNew?: boolean }) => void
setSelectedListItem: (item?: { key: string; isNew?: boolean }) => void

search: SearchFilter
setSearch: (search: SearchFilter) => void