From f40b212b0457d5bcbf34eadf30d540e3f7f79629 Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 28 Nov 2024 12:00:02 +0800 Subject: [PATCH] feat: support update if installed from marketplace --- .../hooks/use-check-installed.tsx | 34 +++++++++++ .../steps/install.tsx | 57 ++++++++++++++----- web/service/use-plugins.ts | 30 ++++++++++ 3 files changed, 106 insertions(+), 15 deletions(-) create mode 100644 web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx diff --git a/web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx b/web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx new file mode 100644 index 0000000000..5b35128049 --- /dev/null +++ b/web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx @@ -0,0 +1,34 @@ +import { useCheckInstalled as useDoCheckInstalled } from '@/service/use-plugins' + +import { useMemo } from 'react' +type Props = { + pluginIds: string[], + enabled: boolean +} +const useCheckInstalled = (props: Props) => { + const { data, isLoading, error } = useDoCheckInstalled(props) + + const installedInfo = useMemo(() => { + if (!data) + return undefined + + const res: Record = {} + data?.plugins.forEach((plugin) => { + res[plugin.plugin_id] = { + installedVersion: plugin.declaration.version, + uniqueIdentifier: plugin.plugin_unique_identifier, + } + }) + return res + }, [data]) + return { + installedInfo, + isLoading, + error, + } +} + +export default useCheckInstalled diff --git a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx index cc7303a4c4..1cb0594e32 100644 --- a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx +++ b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx @@ -1,7 +1,7 @@ 'use client' import type { FC } from 'react' import React, { useMemo } from 'react' -import { RiInformation2Line } from '@remixicon/react' +// import { RiInformation2Line } from '@remixicon/react' import type { Plugin, PluginManifestInMarket } from '../../../types' import Card from '../../../card' import { pluginManifestInMarketToPluginProps } from '../../utils' @@ -9,8 +9,9 @@ import Button from '@/app/components/base/button' import { useTranslation } from 'react-i18next' import { RiLoader2Line } from '@remixicon/react' import Badge, { BadgeState } from '@/app/components/base/badge/index' -import { useInstallPackageFromMarketPlace } from '@/service/use-plugins' +import { useInstallPackageFromMarketPlace, useUpdatePackageFromMarketPlace } from '@/service/use-plugins' import checkTaskStatus from '../../base/check-task-status' +import useCheckInstalled from '@/app/components/plugins/install-plugin/hooks/use-check-installed' const i18nPrefix = 'plugin.installModal' @@ -32,7 +33,18 @@ const Installed: FC = ({ onFailed, }) => { const { t } = useTranslation() + const toInstallVersion = payload.version || payload.latest_version + const pluginId = (payload as Plugin).plugin_id + const { installedInfo } = useCheckInstalled({ + pluginIds: [pluginId], + enabled: !!pluginId, + }) + const installedInfoPayload = installedInfo?.[pluginId] + const installedVersion = installedInfoPayload?.installedVersion + const hasInstalled = !!installedVersion + const { mutateAsync: installPackageFromMarketPlace } = useInstallPackageFromMarketPlace() + const { mutateAsync: updatePackageFromMarketPlace } = useUpdatePackageFromMarketPlace() const [isInstalling, setIsInstalling] = React.useState(false) const { check, @@ -50,10 +62,28 @@ const Installed: FC = ({ setIsInstalling(true) try { - const { - all_installed: isInstalled, - task_id: taskId, - } = await installPackageFromMarketPlace(uniqueIdentifier) + let taskId + let isInstalled + if (hasInstalled) { + const { + all_installed, + task_id, + } = await updatePackageFromMarketPlace({ + original_plugin_unique_identifier: installedInfoPayload.uniqueIdentifier, + new_plugin_unique_identifier: uniqueIdentifier, + }) + taskId = task_id + isInstalled = all_installed + } + else { + const { + all_installed, + task_id, + } = await installPackageFromMarketPlace(uniqueIdentifier) + taskId = task_id + isInstalled = all_installed + } + if (isInstalled) { onInstalled() return @@ -73,28 +103,25 @@ const Installed: FC = ({ } } - const toInstallVersion = '1.3.0' - const supportCheckInstalled = false // TODO: check installed in beta version. - const versionInfo = useMemo(() => { return (<>{ - payload.latest_version === toInstallVersion || !supportCheckInstalled + !installedVersion ? ( - {payload.version || payload.latest_version} + { } ) : ( <> - {`${payload.latest_version} -> ${toInstallVersion}`} + {`${installedVersion} -> ${toInstallVersion}`} -
+ {/*
Used in 3 apps
-
+
*/} ) }) - }, [payload.latest_version, payload.version, supportCheckInstalled]) + }, [installedVersion, payload]) return ( <> diff --git a/web/service/use-plugins.ts b/web/service/use-plugins.ts index 9bdf63c5c5..50003a2f1a 100644 --- a/web/service/use-plugins.ts +++ b/web/service/use-plugins.ts @@ -8,6 +8,7 @@ import type { PackageDependency, Permissions, Plugin, + PluginDetail, PluginTask, PluginsFromMarketplaceByInfoResponse, PluginsFromMarketplaceResponse, @@ -29,6 +30,25 @@ import { useInvalidateAllBuiltInTools } from './use-tools' const NAME_SPACE = 'plugins' const useInstalledPluginListKey = [NAME_SPACE, 'installedPluginList'] +export const useCheckInstalled = ({ + pluginIds, + enabled, +}: { + pluginIds: string[], + enabled: boolean +}) => { + return useQuery<{ plugins: PluginDetail[] }>({ + queryKey: [NAME_SPACE, 'checkInstalled'], + queryFn: () => post<{ plugins: PluginDetail[] }>('/workspaces/current/plugin/list/installations/ids', { + body: { + plugin_ids: pluginIds, + }, + }), + enabled, + staleTime: 0, // always fresh + }) +} + export const useInstalledPluginList = (disable?: boolean) => { return useQuery({ queryKey: useInstalledPluginListKey, @@ -58,6 +78,16 @@ export const useInstallPackageFromMarketPlace = () => { }) } +export const useUpdatePackageFromMarketPlace = () => { + return useMutation({ + mutationFn: (body: object) => { + return post('/workspaces/current/plugin/upgrade/marketplace', { + body, + }) + }, + }) +} + export const useVersionListOfPlugin = (pluginID: string) => { return useQuery<{ data: VersionListResponse }>({ queryKey: [NAME_SPACE, 'versions', pluginID],