mirror of
https://github.com/supabase/supabase.git
synced 2026-06-14 23:25:16 +08:00
This PR migrates the whole monorepo to use Tailwind v4: - Removed `@tailwindcss/container-queries` plugin since it's included by default in v4, - Bump all instances of Tailwind to v4. Made minimal changes to the shared config to remove non-supported features (`alpha` mentions), - Migrate all apps to be compatible with v4 configs, - Fix the `typography.css` import in 3 apps, - Add missing rules which were included by default in v3, - Run `pnpm dlx @tailwindcss/upgrade` on all apps, which renames a lot of classes - Rename all misnamed classes according to https://tailwindcss.com/docs/upgrade-guide#renamed-utilities in all apps. --------- Co-authored-by: Jordi Enric <jordi.err@gmail.com>
228 lines
7.8 KiB
TypeScript
228 lines
7.8 KiB
TypeScript
import { useEscapeKeydown } from '@radix-ui/react-use-escape-keydown'
|
|
import { useParams } from 'common'
|
|
import dayjs from 'dayjs'
|
|
import { isNil, noop } from 'lodash'
|
|
import { Archive, Clock12, Trash2, X } from 'lucide-react'
|
|
import { useState } from 'react'
|
|
import {
|
|
Button,
|
|
ResizablePanel,
|
|
Separator,
|
|
Tabs_Shadcn_,
|
|
TabsContent_Shadcn_,
|
|
TabsList_Shadcn_,
|
|
TabsTrigger_Shadcn_,
|
|
} from 'ui'
|
|
|
|
import { MonacoEditor } from '@/components/grid/components/common/MonacoEditor'
|
|
import { RowAction, RowData } from '@/components/interfaces/Auth/Users/UserOverview'
|
|
import { useDatabaseQueueMessageArchiveMutation } from '@/data/database-queues/database-queue-messages-archive-mutation'
|
|
import { useDatabaseQueueMessageDeleteMutation } from '@/data/database-queues/database-queue-messages-delete-mutation'
|
|
import { PostgresQueueMessage } from '@/data/database-queues/database-queue-messages-infinite-query'
|
|
import { useDatabaseQueueMessageReadMutation } from '@/data/database-queues/database-queue-messages-read-mutation'
|
|
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
|
|
import { prettifyJSON } from '@/lib/helpers'
|
|
|
|
export const DATE_FORMAT = 'DD MMM, YYYY HH:mm'
|
|
|
|
interface MessageDetailsPanelProps {
|
|
selectedMessage: PostgresQueueMessage
|
|
setSelectedMessage: (value: number | null) => void
|
|
}
|
|
|
|
const tryFormatInitialValue = (value: string) => {
|
|
try {
|
|
const jsonValue = JSON.parse(value)
|
|
return JSON.stringify(jsonValue)
|
|
} catch (err) {
|
|
if (typeof value === 'string') {
|
|
return value.replaceAll(`\"`, `"`)
|
|
} else {
|
|
return JSON.stringify(value)
|
|
}
|
|
}
|
|
}
|
|
|
|
export const MessageDetailsPanel = ({
|
|
selectedMessage,
|
|
setSelectedMessage,
|
|
}: MessageDetailsPanelProps) => {
|
|
const { id: _id, childId: queueName } = useParams()
|
|
const { data: project } = useSelectedProjectQuery()
|
|
|
|
useEscapeKeydown(() => setSelectedMessage(null))
|
|
|
|
const {
|
|
mutate: archiveMessage,
|
|
isPending: isLoadingArchive,
|
|
isSuccess: isSuccessArchive,
|
|
} = useDatabaseQueueMessageArchiveMutation()
|
|
|
|
const {
|
|
mutate: readMessage,
|
|
isPending: isLoadingRead,
|
|
isSuccess: isSuccessRead,
|
|
} = useDatabaseQueueMessageReadMutation()
|
|
|
|
const {
|
|
mutate: deleteMessage,
|
|
isPending: isLoadingDelete,
|
|
isSuccess: isSuccessDelete,
|
|
} = useDatabaseQueueMessageDeleteMutation()
|
|
|
|
const initialValue = JSON.stringify(selectedMessage?.message)
|
|
const jsonString = prettifyJSON(!isNil(initialValue) ? tryFormatInitialValue(initialValue) : '')
|
|
|
|
const [view, setView] = useState<'details' | 'suggestion'>('details')
|
|
|
|
return (
|
|
<ResizablePanel
|
|
defaultSize="30"
|
|
maxSize="45"
|
|
minSize="30"
|
|
collapsible
|
|
onResize={(panelSize) => {
|
|
if (panelSize.asPercentage === 0) {
|
|
setSelectedMessage(null)
|
|
}
|
|
}}
|
|
className="bg-studio border-t pointer-events-auto"
|
|
>
|
|
<Button
|
|
type="text"
|
|
className="absolute top-3 right-3 px-1"
|
|
icon={<X />}
|
|
onClick={() => setSelectedMessage(null)}
|
|
/>
|
|
|
|
<Tabs_Shadcn_
|
|
value={view}
|
|
className="flex flex-col h-full"
|
|
onValueChange={(value: any) => {
|
|
setView(value)
|
|
}}
|
|
>
|
|
<TabsList_Shadcn_ className="px-5 flex gap-x-4 min-h-[46px]">
|
|
<TabsTrigger_Shadcn_
|
|
value="details"
|
|
className="px-0 pb-0 h-full text-xs data-[state=active]:bg-transparent shadow-none!"
|
|
>
|
|
Overview
|
|
</TabsTrigger_Shadcn_>
|
|
</TabsList_Shadcn_>
|
|
<TabsContent_Shadcn_ value="details" className="w-full mt-0 overflow-y-auto grow">
|
|
<div className="flex flex-col px-4 py-4 text-sm">
|
|
<RowData property="Message ID" value={`${selectedMessage.msg_id}`} />
|
|
<RowData
|
|
property="Added at"
|
|
value={dayjs(selectedMessage.enqueued_at).format(DATE_FORMAT)}
|
|
/>
|
|
<RowData
|
|
property="Available at"
|
|
value={dayjs(selectedMessage.vt).format(DATE_FORMAT)}
|
|
/>
|
|
<RowData property="Retries" value={`${selectedMessage.read_ct}`} />
|
|
|
|
<div>
|
|
<h3 className="text-foreground-light py-1">Payload</h3>
|
|
<MonacoEditor
|
|
key={selectedMessage.msg_id}
|
|
onChange={noop}
|
|
width="100%"
|
|
value={jsonString || 'NULL'}
|
|
language="json"
|
|
readOnly
|
|
/>
|
|
</div>
|
|
</div>
|
|
<Separator />
|
|
<div className="flex flex-col px-4 py-4 -space-y-1">
|
|
{!selectedMessage.archived_at ? (
|
|
<>
|
|
<RowAction
|
|
title="Postpone message"
|
|
description="The message will be postponed and won't show up in reads for 60 seconds."
|
|
button={{
|
|
icon: <Clock12 />,
|
|
text: 'Postpone',
|
|
isLoading: isLoadingRead,
|
|
onClick: () => {
|
|
readMessage({
|
|
projectRef: project!.ref,
|
|
connectionString: project?.connectionString,
|
|
queueName: queueName!,
|
|
messageId: selectedMessage.msg_id,
|
|
duration: 60,
|
|
})
|
|
},
|
|
}}
|
|
success={
|
|
isSuccessRead
|
|
? {
|
|
title: 'Postponed',
|
|
description: 'The message was postponed for 60 seconds.',
|
|
}
|
|
: undefined
|
|
}
|
|
/>
|
|
<RowAction
|
|
title="Archive message"
|
|
description="The message will be marked as archived and hidden from future reads by consumers. You can still access the message later."
|
|
button={{
|
|
icon: <Archive />,
|
|
text: 'Archive',
|
|
isLoading: isLoadingArchive,
|
|
type: 'warning',
|
|
onClick: () => {
|
|
archiveMessage({
|
|
projectRef: project!.ref,
|
|
connectionString: project?.connectionString,
|
|
queueName: queueName!,
|
|
messageId: selectedMessage.msg_id,
|
|
})
|
|
},
|
|
}}
|
|
success={
|
|
isSuccessArchive
|
|
? {
|
|
title: 'Archived',
|
|
description: 'The message was archived successfully.',
|
|
}
|
|
: undefined
|
|
}
|
|
/>
|
|
<RowAction
|
|
title="Delete message"
|
|
description="The message cannot be recovered afterwards."
|
|
button={{
|
|
icon: <Trash2 />,
|
|
text: 'Delete',
|
|
type: 'danger',
|
|
isLoading: isLoadingDelete,
|
|
onClick: () => {
|
|
deleteMessage({
|
|
projectRef: project!.ref,
|
|
connectionString: project?.connectionString,
|
|
queueName: queueName!,
|
|
messageId: selectedMessage.msg_id,
|
|
})
|
|
},
|
|
}}
|
|
success={
|
|
isSuccessDelete
|
|
? {
|
|
title: 'Deleted',
|
|
description: 'The message was deleted successfully.',
|
|
}
|
|
: undefined
|
|
}
|
|
/>
|
|
</>
|
|
) : null}
|
|
</div>
|
|
</TabsContent_Shadcn_>
|
|
</Tabs_Shadcn_>
|
|
</ResizablePanel>
|
|
)
|
|
}
|