Merge branch 'perf/web-app-authrozation' into deploy/enterprise

pull/22393/head
NFish 7 months ago
commit 2a0a315187

@ -22,6 +22,7 @@ const Explore: FC<IExploreProps> = ({
const { userProfile, isCurrentWorkspaceDatasetOperator } = useAppContext() const { userProfile, isCurrentWorkspaceDatasetOperator } = useAppContext()
const [hasEditPermission, setHasEditPermission] = useState(false) const [hasEditPermission, setHasEditPermission] = useState(false)
const [installedApps, setInstalledApps] = useState<InstalledApp[]>([]) const [installedApps, setInstalledApps] = useState<InstalledApp[]>([])
const [isFetchingInstalledApps, setIsFetchingInstalledApps] = useState(false)
const { t } = useTranslation() const { t } = useTranslation()
useDocumentTitle(t('common.menus.explore')) useDocumentTitle(t('common.menus.explore'))
@ -51,6 +52,8 @@ const Explore: FC<IExploreProps> = ({
hasEditPermission, hasEditPermission,
installedApps, installedApps,
setInstalledApps, setInstalledApps,
isFetchingInstalledApps,
setIsFetchingInstalledApps,
} }
} }
> >

@ -20,7 +20,7 @@ export type IInstalledAppProps = {
const InstalledApp: FC<IInstalledAppProps> = ({ const InstalledApp: FC<IInstalledAppProps> = ({
id, id,
}) => { }) => {
const { installedApps } = useContext(ExploreContext) const { installedApps, isFetchingInstalledApps } = useContext(ExploreContext)
const updateAppInfo = useWebAppStore(s => s.updateAppInfo) const updateAppInfo = useWebAppStore(s => s.updateAppInfo)
const installedApp = installedApps.find(item => item.id === id) const installedApp = installedApps.find(item => item.id === id)
const updateWebAppAccessMode = useWebAppStore(s => s.updateWebAppAccessMode) const updateWebAppAccessMode = useWebAppStore(s => s.updateWebAppAccessMode)
@ -90,21 +90,25 @@ const InstalledApp: FC<IInstalledAppProps> = ({
<AppUnavailable className='h-auto w-auto' code={403} unknownReason='no permission.' /> <AppUnavailable className='h-auto w-auto' code={403} unknownReason='no permission.' />
</div> </div>
} }
if (isFetchingAppParams || isFetchingAppMeta || isFetchingWebAppAccessMode || !installedApp) { if (isFetchingAppParams || isFetchingAppMeta || isFetchingWebAppAccessMode || isFetchingInstalledApps) {
return <div className='flex h-full items-center justify-center'> return <div className='flex h-full items-center justify-center'>
<Loading /> <Loading />
</div> </div>
} }
if (!installedApp) {
return <div className='flex h-full items-center justify-center'>
<AppUnavailable code={404} isUnknownReason />
</div>
}
return ( return (
<div className='h-full bg-background-default py-2 pl-0 pr-2 sm:p-2'> <div className='h-full bg-background-default py-2 pl-0 pr-2 sm:p-2'>
{installedApp.app.mode !== 'completion' && installedApp.app.mode !== 'workflow' && ( {installedApp?.app.mode !== 'completion' && installedApp?.app.mode !== 'workflow' && (
<ChatWithHistory installedAppInfo={installedApp} className='overflow-hidden rounded-2xl shadow-md' /> <ChatWithHistory installedAppInfo={installedApp} className='overflow-hidden rounded-2xl shadow-md' />
)} )}
{installedApp.app.mode === 'completion' && ( {installedApp?.app.mode === 'completion' && (
<TextGenerationApp isInstalledApp installedAppInfo={installedApp} /> <TextGenerationApp isInstalledApp installedAppInfo={installedApp} />
)} )}
{installedApp.app.mode === 'workflow' && ( {installedApp?.app.mode === 'workflow' && (
<TextGenerationApp isWorkflow isInstalledApp installedAppInfo={installedApp} /> <TextGenerationApp isWorkflow isInstalledApp installedAppInfo={installedApp} />
)} )}
</div> </div>

@ -8,11 +8,11 @@ import Link from 'next/link'
import Toast from '../../base/toast' import Toast from '../../base/toast'
import Item from './app-nav-item' import Item from './app-nav-item'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { fetchInstalledAppList as doFetchInstalledAppList, uninstallApp, updatePinStatus } from '@/service/explore'
import ExploreContext from '@/context/explore-context' import ExploreContext from '@/context/explore-context'
import Confirm from '@/app/components/base/confirm' import Confirm from '@/app/components/base/confirm'
import Divider from '@/app/components/base/divider' import Divider from '@/app/components/base/divider'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { useGetInstalledApps, useUninstallApp, useUpdateAppPinStatus } from '@/service/use-explore'
const SelectedDiscoveryIcon = () => ( const SelectedDiscoveryIcon = () => (
<svg width="16" height="16" viewBox="0 0 16 16" fill="current" xmlns="http://www.w3.org/2000/svg"> <svg width="16" height="16" viewBox="0 0 16 16" fill="current" xmlns="http://www.w3.org/2000/svg">
@ -50,16 +50,14 @@ const SideBar: FC<IExploreSideBarProps> = ({
const lastSegment = segments.slice(-1)[0] const lastSegment = segments.slice(-1)[0]
const isDiscoverySelected = lastSegment === 'apps' const isDiscoverySelected = lastSegment === 'apps'
const isChatSelected = lastSegment === 'chat' 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 media = useBreakpoints()
const isMobile = media === MediaType.mobile const isMobile = media === MediaType.mobile
const fetchInstalledAppList = async () => {
const { installed_apps }: any = await doFetchInstalledAppList()
setInstalledApps(installed_apps)
}
const [showConfirm, setShowConfirm] = useState(false) const [showConfirm, setShowConfirm] = useState(false)
const [currId, setCurrId] = useState('') const [currId, setCurrId] = useState('')
const handleDelete = async () => { const handleDelete = async () => {
@ -70,25 +68,31 @@ const SideBar: FC<IExploreSideBarProps> = ({
type: 'success', type: 'success',
message: t('common.api.remove'), message: t('common.api.remove'),
}) })
fetchInstalledAppList()
} }
const handleUpdatePinStatus = async (id: string, isPinned: boolean) => { const handleUpdatePinStatus = async (id: string, isPinned: boolean) => {
await updatePinStatus(id, isPinned) await updatePinStatus({ appId: id, isPinned })
Toast.notify({ Toast.notify({
type: 'success', type: 'success',
message: t('common.api.success'), message: t('common.api.success'),
}) })
fetchInstalledAppList()
} }
useEffect(() => { 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(() => { useEffect(() => {
fetchInstalledAppList() fetchInstalledAppList()
}, [controlUpdateInstalledApps]) }, [controlUpdateInstalledApps, fetchInstalledAppList])
const pinnedAppsCount = installedApps.filter(({ is_pinned }) => is_pinned).length const pinnedAppsCount = installedApps.filter(({ is_pinned }) => is_pinned).length
return ( return (

@ -8,6 +8,8 @@ type IExplore = {
hasEditPermission: boolean hasEditPermission: boolean
installedApps: InstalledApp[] installedApps: InstalledApp[]
setInstalledApps: (installedApps: InstalledApp[]) => void setInstalledApps: (installedApps: InstalledApp[]) => void
isFetchingInstalledApps: boolean
setIsFetchingInstalledApps: (isFetchingInstalledApps: boolean) => void
} }
const ExploreContext = createContext<IExplore>({ const ExploreContext = createContext<IExplore>({
@ -16,6 +18,8 @@ const ExploreContext = createContext<IExplore>({
hasEditPermission: false, hasEditPermission: false,
installedApps: [], installedApps: [],
setInstalledApps: noop, setInstalledApps: noop,
isFetchingInstalledApps: false,
setIsFetchingInstalledApps: noop,
}) })
export default ExploreContext export default ExploreContext

@ -1,11 +1,42 @@
import { useGlobalPublicStore } from '@/context/global-public-context' import { useGlobalPublicStore } from '@/context/global-public-context'
import { AccessMode } from '@/models/access-control' import { AccessMode } from '@/models/access-control'
import { useQuery } from '@tanstack/react-query' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { getAppAccessModeByAppId } from './explore' import { fetchInstalledAppList, getAppAccessModeByAppId, uninstallApp, updatePinStatus } from './explore'
import { fetchAppMeta, fetchAppParams } from './share' import { fetchAppMeta, fetchAppParams } from './share'
const NAME_SPACE = 'explore' 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) => { export const useGetInstalledAppAccessModeByAppId = (appId: string | null) => {
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures) const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
return useQuery({ return useQuery({

Loading…
Cancel
Save