Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

plugin-version-picker.tsx 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useCallback } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import {
  6. PortalToFollowElem,
  7. PortalToFollowElemContent,
  8. PortalToFollowElemTrigger,
  9. } from '@/app/components/base/portal-to-follow-elem'
  10. import Badge from '@/app/components/base/badge'
  11. import type {
  12. OffsetOptions,
  13. Placement,
  14. } from '@floating-ui/react'
  15. import { useVersionListOfPlugin } from '@/service/use-plugins'
  16. import useTimestamp from '@/hooks/use-timestamp'
  17. import cn from '@/utils/classnames'
  18. import { lt } from 'semver'
  19. type Props = {
  20. disabled?: boolean
  21. isShow: boolean
  22. onShowChange: (isShow: boolean) => void
  23. pluginID: string
  24. currentVersion: string
  25. trigger: React.ReactNode
  26. placement?: Placement
  27. offset?: OffsetOptions
  28. onSelect: ({
  29. version,
  30. unique_identifier,
  31. isDowngrade,
  32. }: {
  33. version: string
  34. unique_identifier: string
  35. isDowngrade: boolean
  36. }) => void
  37. }
  38. const PluginVersionPicker: FC<Props> = ({
  39. disabled = false,
  40. isShow,
  41. onShowChange,
  42. pluginID,
  43. currentVersion,
  44. trigger,
  45. placement = 'bottom-start',
  46. offset = {
  47. mainAxis: 4,
  48. crossAxis: -16,
  49. },
  50. onSelect,
  51. }) => {
  52. const { t } = useTranslation()
  53. const format = t('appLog.dateTimeFormat').split(' ')[0]
  54. const { formatDate } = useTimestamp()
  55. const handleTriggerClick = () => {
  56. if (disabled) return
  57. onShowChange(true)
  58. }
  59. const { data: res } = useVersionListOfPlugin(pluginID)
  60. const handleSelect = useCallback(({ version, unique_identifier, isDowngrade }: {
  61. version: string
  62. unique_identifier: string
  63. isDowngrade: boolean
  64. }) => {
  65. if (currentVersion === version)
  66. return
  67. onSelect({ version, unique_identifier, isDowngrade })
  68. onShowChange(false)
  69. }, [currentVersion, onSelect, onShowChange])
  70. return (
  71. <PortalToFollowElem
  72. placement={placement}
  73. offset={offset}
  74. open={isShow}
  75. onOpenChange={onShowChange}
  76. >
  77. <PortalToFollowElemTrigger
  78. className={cn('inline-flex cursor-pointer items-center', disabled && 'cursor-default')}
  79. onClick={handleTriggerClick}
  80. >
  81. {trigger}
  82. </PortalToFollowElemTrigger>
  83. <PortalToFollowElemContent className='z-[1000]'>
  84. <div className="relative w-[209px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg backdrop-blur-sm">
  85. <div className='system-xs-medium-uppercase px-3 pb-0.5 pt-1 text-text-tertiary'>
  86. {t('plugin.detailPanel.switchVersion')}
  87. </div>
  88. <div className='relative'>
  89. {res?.data.versions.map(version => (
  90. <div
  91. key={version.unique_identifier}
  92. className={cn(
  93. 'flex h-7 cursor-pointer items-center gap-1 rounded-lg px-3 py-1 hover:bg-state-base-hover',
  94. currentVersion === version.version && 'cursor-default opacity-30 hover:bg-transparent',
  95. )}
  96. onClick={() => handleSelect({
  97. version: version.version,
  98. unique_identifier: version.unique_identifier,
  99. isDowngrade: lt(version.version, currentVersion),
  100. })}
  101. >
  102. <div className='flex grow items-center'>
  103. <div className='system-sm-medium text-text-secondary'>{version.version}</div>
  104. {currentVersion === version.version && <Badge className='ml-1' text='CURRENT'/>}
  105. </div>
  106. <div className='system-xs-regular shrink-0 text-text-tertiary'>{formatDate(version.created_at, format)}</div>
  107. </div>
  108. ))}
  109. </div>
  110. </div>
  111. </PortalToFollowElemContent>
  112. </PortalToFollowElem>
  113. )
  114. }
  115. export default React.memo(PluginVersionPicker)