Your search for "{filterString}" did not return any results
@@ -37,34 +91,9 @@ export const QueuesRows = ({ queues: fetchedQueues, filterString }: QueuesRowsPr
return (
<>
- {queues.map((q) => {
- const type = q.is_partitioned ? 'Partitioned' : q.is_unlogged ? 'Unlogged' : 'Regular'
-
- return (
-
+
{!selectedMessage.archived_at ? (
- ,
- text: 'Archive',
- isLoading: isLoading,
- onClick: () => {
- mutate({
- projectRef: project!.ref,
- connectionString: project?.connectionString,
- queryName: queueName!,
- messageId: selectedMessage.msg_id,
- })
- },
- }}
- success={
- isSuccess
- ? {
- title: 'Archived',
- description: 'The message is archived successfully.',
- }
- : undefined
- }
- />
+ <>
+ ,
+ text: 'Postpone',
+ isLoading: isLoadingRead,
+ onClick: () => {
+ readMessage({
+ projectRef: project!.ref,
+ connectionString: project?.connectionString,
+ queryName: queueName!,
+ messageId: selectedMessage.msg_id,
+ duration: 60,
+ })
+ },
+ }}
+ success={
+ isSuccessRead
+ ? {
+ title: 'Postponed',
+ description: 'The message was postponed for 60 seconds.',
+ }
+ : undefined
+ }
+ />
+ ,
+ text: 'Archive',
+ isLoading: isLoadingArchive,
+ type: 'warning',
+ onClick: () => {
+ archiveMessage({
+ projectRef: project!.ref,
+ connectionString: project?.connectionString,
+ queryName: queueName!,
+ messageId: selectedMessage.msg_id,
+ })
+ },
+ }}
+ success={
+ isSuccessArchive
+ ? {
+ title: 'Archived',
+ description: 'The message was archived successfully.',
+ }
+ : undefined
+ }
+ />
+ ,
+ 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}
diff --git a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/PurgeQueue.tsx b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/PurgeQueue.tsx
new file mode 100644
index 00000000000..5743748e97a
--- /dev/null
+++ b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/PurgeQueue.tsx
@@ -0,0 +1,65 @@
+import { useRouter } from 'next/router'
+import { toast } from 'sonner'
+
+import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
+import { useDatabaseQueuePurgeMutation } from 'data/database-queues/database-queues-purge-mutation'
+import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal'
+
+interface PurgeQueueProps {
+ queueName: string
+ visible: boolean
+ onClose: () => void
+}
+
+const PurgeQueue = ({ queueName, visible, onClose }: PurgeQueueProps) => {
+ const { project } = useProjectContext()
+ const router = useRouter()
+
+ const { mutate: purgeDatabaseQueue, isLoading } = useDatabaseQueuePurgeMutation({
+ onSuccess: () => {
+ toast.success(`Successfully purged queue ${queueName}`)
+ router.push(`/project/${project?.ref}/integrations/queues`)
+ onClose()
+ },
+ })
+
+ async function handlePurge() {
+ if (!project) return console.error('Project is required')
+
+ purgeDatabaseQueue({
+ queueName: queueName,
+ projectRef: project.ref,
+ connectionString: project.connectionString,
+ })
+ }
+
+ if (!queueName) {
+ return null
+ }
+
+ return (
+
onClose()}
+ onConfirm={handlePurge}
+ title="Purge this queue"
+ loading={isLoading}
+ confirmLabel={`Purge queue ${queueName}`}
+ confirmPlaceholder="Type in name of queue"
+ confirmString={queueName ?? 'Unknown'}
+ text={
+ <>
+ This will purge the queue{' '}
+ {queueName}
+ >
+ }
+ alert={{
+ title:
+ "This action will delete all messages from the queue. They can't be recovered afterwards.",
+ }}
+ />
+ )
+}
+
+export default PurgeQueue
diff --git a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/QueueDataGrid.tsx b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/QueueDataGrid.tsx
index e5e30783d41..c77211a1c7f 100644
--- a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/QueueDataGrid.tsx
+++ b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/QueueDataGrid.tsx
@@ -6,17 +6,18 @@ import { UIEvent, useMemo, useRef } from 'react'
import DataGrid, { Column, DataGridHandle, Row } from 'react-data-grid'
import { PostgresQueueMessage } from 'data/database-queues/database-queue-messages-infinite-query'
-import { Badge, ResizableHandle, ResizablePanel, ResizablePanelGroup, cn } from 'ui'
+import { Badge, Button, ResizableHandle, ResizablePanel, ResizablePanelGroup, cn } from 'ui'
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
import { DATE_FORMAT, MessageDetailsPanel } from './MessageDetailsPanel'
interface QueueDataGridProps {
isLoading: boolean
messages: PostgresQueueMessage[]
+ showMessageModal: () => void
fetchNextPage: () => void
}
-function isAtBottom({ currentTarget }: React.UIEvent): boolean {
+function isAtBottom({ currentTarget }: UIEvent): boolean {
return currentTarget.scrollTop + 10 >= currentTarget.scrollHeight - currentTarget.clientHeight
}
@@ -123,6 +124,7 @@ const columns = messagesCols.map((col) => {
export const QueueMessagesDataGrid = ({
isLoading,
messages,
+ showMessageModal,
fetchNextPage,
}: QueueDataGridProps) => {
const gridRef = useRef(null)
@@ -188,6 +190,9 @@ export const QueueMessagesDataGrid = ({
The selected queue doesn't have any messages.
+
),
diff --git a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/SendMessageModal.tsx b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/SendMessageModal.tsx
new file mode 100644
index 00000000000..26fb2c27c1b
--- /dev/null
+++ b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/SendMessageModal.tsx
@@ -0,0 +1,138 @@
+import { zodResolver } from '@hookform/resolvers/zod'
+import { SubmitHandler, useForm } from 'react-hook-form'
+import z from 'zod'
+
+import { useParams } from 'common'
+import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
+import CodeEditor from 'components/ui/CodeEditor/CodeEditor'
+import { useDatabaseQueueMessageSendMutation } from 'data/database-queues/database-queue-messages-send-mutation'
+import { useEffect } from 'react'
+import { toast } from 'sonner'
+import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, Input, Modal } from 'ui'
+import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
+
+interface SendMessageModalProps {
+ visible: boolean
+ onClose: () => void
+}
+
+const FormSchema = z.object({
+ delay: z.coerce.number().int().gte(0).default(5),
+ payload: z.string().refine(
+ (val) => {
+ try {
+ JSON.parse(val)
+ } catch {
+ return false
+ }
+ },
+ {
+ message: 'The payload should be a JSON object',
+ }
+ ),
+})
+
+export type SendMessageForm = z.infer