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