feat: from marketplace

This commit is contained in:
Joel 2024-10-14 18:35:01 +08:00
parent 39a6f0943d
commit e2fec587f8
8 changed files with 157 additions and 3 deletions

View File

@ -12,6 +12,8 @@ import { useToolTabs } from './hooks'
import ViewTypeSelect, { ViewType } from './view-type-select'
import cn from '@/utils/classnames'
import { useGetLanguage } from '@/context/i18n'
import PluginList from '@/app/components/workflow/block-selector/market-place-plugin/list'
import { extensionDallE, modelGPT4, toolNotion } from '@/app/components/plugins/card/card-mock'
type AllToolsProps = {
searchText: string
@ -71,6 +73,7 @@ const AllTools = ({
</div>
<ViewTypeSelect viewType={activeView} onChange={setActiveView} />
</div>
<PluginList list={[toolNotion, extensionDallE, modelGPT4] as any} />
<Tools
showWorkflowEmpty={activeTab === ToolTypeEnum.Workflow}
tools={tools}

View File

@ -0,0 +1,56 @@
'use client'
import type { FC } from 'react'
import React, { useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { RiMoreFill } from '@remixicon/react'
import ActionButton from '@/app/components/base/action-button'
// import Button from '@/app/components/base/button'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import cn from '@/utils/classnames'
type Props = {
}
const OperationDropdown: FC<Props> = () => {
const { t } = useTranslation()
const [open, doSetOpen] = useState(false)
const openRef = useRef(open)
const setOpen = useCallback((v: boolean) => {
doSetOpen(v)
openRef.current = v
}, [doSetOpen])
const handleTrigger = useCallback(() => {
setOpen(!openRef.current)
}, [setOpen])
return (
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
placement='bottom-end'
offset={{
mainAxis: 0,
crossAxis: 0,
}}
>
<PortalToFollowElemTrigger onClick={handleTrigger}>
<ActionButton className={cn(open && 'bg-state-base-hover')}>
<RiMoreFill className='w-4 h-4 text-components-button-secondary-accent-text' />
</ActionButton>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-50'>
<div className='w-[112px] p-1 bg-components-panel-bg-blur rounded-xl border-[0.5px] border-components-panel-border shadow-lg'>
<div className='px-3 py-1.5 rounded-lg text-text-secondary system-md-regular cursor-pointer hover:bg-state-base-hover'>{t('common.operation.download')}</div>
{/* Wait marketplace */}
{/* <div className='px-3 py-1.5 rounded-lg text-text-secondary system-md-regular cursor-pointer hover:bg-state-base-hover'>{t('common.operation.viewDetail')}</div> */}
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
)
}
export default React.memo(OperationDropdown)

View File

@ -0,0 +1,54 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import { useContext } from 'use-context-selector'
import { useTranslation } from 'react-i18next'
import Action from './action'
import type { Plugin } from '@/app/components/plugins/types.ts'
import I18n from '@/context/i18n'
import { formatNumber } from '@/utils/format'
enum ActionType {
install = 'install',
download = 'download',
// viewDetail = 'viewDetail', // wait for marketplace api
}
type Props = {
payload: Plugin
onAction: (type: ActionType) => void
}
const Item: FC<Props> = ({
payload,
}) => {
const { t } = useTranslation()
const { locale } = useContext(I18n)
return (
<div className='flex rounded-lg py-2 pr-1 pl-3 hover:bg-state-base-hover'>
<div
className='shrink-0 relative w-6 h-6 border-[0.5px] border-components-panel-border-subtle rounded-md bg-center bg-no-repeat bg-contain'
style={{ backgroundImage: `url(${payload.icon})` }}
/>
<div className='ml-2 w-0 grow flex'>
<div className='w-0 grow'>
<div className='h-4 leading-4 text-text-primary system-sm-medium truncate '>{payload.label[locale]}</div>
<div className='h-5 leading-5 text-text-tertiary system-xs-regular truncate'>{payload.brief[locale]}</div>
<div className='flex text-text-tertiary system-xs-regular space-x-1'>
<div>{payload.org}</div>
<div>·</div>
<div>{t('plugin.install', { num: formatNumber(payload.install_count || 0) })}</div>
</div>
</div>
{/* Action */}
<div className='flex items-center space-x-1 h-4 text-components-button-secondary-accent-text system-xs-medium'>
<div className='px-1.5'>{t('plugin.installAction')}</div>
<Action />
</div>
</div>
</div>
)
}
export default React.memo(Item)

View File

@ -0,0 +1,35 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import Item from './item'
import type { Plugin } from '@/app/components/plugins/types.ts'
type Props = {
list: Plugin[]
// onInstall: () =>
}
const List: FC<Props> = ({
list,
}) => {
const { t } = useTranslation()
return (
<div>
<div className='pt-3 px-4 py-1 text-text-primary system-sm-medium'>
{t('plugin.fromMarketplace')}
</div>
<div className='p-1'>
{list.map((item, index) => (
<Item
key={index}
payload={item}
onAction={() => { }}
/>
))}
</div>
</div>
)
}
export default React.memo(List)

View File

@ -75,13 +75,13 @@ const ToolItem: FC<Props> = ({
})
}}
>
<div className='flex items-center h-8'>
<div className='flex grow items-center h-8'>
<BlockIcon
className='shrink-0'
type={BlockEnum.Tool}
toolIcon={provider.icon}
/>
<div className='ml-2 text-sm text-gray-900 flex-1 min-w-0 truncate'>{payload.label[language]}</div>
<div className='ml-2 text-sm text-gray-900 flex-1 w-0 grow truncate'>{payload.label[language]}</div>
</div>
{isToolPlugin && (
<FoldIcon className={cn('w-4 h-4 text-text-quaternary shrink-0', isFold && 'text-text-tertiary')} />

View File

@ -1,5 +1,6 @@
const translation = {
from: 'From',
fromMarketplace: 'From Marketplace',
endpointsEnabled: '{{num}} sets of endpoints enabled',
detailPanel: {
operation: {
@ -18,6 +19,8 @@ const translation = {
disabled: 'Disabled',
modelNum: '{{num}} MODELS INCLUDED',
},
install: '{{num}} installs',
installAction: 'Install',
}
export default translation

View File

@ -198,7 +198,7 @@ const translation = {
'searchTool': 'Search tool',
'tools': 'Tools',
'allTool': 'All',
'builtInTool': 'Built-in',
'plugin': 'Plugin',
'customTool': 'Custom',
'workflowTool': 'Workflow',
'question-understand': 'Question Understand',

View File

@ -1,5 +1,6 @@
const translation = {
from: '来自',
fromMarketplace: '来自市场',
endpointsEnabled: '{{num}} 组端点已启用',
detailPanel: {
operation: {
@ -18,6 +19,8 @@ const translation = {
disabled: '停用',
modelNum: '{{num}} 模型已包含',
},
install: '{{num}} 次安装',
installAction: '安装',
}
export default translation