OutOfDateNotice.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // @ts-nocheck
  2. import { GitBranchIcon } from 'lucide-react'
  3. import { useState } from 'react'
  4. import {
  5. AlertDialog,
  6. AlertDialogAction,
  7. AlertDialogCancel,
  8. AlertDialogContent,
  9. AlertDialogDescription,
  10. AlertDialogFooter,
  11. AlertDialogHeader,
  12. AlertDialogTitle,
  13. AlertDialogTrigger,
  14. Button,
  15. } from 'ui'
  16. import { Admonition } from 'ui-patterns'
  17. import { useSendEventMutation } from '@/data/telemetry/send-event-mutation'
  18. import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
  19. import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
  20. interface OutOfDateNoticeProps {
  21. isBranchOutOfDateMigrations: boolean
  22. missingMigrationsCount: number
  23. hasMissingFunctions: boolean
  24. missingFunctionsCount: number
  25. hasOutOfDateFunctions: boolean
  26. outOfDateFunctionsCount: number
  27. hasEdgeFunctionModifications: boolean
  28. modifiedFunctionsCount: number
  29. isPushing: boolean
  30. onPush: () => void
  31. }
  32. export const OutOfDateNotice = ({
  33. isBranchOutOfDateMigrations,
  34. missingMigrationsCount,
  35. hasMissingFunctions,
  36. hasOutOfDateFunctions,
  37. hasEdgeFunctionModifications,
  38. modifiedFunctionsCount,
  39. isPushing,
  40. onPush,
  41. }: OutOfDateNoticeProps) => {
  42. const [isDialogOpen, setIsDialogOpen] = useState(false)
  43. const hasOutdatedMigrations = isBranchOutOfDateMigrations && missingMigrationsCount > 0
  44. const { data: selectedOrg } = useSelectedOrganizationQuery()
  45. const { data: project } = useSelectedProjectQuery()
  46. const { mutate: sendEvent } = useSendEventMutation()
  47. const isBranch = project?.parent_project_ref !== undefined
  48. const parentProjectRef = isBranch ? project?.parent_project_ref : project?.ref
  49. const getTitle = () => {
  50. if (hasOutdatedMigrations && (hasMissingFunctions || hasOutOfDateFunctions)) {
  51. return 'Your database schema and edge functions are out of date'
  52. } else if (hasOutdatedMigrations) {
  53. return 'Your database schema is out of date'
  54. } else if (hasMissingFunctions || hasOutOfDateFunctions) {
  55. return 'Your functions are out of date'
  56. }
  57. return 'Branch is out of date'
  58. }
  59. const getDescription = () => {
  60. return 'Update this branch to get the latest changes from the production branch.'
  61. }
  62. const handleUpdate = (shouldCloseDialog = false) => {
  63. if (shouldCloseDialog) {
  64. setIsDialogOpen(false)
  65. }
  66. // Track branch update
  67. sendEvent({
  68. action: 'branch_updated',
  69. properties: {
  70. modifiedEdgeFunctions: hasEdgeFunctionModifications,
  71. source: 'out_of_date_notice',
  72. },
  73. groups: {
  74. project: parentProjectRef ?? 'Unknown',
  75. organization: selectedOrg?.slug ?? 'Unknown',
  76. },
  77. })
  78. onPush()
  79. }
  80. return (
  81. <Admonition type="warning" className="my-4">
  82. <div className="w-full flex items-center justify-between">
  83. <div>
  84. <h3 className="text-sm font-medium">{getTitle()}</h3>
  85. <p className="text-sm text-foreground-light">{getDescription()}</p>
  86. </div>
  87. {hasEdgeFunctionModifications ? (
  88. <AlertDialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
  89. <AlertDialogTrigger asChild>
  90. <Button
  91. type="default"
  92. loading={isPushing}
  93. icon={<GitBranchIcon size={16} strokeWidth={1.5} />}
  94. className="shrink-0"
  95. >
  96. {isPushing ? 'Updating...' : 'Update branch'}
  97. </Button>
  98. </AlertDialogTrigger>
  99. <AlertDialogContent>
  100. <AlertDialogHeader>
  101. <AlertDialogTitle>Update branch with modified functions</AlertDialogTitle>
  102. <AlertDialogDescription>
  103. This branch has {modifiedFunctionsCount} modified edge function
  104. {modifiedFunctionsCount !== 1 ? 's' : ''} that will be overwritten when updating
  105. with the latest functions from the production branch. This action cannot be
  106. undone.
  107. </AlertDialogDescription>
  108. </AlertDialogHeader>
  109. <AlertDialogFooter>
  110. <AlertDialogCancel>Cancel</AlertDialogCancel>
  111. <AlertDialogAction variant="warning" onClick={() => handleUpdate(true)}>
  112. Update anyway
  113. </AlertDialogAction>
  114. </AlertDialogFooter>
  115. </AlertDialogContent>
  116. </AlertDialog>
  117. ) : (
  118. <Button
  119. type="default"
  120. loading={isPushing}
  121. onClick={() => handleUpdate()}
  122. icon={<GitBranchIcon size={16} strokeWidth={1.5} />}
  123. className="shrink-0"
  124. >
  125. {isPushing ? 'Updating...' : 'Update branch'}
  126. </Button>
  127. )}
  128. </div>
  129. </Admonition>
  130. )
  131. }