LocalVersionPopover.tsx 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import dayjs from 'dayjs'
  2. import {
  3. Badge,
  4. Button,
  5. Dialog,
  6. DialogContent,
  7. DialogHeader,
  8. DialogSection,
  9. DialogTitle,
  10. DialogTrigger,
  11. Popover,
  12. PopoverContent,
  13. PopoverSeparator,
  14. PopoverTrigger,
  15. Tabs_Shadcn_,
  16. TabsContent_Shadcn_,
  17. TabsList_Shadcn_,
  18. TabsTrigger_Shadcn_,
  19. } from 'ui'
  20. import { Admonition } from 'ui-patterns/admonition'
  21. import { SimpleCodeBlock } from 'ui-patterns/SimpleCodeBlock'
  22. import { getSemver, semverGte, semverLte } from './LocalVersionPopover.utils'
  23. import { DocsButton } from '@/components/ui/DocsButton'
  24. import { InlineLink } from '@/components/ui/InlineLink'
  25. import { useCLIReleaseVersionQuery } from '@/data/misc/cli-release-version-query'
  26. import { DOCS_URL } from '@/lib/constants'
  27. import { useTrack } from '@/lib/telemetry/track'
  28. export const LocalVersionPopover = () => {
  29. const track = useTrack()
  30. const { data, isSuccess } = useCLIReleaseVersionQuery()
  31. const { current: currentCliVersion, latest: latestCliVersion } = data || {}
  32. const hasLatestCLIVersion = isSuccess && !!latestCliVersion
  33. const current = getSemver(currentCliVersion)
  34. const latest = getSemver(latestCliVersion)
  35. const hasUpdate =
  36. !!current && !!latest
  37. ? currentCliVersion !== latestCliVersion && semverLte(current, latest)
  38. : false
  39. const isBeta =
  40. !!current && !!latest && currentCliVersion !== latestCliVersion && semverGte(current, latest)
  41. const approximateNextRelease = !!data?.published_at
  42. ? dayjs(data?.published_at).utc().add(14, 'day').format('DD MMM YYYY')
  43. : undefined
  44. if (!isSuccess || !currentCliVersion) return null
  45. return (
  46. <Popover
  47. onOpenChange={(open) => {
  48. if (open) track('header_local_version_popover_opened')
  49. }}
  50. >
  51. <PopoverTrigger className="flex items-center">
  52. <Badge variant={isBeta ? 'warning' : hasUpdate ? 'success' : 'default'}>
  53. {isBeta ? 'Beta' : hasUpdate ? 'Update available' : 'Latest'}
  54. </Badge>
  55. </PopoverTrigger>
  56. <PopoverContent align="end" className="w-80 px-0">
  57. {hasLatestCLIVersion ? (
  58. !isBeta && hasUpdate ? (
  59. <div className="px-4 mb-3">
  60. <p className="text-sm mb-2">A new version of Briven CLI is available:</p>
  61. <Tabs_Shadcn_ defaultValue="macos">
  62. <TabsList_Shadcn_ className="mt-2">
  63. <TabsTrigger_Shadcn_ className="px-2 text-xs" value="macos">
  64. macOS
  65. </TabsTrigger_Shadcn_>
  66. <TabsTrigger_Shadcn_ className="px-2 text-xs" value="windows">
  67. Windows
  68. </TabsTrigger_Shadcn_>
  69. <TabsTrigger_Shadcn_ className="px-2 text-xs" value="linux">
  70. Linux
  71. </TabsTrigger_Shadcn_>
  72. <TabsTrigger_Shadcn_ className="px-2 text-xs" value="npm">
  73. npm / Bun
  74. </TabsTrigger_Shadcn_>
  75. </TabsList_Shadcn_>
  76. <TabsContent_Shadcn_ className="mt-2 text-xs" value="macos">
  77. <SimpleCodeBlock parentClassName="bg-selection rounded-sm px-2!">
  78. brew upgrade briven
  79. </SimpleCodeBlock>
  80. </TabsContent_Shadcn_>
  81. <TabsContent_Shadcn_ className="mt-2 text-xs" value="windows">
  82. <SimpleCodeBlock parentClassName="bg-selection rounded-sm px-2!">
  83. scoop update briven
  84. </SimpleCodeBlock>
  85. </TabsContent_Shadcn_>
  86. <TabsContent_Shadcn_ className="mt-2 text-xs" value="linux">
  87. <SimpleCodeBlock parentClassName="bg-selection rounded-sm px-2!">
  88. brew upgrade briven
  89. </SimpleCodeBlock>
  90. </TabsContent_Shadcn_>
  91. <TabsContent_Shadcn_ className="mt-2 text-xs" value="npm">
  92. <SimpleCodeBlock parentClassName="bg-selection rounded-sm px-2!">
  93. npm update briven --save-dev
  94. </SimpleCodeBlock>
  95. </TabsContent_Shadcn_>
  96. </Tabs_Shadcn_>
  97. </div>
  98. ) : (
  99. <div className="px-4 mb-3">
  100. {isBeta ? (
  101. <p className="text-sm">You're on the Beta version of Briven CLI</p>
  102. ) : (
  103. <p className="text-sm">You're on the latest version of Briven CLI</p>
  104. )}
  105. </div>
  106. )
  107. ) : null}
  108. <div className="flex flex-col gap-y-2 px-4">
  109. <p className="text-xs text-foreground-lighter">
  110. All available release versions of the CLI can be found on our{' '}
  111. <InlineLink href="https://github.com/briven/cli/releases">
  112. GitHub repository
  113. </InlineLink>
  114. .
  115. </p>
  116. </div>
  117. <div className="flex items-center gap-x-2 mt-3 px-4">
  118. <Dialog>
  119. <DialogTrigger asChild>
  120. <Button type="default">Release schedule</Button>
  121. </DialogTrigger>
  122. <DialogContent>
  123. <DialogHeader className="border-b">
  124. <DialogTitle>Stable release schedule</DialogTitle>
  125. </DialogHeader>
  126. <DialogSection className="flex flex-col gap-y-3">
  127. <div className="flex flex-col gap-y-2">
  128. <p className="text-foreground-lighter text-xs font-mono uppercase">
  129. Approximate next release: {approximateNextRelease}
  130. </p>
  131. <p className="text-sm">
  132. Briven CLI releases follows a two-week schedule, with stable updates available
  133. through the{' '}
  134. <InlineLink
  135. href={`${DOCS_URL}/guides/local-development/cli/getting-started?queryGroups=platform&platform=linux#updating-the-briven-cli`}
  136. >
  137. CLI
  138. </InlineLink>
  139. .
  140. </p>
  141. </div>
  142. <Admonition
  143. type="default"
  144. title="Beta Releases"
  145. description="Beta releases are also available between stable releases through the Beta version of the CLI, which might be helpful if you are waiting for a specific fix."
  146. >
  147. <p className="mt-2!">If you'd like to try, we recommend doing so via npm:</p>
  148. <div className="flex items-center bg-surface-200 py-1 px-2 rounded-sm mt-2 mb-1">
  149. <SimpleCodeBlock parentClassName="bg-surface-200">
  150. npm i briven@beta --save-dev
  151. </SimpleCodeBlock>
  152. </div>
  153. {
  154. <p className="text-sm text-foreground-lighter">
  155. Latest Beta version: <span>{data.beta}</span>
  156. </p>
  157. }
  158. <DocsButton
  159. href={`${DOCS_URL}/guides/local-development/cli/getting-started?queryGroups=platform&platform=linux#using-beta-version`}
  160. className="no-underline! mt-2"
  161. />
  162. </Admonition>
  163. </DialogSection>
  164. </DialogContent>
  165. </Dialog>
  166. <Button type="default" asChild>
  167. <a
  168. target="_blank"
  169. rel="noreferrer noopener"
  170. href={`${DOCS_URL}/guides/local-development/cli/getting-started?queryGroups=platform&platform=linux`}
  171. >
  172. CLI Docs
  173. </a>
  174. </Button>
  175. </div>
  176. <PopoverSeparator className="my-4" />
  177. <div className="flex items-center gap-x-4 px-4">
  178. <div className="flex flex-col gap-y-1">
  179. <p className="text-xs">Current version:</p>
  180. <p className="text-sm font-mono">{currentCliVersion}</p>
  181. </div>
  182. {hasLatestCLIVersion && hasUpdate && !isBeta && (
  183. <div className="flex flex-col gap-y-1">
  184. <p className="text-xs">Available version:</p>
  185. <p className="text-sm font-mono">{latestCliVersion}</p>
  186. </div>
  187. )}
  188. </div>
  189. </PopoverContent>
  190. </Popover>
  191. )
  192. }