ActionStatusBadge.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import type { PropsWithChildren } from 'react'
  2. import { Badge, StatusIcon, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
  3. import { ActionName, ActionStatus, type ActionRunStep } from '@/data/actions/action-runs-query'
  4. export interface ActionStatusBadgeProps {
  5. name: ActionName
  6. status: ActionStatus
  7. }
  8. const UNHEALTHY_STATUES: ActionStatus[] = ['DEAD', 'REMOVING']
  9. const WAITING_STATUSES: ActionStatus[] = ['CREATED', 'RESTARTING', 'RUNNING']
  10. export const STATUS_TO_LABEL: Record<ActionStatus, string> = {
  11. CREATED: 'pending',
  12. DEAD: 'failed',
  13. EXITED: 'succeeded',
  14. PAUSED: 'skipped',
  15. REMOVING: 'failed',
  16. RESTARTING: 'restarting',
  17. RUNNING: 'running',
  18. }
  19. const NAME_TO_LABEL: Record<ActionName, string> = {
  20. clone: 'Cloning repo',
  21. pull: 'Pulling data',
  22. health: 'Health check',
  23. configure: 'Configurations',
  24. migrate: 'Migrations',
  25. seed: 'Data seeding',
  26. deploy: 'Functions deployment',
  27. }
  28. export const ActionStatusBadgeCondensed = ({
  29. children,
  30. status,
  31. details,
  32. }: PropsWithChildren<{
  33. status: ActionStatus
  34. details: Array<ActionRunStep>
  35. }>) => {
  36. if (status === 'EXITED') {
  37. return null
  38. }
  39. const isUnhealthy = UNHEALTHY_STATUES.includes(status)
  40. return (
  41. <Tooltip>
  42. <TooltipTrigger asChild>
  43. <Badge variant={isUnhealthy ? 'destructive' : 'default'} className="gap-1.5">
  44. {isUnhealthy && <StatusIcon variant="destructive" hideBackground />}
  45. {children}
  46. </Badge>
  47. </TooltipTrigger>
  48. <TooltipContent>
  49. Additional {STATUS_TO_LABEL[status]} steps:
  50. <ul>
  51. {details.map((step) => (
  52. <li key={step.name} className="before:content-['-'] before:mr-0.5">
  53. {NAME_TO_LABEL[step.name]}
  54. </li>
  55. ))}
  56. </ul>
  57. </TooltipContent>
  58. </Tooltip>
  59. )
  60. }
  61. export const ActionStatusBadge = ({ name, status }: ActionStatusBadgeProps) => {
  62. if (status === 'EXITED') {
  63. return null
  64. }
  65. const isUnhealthy = UNHEALTHY_STATUES.includes(status)
  66. const isWaiting = WAITING_STATUSES.includes(status)
  67. return (
  68. <Badge variant={isUnhealthy ? 'destructive' : 'default'} className="gap-1.5">
  69. {(isUnhealthy || isWaiting) && (
  70. <StatusIcon variant={isUnhealthy ? 'destructive' : 'default'} hideBackground />
  71. )}
  72. {NAME_TO_LABEL[name]}: {STATUS_TO_LABEL[status]}
  73. </Badge>
  74. )
  75. }