feat: version tag (#14949)
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import React, { type FC, useCallback } from 'react'
|
||||
import { RiMoreFill } from '@remixicon/react'
|
||||
import { VersionHistoryContextMenuOptions } from '../../../types'
|
||||
import MenuItem from './menu-item'
|
||||
import useContextMenu from './use-context-menu'
|
||||
import {
|
||||
PortalToFollowElem,
|
||||
PortalToFollowElemContent,
|
||||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
|
||||
export type ContextMenuProps = {
|
||||
isShowDelete: boolean
|
||||
isNamedVersion: boolean
|
||||
open: boolean
|
||||
setOpen: React.Dispatch<React.SetStateAction<boolean>>
|
||||
handleClickMenuItem: (operation: VersionHistoryContextMenuOptions) => void
|
||||
}
|
||||
|
||||
const ContextMenu: FC<ContextMenuProps> = (props: ContextMenuProps) => {
|
||||
const { isShowDelete, handleClickMenuItem, open, setOpen } = props
|
||||
const {
|
||||
deleteOperation,
|
||||
options,
|
||||
} = useContextMenu(props)
|
||||
|
||||
const handleClickTrigger = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation()
|
||||
setOpen(v => !v)
|
||||
}, [setOpen])
|
||||
|
||||
return (
|
||||
<PortalToFollowElem
|
||||
placement={'bottom-end'}
|
||||
offset={{
|
||||
mainAxis: 4,
|
||||
crossAxis: 0,
|
||||
}}
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
>
|
||||
<PortalToFollowElemTrigger>
|
||||
<Button size='small' className='px-1' onClick={handleClickTrigger}>
|
||||
<RiMoreFill className='w-4 h-4' />
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='z-10'>
|
||||
<div className='flex flex-col w-[184px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg shadow-shadow-shadow-5 backdrop-blur-[5px]'>
|
||||
<div className='flex flex-col p-1'>
|
||||
{
|
||||
options.map((option) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={option.key}
|
||||
item={option}
|
||||
onClick={handleClickMenuItem.bind(null, option.key)}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
{
|
||||
isShowDelete && (
|
||||
<>
|
||||
<Divider type='horizontal' className='h-[1px] bg-divider-subtle my-0' />
|
||||
<div className='p-1'>
|
||||
<MenuItem
|
||||
item={deleteOperation}
|
||||
isDestructive
|
||||
onClick={handleClickMenuItem.bind(null, VersionHistoryContextMenuOptions.delete)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
</PortalToFollowElem>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(ContextMenu)
|
||||
@@ -0,0 +1,39 @@
|
||||
import React, { type FC } from 'react'
|
||||
import type { VersionHistoryContextMenuOptions } from '../../../types'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type MenuItemProps = {
|
||||
item: {
|
||||
key: VersionHistoryContextMenuOptions
|
||||
name: string
|
||||
}
|
||||
onClick: (operation: VersionHistoryContextMenuOptions) => void
|
||||
isDestructive?: boolean
|
||||
}
|
||||
|
||||
const MenuItem: FC<MenuItemProps> = ({
|
||||
item,
|
||||
onClick,
|
||||
isDestructive = false,
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center justify-between px-2 py-1.5 cursor-pointer rounded-lg ',
|
||||
isDestructive ? 'hover:bg-state-destructive-hover' : 'hover:bg-state-base-hover',
|
||||
)}
|
||||
onClick={() => {
|
||||
onClick(item.key)
|
||||
}}
|
||||
>
|
||||
<div className={cn(
|
||||
'flex-1 text-text-primary system-md-regular',
|
||||
isDestructive && 'hover:text-text-destructive',
|
||||
)}>
|
||||
{item.name}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(MenuItem)
|
||||
@@ -0,0 +1,42 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { VersionHistoryContextMenuOptions } from '../../../types'
|
||||
import type { ContextMenuProps } from './index'
|
||||
|
||||
const useContextMenu = (props: ContextMenuProps) => {
|
||||
const {
|
||||
isNamedVersion,
|
||||
} = props
|
||||
const { t } = useTranslation()
|
||||
|
||||
const deleteOperation = {
|
||||
key: VersionHistoryContextMenuOptions.delete,
|
||||
name: t('common.operation.delete'),
|
||||
}
|
||||
|
||||
const options = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
key: VersionHistoryContextMenuOptions.restore,
|
||||
name: t('workflow.common.restore'),
|
||||
},
|
||||
isNamedVersion
|
||||
? {
|
||||
key: VersionHistoryContextMenuOptions.edit,
|
||||
name: t('workflow.versionHistory.editVersionInfo'),
|
||||
}
|
||||
: {
|
||||
key: VersionHistoryContextMenuOptions.edit,
|
||||
name: t('workflow.versionHistory.nameThisVersion'),
|
||||
},
|
||||
]
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isNamedVersion])
|
||||
|
||||
return {
|
||||
deleteOperation,
|
||||
options,
|
||||
}
|
||||
}
|
||||
|
||||
export default useContextMenu
|
||||
Reference in New Issue
Block a user