From 3e18dd41e7a6348904cef680612996e37ecf1f26 Mon Sep 17 00:00:00 2001 From: NFish Date: Mon, 14 Jul 2025 11:29:37 +0800 Subject: [PATCH] fix: show App is UnAvailable when no app info found in explore page --- web/app/components/explore/index.tsx | 3 ++ .../explore/installed-app/index.tsx | 16 +++++---- web/app/components/explore/sidebar/index.tsx | 30 +++++++++------- web/context/explore-context.ts | 4 +++ web/service/use-explore.ts | 35 +++++++++++++++++-- 5 files changed, 67 insertions(+), 21 deletions(-) diff --git a/web/app/components/explore/index.tsx b/web/app/components/explore/index.tsx index bae2610cba..e716de96f1 100644 --- a/web/app/components/explore/index.tsx +++ b/web/app/components/explore/index.tsx @@ -22,6 +22,7 @@ const Explore: FC = ({ const { userProfile, isCurrentWorkspaceDatasetOperator } = useAppContext() const [hasEditPermission, setHasEditPermission] = useState(false) const [installedApps, setInstalledApps] = useState([]) + const [isFetchingInstalledApps, setIsFetchingInstalledApps] = useState(false) const { t } = useTranslation() useDocumentTitle(t('common.menus.explore')) @@ -51,6 +52,8 @@ const Explore: FC = ({ hasEditPermission, installedApps, setInstalledApps, + isFetchingInstalledApps, + setIsFetchingInstalledApps, } } > diff --git a/web/app/components/explore/installed-app/index.tsx b/web/app/components/explore/installed-app/index.tsx index 212b44934a..8032e173c6 100644 --- a/web/app/components/explore/installed-app/index.tsx +++ b/web/app/components/explore/installed-app/index.tsx @@ -20,7 +20,7 @@ export type IInstalledAppProps = { const InstalledApp: FC = ({ id, }) => { - const { installedApps } = useContext(ExploreContext) + const { installedApps, isFetchingInstalledApps } = useContext(ExploreContext) const updateAppInfo = useWebAppStore(s => s.updateAppInfo) const installedApp = installedApps.find(item => item.id === id) const updateWebAppAccessMode = useWebAppStore(s => s.updateWebAppAccessMode) @@ -90,21 +90,25 @@ const InstalledApp: FC = ({ } - if (isFetchingAppParams || isFetchingAppMeta || isFetchingWebAppAccessMode || !installedApp) { + if (isFetchingAppParams || isFetchingAppMeta || isFetchingWebAppAccessMode || isFetchingInstalledApps) { return
} - + if (!installedApp) { + return
+ +
+ } return (
- {installedApp.app.mode !== 'completion' && installedApp.app.mode !== 'workflow' && ( + {installedApp?.app.mode !== 'completion' && installedApp?.app.mode !== 'workflow' && ( )} - {installedApp.app.mode === 'completion' && ( + {installedApp?.app.mode === 'completion' && ( )} - {installedApp.app.mode === 'workflow' && ( + {installedApp?.app.mode === 'workflow' && ( )}
diff --git a/web/app/components/explore/sidebar/index.tsx b/web/app/components/explore/sidebar/index.tsx index fe5935bcd3..74c397f4fd 100644 --- a/web/app/components/explore/sidebar/index.tsx +++ b/web/app/components/explore/sidebar/index.tsx @@ -8,11 +8,11 @@ import Link from 'next/link' import Toast from '../../base/toast' import Item from './app-nav-item' import cn from '@/utils/classnames' -import { fetchInstalledAppList as doFetchInstalledAppList, uninstallApp, updatePinStatus } from '@/service/explore' import ExploreContext from '@/context/explore-context' import Confirm from '@/app/components/base/confirm' import Divider from '@/app/components/base/divider' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' +import { useGetInstalledApps, useUninstallApp, useUpdateAppPinStatus } from '@/service/use-explore' const SelectedDiscoveryIcon = () => ( @@ -50,16 +50,14 @@ const SideBar: FC = ({ const lastSegment = segments.slice(-1)[0] const isDiscoverySelected = lastSegment === 'apps' const isChatSelected = lastSegment === 'chat' - const { installedApps, setInstalledApps } = useContext(ExploreContext) + const { installedApps, setInstalledApps, setIsFetchingInstalledApps } = useContext(ExploreContext) + const { isFetching: isFetchingInstalledApps, data: ret, refetch: fetchInstalledAppList } = useGetInstalledApps() + const { mutateAsync: uninstallApp } = useUninstallApp() + const { mutateAsync: updatePinStatus } = useUpdateAppPinStatus() const media = useBreakpoints() const isMobile = media === MediaType.mobile - const fetchInstalledAppList = async () => { - const { installed_apps }: any = await doFetchInstalledAppList() - setInstalledApps(installed_apps) - } - const [showConfirm, setShowConfirm] = useState(false) const [currId, setCurrId] = useState('') const handleDelete = async () => { @@ -70,25 +68,31 @@ const SideBar: FC = ({ type: 'success', message: t('common.api.remove'), }) - fetchInstalledAppList() } const handleUpdatePinStatus = async (id: string, isPinned: boolean) => { - await updatePinStatus(id, isPinned) + await updatePinStatus({ appId: id, isPinned }) Toast.notify({ type: 'success', message: t('common.api.success'), }) - fetchInstalledAppList() } useEffect(() => { - fetchInstalledAppList() - }, []) + const installed_apps = (ret as any)?.installed_apps + if (installed_apps && installed_apps.length > 0) + setInstalledApps(installed_apps) + else + setInstalledApps([]) + }, [ret, setInstalledApps]) + + useEffect(() => { + setIsFetchingInstalledApps(isFetchingInstalledApps) + }, [isFetchingInstalledApps, setIsFetchingInstalledApps]) useEffect(() => { fetchInstalledAppList() - }, [controlUpdateInstalledApps]) + }, [controlUpdateInstalledApps, fetchInstalledAppList]) const pinnedAppsCount = installedApps.filter(({ is_pinned }) => is_pinned).length return ( diff --git a/web/context/explore-context.ts b/web/context/explore-context.ts index 11124bd54a..d8d64fb34c 100644 --- a/web/context/explore-context.ts +++ b/web/context/explore-context.ts @@ -8,6 +8,8 @@ type IExplore = { hasEditPermission: boolean installedApps: InstalledApp[] setInstalledApps: (installedApps: InstalledApp[]) => void + isFetchingInstalledApps: boolean + setIsFetchingInstalledApps: (isFetchingInstalledApps: boolean) => void } const ExploreContext = createContext({ @@ -16,6 +18,8 @@ const ExploreContext = createContext({ hasEditPermission: false, installedApps: [], setInstalledApps: noop, + isFetchingInstalledApps: false, + setIsFetchingInstalledApps: noop, }) export default ExploreContext diff --git a/web/service/use-explore.ts b/web/service/use-explore.ts index 1c892a041c..b7d078edbc 100644 --- a/web/service/use-explore.ts +++ b/web/service/use-explore.ts @@ -1,11 +1,42 @@ import { useGlobalPublicStore } from '@/context/global-public-context' import { AccessMode } from '@/models/access-control' -import { useQuery } from '@tanstack/react-query' -import { getAppAccessModeByAppId } from './explore' +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import { fetchInstalledAppList, getAppAccessModeByAppId, uninstallApp, updatePinStatus } from './explore' import { fetchAppMeta, fetchAppParams } from './share' const NAME_SPACE = 'explore' +export const useGetInstalledApps = () => { + return useQuery({ + queryKey: [NAME_SPACE, 'installedApps'], + queryFn: () => { + return fetchInstalledAppList() + }, + }) +} + +export const useUninstallApp = () => { + const client = useQueryClient() + return useMutation({ + mutationKey: [NAME_SPACE, 'uninstallApp'], + mutationFn: (appId: string) => uninstallApp(appId), + onSuccess: () => { + client.invalidateQueries({ queryKey: [NAME_SPACE, 'installedApps'] }) + }, + }) +} + +export const useUpdateAppPinStatus = () => { + const client = useQueryClient() + return useMutation({ + mutationKey: [NAME_SPACE, 'updateAppPinStatus'], + mutationFn: ({ appId, isPinned }: { appId: string; isPinned: boolean }) => updatePinStatus(appId, isPinned), + onSuccess: () => { + client.invalidateQueries({ queryKey: [NAME_SPACE, 'installedApps'] }) + }, + }) +} + export const useGetInstalledAppAccessModeByAppId = (appId: string | null) => { const systemFeatures = useGlobalPublicStore(s => s.systemFeatures) return useQuery({