mirror of
https://github.com/supabase/supabase.git
synced 2026-10-15 14:19:11 +03:00
* Initial commit. * Minor type fixes. * Add a integration for Queues. Refactor some of the integration layout. * Migrate the Cron integration to the new style. * Add useInstalledIntegrations hook. * Add an integration entry for vault. * Add an integration entry for GraphiQL. * Add supabase webhooks. * Feat/integrations get layout (#30538) * scroll based icon * Update header.tsx * remove dep from overview * moar * more table stuff * moar * alt nav put in * fix MotionNumber issues * more * trying both layouts * Fix bunch of type errors. --------- Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> * Migrate Vercel and Github files to their own folders. * Switch all integrations with the new designs. * More fixes for links, pages structure and other random stuff. * Remove unneeded file. * Another set of fixes. Migrated most of the extension integrations. * Migrated Vault and webhooks to the new style. * Various fixes to make the animation work. * Remove extra code. * Tiny fixes 😬 i swear its tiny * Refactor IntegrationOverviewTab * chore/ update integrations routes (#30585) * init * add child support in tabs * add webhooks * Update IntegrationPageHandler.tsx * fix id issues * use messageId instead * animation tweaks * Move the description to the wrappers array. * The useInstalledIntegrations now provides integrations which could be installed. * Add static content for the various integrations. * Move the page handler logic into the integrations definitions. * Clean up some extra code. * Add logic to make the overview tab the default tab. * Don't show the header until the integration id has been checked. * Add logic to the integration pages to avoid weird loading bugs, deselecting tabs if the integration hasn't been installed etc. * Fix the webhooks overview tab. * Fix the buttons for enabling extensions. * Add padding to all custom tab contents. * Small fixes * Prettier lint * Fix icon color + add empty state for when available integrations are all installed * Fix ts errors * Fiox * Add enable webhooks cta * Fix key * Fix all lints * Fix the queues create sheet. * Fix the deletion of wrappers. * Fix the minimum version alert for the wrappers extension. * Make the queues table fit the whole container. * Fix an issue which reset the tab when installing an extension. * Address comments * Add loading state for installed integrations in side nav * Fix edit secret not rendering value in input field after subsequent openings * Fix vault keys auto filling search input with vault * Fix search input placeholder for cron * Minor fix in install database extension copy * Fix a bad redirect when reloading. * Fix bad url redirects. * Fix scrolling in create new/edit wrapper sheet. * Add y padding to the wrappers rows. * Fix merge errors. * More merge fixes. * Fix bad imports during the merge. --------- Co-authored-by: Jonathan Summers-Muir <MildTomato@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
224 lines
7.7 KiB
TypeScript
224 lines
7.7 KiB
TypeScript
import { useEscapeKeydown } from '@radix-ui/react-use-escape-keydown'
|
|
import { isNil, noop } from 'lodash'
|
|
import { Archive, Clock12, Trash2, X } from 'lucide-react'
|
|
import { useState } from 'react'
|
|
|
|
import { useParams } from 'common'
|
|
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 dayjs from 'dayjs'
|
|
import { useSelectedProject } from 'hooks/misc/useSelectedProject'
|
|
import { prettifyJSON } from 'lib/helpers'
|
|
import {
|
|
Button,
|
|
ResizablePanel,
|
|
Separator,
|
|
Tabs_Shadcn_,
|
|
TabsContent_Shadcn_,
|
|
TabsList_Shadcn_,
|
|
TabsTrigger_Shadcn_,
|
|
} from 'ui'
|
|
|
|
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 project = useSelectedProject()
|
|
|
|
useEscapeKeydown(() => setSelectedMessage(null))
|
|
|
|
const {
|
|
mutate: archiveMessage,
|
|
isLoading: isLoadingArchive,
|
|
isSuccess: isSuccessArchive,
|
|
} = useDatabaseQueueMessageArchiveMutation()
|
|
|
|
const {
|
|
mutate: readMessage,
|
|
isLoading: isLoadingRead,
|
|
isSuccess: isSuccessRead,
|
|
} = useDatabaseQueueMessageReadMutation()
|
|
|
|
const {
|
|
mutate: deleteMessage,
|
|
isLoading: 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
|
|
onCollapse={() => 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,
|
|
queryName: 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,
|
|
queryName: 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>
|
|
)
|
|
}
|