TableReplicationRow.tsx115 lines · main
1import { useParams } from 'common'
2import { ExternalLink, RotateCcw } from 'lucide-react'
3import Link from 'next/link'
4import { Badge, Button, TableCell, TableRow, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
5
6import { ErroredTableDetails } from '../ErroredTableDetails'
7import { TableState } from './ReplicationPipelineStatus.types'
8import { getStatusConfig } from './ReplicationPipelineStatus.utils'
9import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
10import { InlineLinkClassName } from '@/components/ui/InlineLink'
11import { ReplicationPipelineTableStatus } from '@/data/replication/pipeline-replication-status-query'
12
13interface TableReplicationRowProps {
14 table: ReplicationPipelineTableStatus
15 isRestarting: boolean
16 showDisabledState: boolean
17 disabledStateMessage: string
18 isAnyRestartInProgress: boolean
19 isPipelineStopped: boolean
20 onSelectRestart: () => void
21 onSelectShowError: () => void
22}
23
24export const TableReplicationRow = ({
25 table,
26 isRestarting,
27 showDisabledState,
28 disabledStateMessage,
29 isAnyRestartInProgress,
30 isPipelineStopped,
31 onSelectRestart,
32 onSelectShowError,
33}: TableReplicationRowProps) => {
34 const { ref } = useParams()
35 const isErrorState = table.state.name === 'error'
36 const statusConfig = getStatusConfig(table.state as TableState['state'])
37
38 return (
39 <TableRow>
40 <TableCell className="align-top">
41 <div className="flex items-center gap-x-2">
42 <p>{table.table_name}</p>
43
44 <ButtonTooltip
45 asChild
46 type="text"
47 className="px-1.5"
48 icon={<ExternalLink />}
49 tooltip={{
50 content: { side: 'bottom', text: 'Open in Table Editor' },
51 }}
52 >
53 <Link
54 target="_blank"
55 rel="noopener noreferrer"
56 href={`/project/${ref}/editor/${table.table_id}`}
57 />
58 </ButtonTooltip>
59 </div>
60 </TableCell>
61
62 <TableCell className="align-top">
63 {isRestarting ? (
64 <Badge variant="default">Restarting</Badge>
65 ) : showDisabledState ? (
66 <Badge variant="default">Not Available</Badge>
67 ) : (
68 statusConfig.badge
69 )}
70 </TableCell>
71
72 <TableCell className="align-top">
73 {isRestarting ? (
74 <p className="text-sm text-foreground-lighter">
75 Replication is being restarted for this table. The pipeline will restart automatically.
76 </p>
77 ) : showDisabledState ? (
78 <p className="text-sm text-foreground-lighter">{disabledStateMessage}</p>
79 ) : (
80 <div className="flex flex-col gap-y-3">
81 <div className="text-sm text-foreground">
82 {statusConfig.description}{' '}
83 {isErrorState && 'reason' in table.state && (
84 <button className={InlineLinkClassName} onClick={() => onSelectShowError()}>
85 View error.
86 </button>
87 )}
88 </div>
89 {table.state.name === 'error' && <ErroredTableDetails table={table} />}
90 </div>
91 )}
92 </TableCell>
93
94 <TableCell className="align-top">
95 <div className="flex items-center justify-end">
96 <Tooltip>
97 <TooltipTrigger asChild>
98 <Button
99 type="default"
100 className="w-7"
101 icon={<RotateCcw />}
102 disabled={showDisabledState || isRestarting || isAnyRestartInProgress}
103 aria-label={`Restart replication for ${table.table_name}`}
104 onClick={onSelectRestart}
105 />
106 </TooltipTrigger>
107 <TooltipContent side="bottom" align="center">
108 {isPipelineStopped ? 'Reset table and start pipeline' : 'Reset and restart pipeline'}
109 </TooltipContent>
110 </Tooltip>
111 </div>
112 </TableCell>
113 </TableRow>
114 )
115}