Files
Danny White e21e0c73bb refactor(studio): simplify pipeline error details (#50444)
## What kind of change does this PR introduce?

Studio UI refactor.

## What is the current behavior?

Failed replicated tables spread retry timing and error details across
several visually heavy blocks.

## What is the new behavior?

Condenses retry timing and failure details into a clearer table-level
presentation without changing retry behaviour or pipeline mutations.

| Before | After |
| --- | --- |
| <img width="1842" height="594" alt="CleanShot 2026-09-16 at 12 55
52@2x"
src="https://github.com/user-attachments/assets/fb6f6a3f-2e81-411e-9d49-ed4cf8cc66e7"
/> | <img width="1824" height="328" alt="CleanShot 2026-09-16 at 15 16
21@2x"
src="https://github.com/user-attachments/assets/bad558c4-2d4c-4d1b-bb68-32ad4d5b348f"
/> |
| _Not applicable._ | <img width="832" height="662" alt="CleanShot
2026-09-16 at 15 16 29@2x"
src="https://github.com/user-attachments/assets/540a5d55-f99f-4c1e-9a57-5ab2ac31e44e"
/> |

This is an independent slice extracted from #49630. The related review
series is #50443, this PR, #50445, #50446, then #49630.

## To test

1. Open `/project/<ref>/database/replication` and select a pipeline with
a failed table.
2. Confirm the table row presents its failure and retry timing without
expanding the row unnecessarily.
3. Open the error details dialog and confirm the underlying error
remains available.

This is difficult to test unless you have a properly-failing table. You
can instead do the following locally:

1. Check out `dnywh/tmp/pipelines-running-fixture`.
2. Open `/project/<ref>/database/replication/<pipelineId>`.
3. Use the floating pipeline-state switcher in the bottom-right.
4. Select _Running, some tables errored_.
2026-09-17 12:17:52 +10:00

65 lines
1.8 KiB
TypeScript

import {
Button,
cn,
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogSection,
DialogSectionSeparator,
DialogTitle,
} from 'ui'
import { CodeBlock } from 'ui-patterns/CodeBlock'
interface ErrorDetailsDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
tableName: string
reason: string
solution?: string
}
export const ErrorDetailsDialog = ({
open,
onOpenChange,
tableName,
reason,
solution,
}: ErrorDetailsDialogProps) => {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent size="small">
<DialogHeader>
<DialogTitle>Replication error</DialogTitle>
<DialogDescription>{tableName} stopped replicating</DialogDescription>
</DialogHeader>
<DialogSectionSeparator />
<DialogSection className="flex flex-col gap-y-4">
{/*
No `language`: this is an error message reported by the destination, not code, so
syntax highlighting would colour it at random. The code block is still the right
frame, since it marks the text as machine output and carries a copy button for
pasting into a support request.
*/}
<CodeBlock
hideLineNumbers
wrapLines
wrapLongLines
value={reason}
wrapperClassName={cn('[&_pre]:px-3 [&_pre]:py-3')}
className="[&_code]:text-xs [&_code]:text-foreground [&_span]:text-foreground!"
/>
{solution && <p className="text-sm text-foreground-light">{solution}</p>}
</DialogSection>
<DialogFooter>
<DialogClose asChild>
<Button variant="default">Close</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
)
}