polish privatelink delete flow and list attention copy

This commit is contained in:
Danny White committed 2026-08-18 12:42:22 +10:00
1 parent 5cb6546c03
commit 2cb24f06b0
4 files changed
+45 -31

No files matched your search

@@ -60,14 +60,15 @@ describe('getConnectionsAttentionCopy', () => {
const copy = getConnectionsAttentionCopy({ waitingCount: 1, expiredCount: 0 })
expect(copy?.type).toBe('warning')
expect(copy?.title).toBe('Waiting for the AWS account owner')
expect(copy?.showAcceptLink).toBe(true)
expect(copy?.shouldShowAcceptLink).toBe(true)
})
it('uses destructive copy when only expired', () => {
const copy = getConnectionsAttentionCopy({ waitingCount: 0, expiredCount: 2 })
expect(copy?.type).toBe('destructive')
expect(copy?.title).toBe('Connection requests expired')
expect(copy?.showAcceptLink).toBe(false)
expect(copy?.description).toBe('AWS can no longer accept the expired shares below.')
expect(copy?.shouldShowAcceptLink).toBe(false)
})
it('counts statuses from a list', () => {
@@ -73,7 +73,7 @@ export function getConnectionsAttentionCopy(attention: ConnectionsAttention): {
type: 'warning' | 'destructive'
title: string
description: string
showAcceptLink: boolean
shouldShowAcceptLink: boolean
} | null {
const { waitingCount, expiredCount } = attention
if (waitingCount === 0 && expiredCount === 0) return null
@@ -82,8 +82,8 @@ export function getConnectionsAttentionCopy(attention: ConnectionsAttention): {
return {
type: 'destructive',
title: expiredCount === 1 ? 'A connection request expired' : 'Connection requests expired',
description: 'Add a new connection to try again. AWS can no longer accept this share.',
showAcceptLink: false,
description: `AWS can no longer accept the expired share${expiredCount === 1 ? '' : 's'} below.`,
shouldShowAcceptLink: false,
}
}
@@ -91,9 +91,8 @@ export function getConnectionsAttentionCopy(attention: ConnectionsAttention): {
return {
type: 'warning',
title: 'Some connections need attention',
description:
'Accept waiting resource shares in AWS within 12 hours. Expired requests need a new connection.',
showAcceptLink: true,
description: `Accept the waiting resource share${waitingCount === 1 ? '' : 's'} in AWS within 12 hours.`,
shouldShowAcceptLink: true,
}
}
@@ -101,7 +100,7 @@ export function getConnectionsAttentionCopy(attention: ConnectionsAttention): {
type: 'warning',
title:
waitingCount === 1 ? 'Waiting for the AWS account owner' : 'Waiting for AWS account owners',
description: 'Accept the resource share in AWS within 12 hours.',
showAcceptLink: true,
description: `Accept the resource share${waitingCount === 1 ? '' : 's'} in AWS within 12 hours.`,
shouldShowAcceptLink: true,
}
}
@@ -25,7 +25,7 @@ export function AWSPrivateLinkAttentionAdmonition({
description={copy.description}
className={className}
actions={
copy.showAcceptLink && (
copy.shouldShowAcceptLink && (
<Button variant="default" className="w-min" icon={<SquareArrowOutUpRight />} asChild>
<Link
target="_blank"
@@ -25,6 +25,7 @@ import {
} from 'ui-patterns/PageSection'
import { IntegrationSectionIcon } from '../IntegrationsSettings'
import { getConnectionTitle } from './AWSPrivateLink.utils'
import { AWSPrivateLinkAccountItem } from './AWSPrivateLinkAccountItem'
import { AWSPrivateLinkAttentionAdmonition } from './AWSPrivateLinkAttentionAdmonition'
import { AWSPrivateLinkForm } from './AWSPrivateLinkForm'
@@ -46,7 +47,7 @@ export const AWSPrivateLinkSection = () => {
const [showForm, setShowForm] = useState(false)
const [showDeleteModal, setShowDeleteModal] = useState(false)
const { mutate: deleteAccount, isPending: isDeleting } = useAWSAccountDeleteMutation({
const { mutateAsync: deleteAccount, isPending: isDeleting } = useAWSAccountDeleteMutation({
onSuccess: () => {
toast.success('Connection will be deleted shortly')
setShowDeleteModal(false)
@@ -68,25 +69,34 @@ export const AWSPrivateLinkSection = () => {
setShowForm(true)
}
const onConfirmDelete = () => {
if (selectedAccount && project) {
deleteAccount({
projectRef: project.ref,
awsAccountId: selectedAccount.aws_account_id,
databaseIdentifier:
selectedAccount.database_type === 'READ_REPLICA'
? selectedAccount.database_identifier
: undefined,
})
}
const onConfirmDelete = async () => {
if (!selectedAccount || !project) return
await deleteAccount({
projectRef: project.ref,
awsAccountId: selectedAccount.aws_account_id,
databaseIdentifier:
selectedAccount.database_type === 'READ_REPLICA'
? selectedAccount.database_identifier
: undefined,
})
}
const deleteDatabaseCopy =
selectedAccount?.database_type === 'READ_REPLICA'
? selectedAccount.database_identifier
? `the read replica (ID: ${formatDatabaseID(selectedAccount.database_identifier)})`
: 'a read replica'
: 'the primary database'
let deleteDatabaseCopy = 'the primary database'
if (selectedAccount?.database_type === 'READ_REPLICA') {
deleteDatabaseCopy = selectedAccount.database_identifier
? `the read replica (ID: ${formatDatabaseID(selectedAccount.database_identifier)})`
: 'the read replica (ID: Unknown identifier)'
}
const deleteConnectionTitle = selectedAccount
? getConnectionTitle({
account_name: selectedAccount.account_name,
aws_account_id: selectedAccount.aws_account_id,
})
: ''
const showDeleteConnectionId =
!!selectedAccount && deleteConnectionTitle === selectedAccount.aws_account_id
return (
<>
@@ -161,8 +171,12 @@ export const AWSPrivateLinkSection = () => {
<AlertDialogTitle>Delete connection</AlertDialogTitle>
<AlertDialogDescription>
This removes the PrivateLink connection for{' '}
<code className="text-code-inline">{selectedAccount?.aws_account_id}</code> on{' '}
{deleteDatabaseCopy}. Applications using this private path will lose access.
{showDeleteConnectionId ? (
<code className="text-code-inline">{deleteConnectionTitle}</code>
) : (
deleteConnectionTitle
)}{' '}
on {deleteDatabaseCopy}. Applications using this private path will lose access.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>