| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- 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>
- )
- }
|