From 10190a9aa5c2f978f1bf1cf9958912fb90aa4edc Mon Sep 17 00:00:00 2001 From: JzoNg Date: Wed, 16 Oct 2024 17:30:51 +0800 Subject: [PATCH] plugin detail header data binding --- .../plugins/plugin-detail-panel/index.tsx | 63 ++++++++++++++----- .../plugins/plugin-detail-panel/mock.ts | 36 +++++++++++ .../plugins/plugin-page/plugins-panel.tsx | 10 +-- web/app/components/plugins/types.ts | 28 ++++++++- web/i18n/en-US/plugin.ts | 6 ++ web/i18n/zh-Hans/plugin.ts | 6 ++ 6 files changed, 125 insertions(+), 24 deletions(-) create mode 100644 web/app/components/plugins/plugin-detail-panel/mock.ts diff --git a/web/app/components/plugins/plugin-detail-panel/index.tsx b/web/app/components/plugins/plugin-detail-panel/index.tsx index 8508ee2546..bd5bed93b7 100644 --- a/web/app/components/plugins/plugin-detail-panel/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/index.tsx @@ -3,19 +3,26 @@ import React, { useMemo } from 'react' import type { FC } from 'react' import { useContext } from 'use-context-selector' import { useTranslation } from 'react-i18next' -import { RiCloseLine, RiVerifiedBadgeLine } from '@remixicon/react' -import type { Plugin } from '../types' -// import { PluginType } from '../types' -import Badge from '../../base/badge' -import Description from '../card/base/description' +import { + RiBugLine, + RiCloseLine, + RiHardDrive3Line, + // RiVerifiedBadgeLine, +} from '@remixicon/react' +import type { PluginDetail } from '../types' +import { PluginSource } from '../types' +// import Description from '../card/base/description' import Icon from '../card/base/card-icon' import Title from '../card/base/title' +import OrgInfo from '../card/base/org-info' import OperationDropdown from './operation-dropdown' import EndpointList from './endpoint-list' import ActionList from './action-list' import ModelList from './model-list' -// import type { Locale } from '@/i18n' +import Badge from '@/app/components/base/badge' +import Tooltip from '@/app/components/base/tooltip' import { BoxSparkleFill } from '@/app/components/base/icons/src/vender/plugin' +import { Github } from '@/app/components/base/icons/src/public/common' import Button from '@/app/components/base/button' import ActionButton from '@/app/components/base/action-button' import Drawer from '@/app/components/base/drawer' @@ -24,7 +31,7 @@ import I18n from '@/context/i18n' import cn from '@/utils/classnames' type Props = { - pluginDetail: Plugin | undefined + pluginDetail: PluginDetail | undefined onHide: () => void } @@ -38,7 +45,8 @@ const PluginDetailPanel: FC = ({ const hasNewVersion = useMemo(() => { if (!pluginDetail) return false - return pluginDetail.latest_version !== pluginDetail.version + return false // TODO + // return pluginDetail.latest_version !== pluginDetail.version }, [pluginDetail]) const handleUpdate = () => {} @@ -61,11 +69,11 @@ const PluginDetailPanel: FC = ({ <>
- +
- - <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" /> + <Title title={pluginDetail.declaration.label[locale]} /> + {/* <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" /> */} <Badge className='mx-1' text={pluginDetail.version} @@ -77,9 +85,33 @@ const PluginDetailPanel: FC<Props> = ({ </div> <div className='mb-1 flex justify-between items-center h-4'> <div className='flex items-center'> - <div className='text-text-tertiary system-xs-regular'>{pluginDetail.org}</div> - <div className='ml-1 text-text-quaternary system-xs-regular'>·</div> - <BoxSparkleFill className='w-3.5 h-3.5 text-text-tertiary' /> + <OrgInfo + className="mt-0.5" + packageNameClassName='w-auto' + orgName={pluginDetail.declaration.author} + packageName={pluginDetail.declaration.name} + /> + <div className='ml-1 mr-0.5 text-text-quaternary system-xs-regular'>·</div> + {pluginDetail.source === PluginSource.marketplace && ( + <Tooltip popupContent={t('plugin.detailPanel.categoryTip.marketplace')} > + <BoxSparkleFill className='w-3.5 h-3.5 text-text-tertiary hover:text-text-accent' /> + </Tooltip> + )} + {pluginDetail.source === PluginSource.github && ( + <Tooltip popupContent={t('plugin.detailPanel.categoryTip.github')} > + <Github className='w-3.5 h-3.5 text-text-secondary hover:text-text-primary' /> + </Tooltip> + )} + {pluginDetail.source === PluginSource.local && ( + <Tooltip popupContent={t('plugin.detailPanel.categoryTip.local')} > + <RiHardDrive3Line className='w-3.5 h-3.5 text-text-tertiary' /> + </Tooltip> + )} + {pluginDetail.source === PluginSource.debugging && ( + <Tooltip popupContent={t('plugin.detailPanel.categoryTip.debugging')} > + <RiBugLine className='w-3.5 h-3.5 text-text-tertiary hover:text-text-warning' /> + </Tooltip> + )} </div> </div> </div> @@ -90,7 +122,8 @@ const PluginDetailPanel: FC<Props> = ({ </ActionButton> </div> </div> - <Description className='mt-3' text={pluginDetail.brief[locale]} descriptionLineRows={2}></Description> + {/* category === extension TODO */} + {/* <Description className='mt-3' text={pluginDetail.declaration.brief[locale]} descriptionLineRows={2}></Description> */} </div> <div className='grow overflow-y-auto'> <ActionList /> diff --git a/web/app/components/plugins/plugin-detail-panel/mock.ts b/web/app/components/plugins/plugin-detail-panel/mock.ts new file mode 100644 index 0000000000..985e16a7b5 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/mock.ts @@ -0,0 +1,36 @@ +import { PluginSource, PluginType } from '../types' + +export const toolNotion = { + id: 'dlfajkgjdga-dfjalksjfglkds-dfjakld', + created_at: '2024-10-16 16:05:33', + updated_at: '2024-10-16 16:05:33', + name: 'notion page search', + plugin_id: 'Notion/notion-page-search', + plugin_unique_identifier: 'Notion/notion-page-search:1.2.0@fldsjflkdsajfldsakajfkls', + declaration: { + version: '1.2.0', + author: 'Notion', + name: 'notion page search', + category: PluginType.tool, + icon: 'https://via.placeholder.com/150', + label: { + 'en-US': 'Notion Page Search', + 'zh-Hans': 'Notion 页面搜索', + }, + brief: { + 'en-US': 'Description: Search Notion pages and open visited ones faster. No admin access required.More and more info...More and more info...More and more info...', + 'zh-Hans': '搜索 Notion 页面并更快地打开已访问的页面。无需管理员访问权限。More and more info...More and more info...More and more info...', + }, + created_at: '2024-10-16 16:05:33', + resource: {}, + plugins: {}, + tool: {}, // TODO + }, + installation_id: 'jflkdsjoewingljlsadjgoijg-dkfjldajglkajglask-dlfkajdg', + tenant_id: 'jflkdsjoewingljlsadjgoijg', + endpoints_setups: 2, + endpoints_active: 1, + version: '1.2.0', + source: PluginSource.marketplace, + meta: null, +} diff --git a/web/app/components/plugins/plugin-page/plugins-panel.tsx b/web/app/components/plugins/plugin-page/plugins-panel.tsx index 4db88a705b..7bd9620177 100644 --- a/web/app/components/plugins/plugin-page/plugins-panel.tsx +++ b/web/app/components/plugins/plugin-page/plugins-panel.tsx @@ -1,12 +1,8 @@ 'use client' import { useState } from 'react' -import type { Plugin } from '../types' +import type { PluginDetail } from '../types' import PluginDetailPanel from '@/app/components/plugins/plugin-detail-panel' -import { - // extensionDallE, - // modelGPT4, - toolNotion, -} from '@/app/components/plugins/card/card-mock' +import { toolNotion } from '@/app/components/plugins/plugin-detail-panel/mock' import type { FilterState } from './filter-management' import FilterManagement from './filter-management' @@ -17,7 +13,7 @@ const PluginsPanel = () => { // } - const [currentPluginDetail, setCurrentPluginDetail] = useState<Plugin | undefined>(toolNotion as any) + const [currentPluginDetail, setCurrentPluginDetail] = useState<PluginDetail | undefined>(toolNotion as any) return ( <> <div className='flex flex-col pt-1 pb-3 px-12 justify-center items-start gap-3 self-stretch'> diff --git a/web/app/components/plugins/types.ts b/web/app/components/plugins/types.ts index 77963763f9..413a5172c9 100644 --- a/web/app/components/plugins/types.ts +++ b/web/app/components/plugins/types.ts @@ -14,17 +14,41 @@ export enum PluginSource { debugging = 'remote', } +export type PluginToolDeclaration = { + identity: { + author: string + name: string + description: Record<Locale, string> + icon: string + label: Record<Locale, string> + tags: string[] + } + credentials_schema: CredentialFormSchemaBase[] // TODO +} + +export type PluginEndpointDeclaration = { + settings: CredentialFormSchemaBase[] + endpoint: EndpointItem[] +} + +export type EndpointItem = { + path: string + method: string +} + export type PluginDeclaration = { version: string author: string icon: string name: string + category: PluginType label: Record<Locale, string> + brief: Record<Locale, string> created_at: string resource: any // useless in frontend plugins: any // useless in frontend - tool: any // TODO - endpoint: any // TODO + tool: PluginToolDeclaration + endpoint: PluginEndpointDeclaration model: any // TODO } diff --git a/web/i18n/en-US/plugin.ts b/web/i18n/en-US/plugin.ts index 9d94549d64..7decbcd9d4 100644 --- a/web/i18n/en-US/plugin.ts +++ b/web/i18n/en-US/plugin.ts @@ -3,6 +3,12 @@ const translation = { fromMarketplace: 'From Marketplace', endpointsEnabled: '{{num}} sets of endpoints enabled', detailPanel: { + categoryTip: { + marketplace: 'Installed from Marketplace', + github: 'Installed from Github', + local: 'Local Plugin', + debugging: 'Debugging Plugin', + }, operation: { install: 'Install', detail: 'Detail', diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts index 30f6032261..118595971f 100644 --- a/web/i18n/zh-Hans/plugin.ts +++ b/web/i18n/zh-Hans/plugin.ts @@ -3,6 +3,12 @@ const translation = { fromMarketplace: '来自市场', endpointsEnabled: '{{num}} 组端点已启用', detailPanel: { + categoryTip: { + marketplace: '从 Marketplace 安装', + github: '从 Github 安装', + local: '本地插件', + debugging: '调试插件', + }, operation: { install: '安装', detail: '详情',