refactor: migrate common service toward TanStack Query (#29009)

This commit is contained in:
yyh
2025-12-19 17:34:14 +08:00
committed by GitHub
parent 89e4261883
commit 079620714e
33 changed files with 885 additions and 633 deletions

View File

@@ -1,10 +1,14 @@
'use client'
import { useCallback, useEffect, useMemo, useState } from 'react'
import useSWR from 'swr'
import { useCallback, useEffect, useMemo } from 'react'
import { createContext, useContext, useContextSelector } from 'use-context-selector'
import type { FC, ReactNode } from 'react'
import { fetchCurrentWorkspace, fetchLangGeniusVersion, fetchUserProfile } from '@/service/common'
import { useQueryClient } from '@tanstack/react-query'
import {
useCurrentWorkspace,
useLangGeniusVersion,
useUserProfile,
} from '@/service/use-common'
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
import { noop } from 'lodash-es'
@@ -79,48 +83,44 @@ export type AppContextProviderProps = {
}
export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) => {
const queryClient = useQueryClient()
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
const { data: userProfileResponse, mutate: mutateUserProfile, error: userProfileError } = useSWR({ url: '/account/profile', params: {} }, fetchUserProfile)
const { data: currentWorkspaceResponse, mutate: mutateCurrentWorkspace, isLoading: isLoadingCurrentWorkspace } = useSWR({ url: '/workspaces/current', params: {} }, fetchCurrentWorkspace)
const { data: userProfileResp } = useUserProfile()
const { data: currentWorkspaceResp, isPending: isLoadingCurrentWorkspace } = useCurrentWorkspace()
const langGeniusVersionQuery = useLangGeniusVersion(
userProfileResp?.meta.currentVersion,
!systemFeatures.branding.enabled,
)
const userProfile = useMemo<UserProfileResponse>(() => userProfileResp?.profile || userProfilePlaceholder, [userProfileResp?.profile])
const currentWorkspace = useMemo<ICurrentWorkspace>(() => currentWorkspaceResp || initialWorkspaceInfo, [currentWorkspaceResp])
const langGeniusVersionInfo = useMemo<LangGeniusVersionResponse>(() => {
if (!userProfileResp?.meta?.currentVersion || !langGeniusVersionQuery.data)
return initialLangGeniusVersionInfo
const current_version = userProfileResp.meta.currentVersion
const current_env = userProfileResp.meta.currentEnv || ''
const versionData = langGeniusVersionQuery.data
return {
...versionData,
current_version,
latest_version: versionData.version,
current_env,
}
}, [langGeniusVersionQuery.data, userProfileResp?.meta])
const [userProfile, setUserProfile] = useState<UserProfileResponse>(userProfilePlaceholder)
const [langGeniusVersionInfo, setLangGeniusVersionInfo] = useState<LangGeniusVersionResponse>(initialLangGeniusVersionInfo)
const [currentWorkspace, setCurrentWorkspace] = useState<ICurrentWorkspace>(initialWorkspaceInfo)
const isCurrentWorkspaceManager = useMemo(() => ['owner', 'admin'].includes(currentWorkspace.role), [currentWorkspace.role])
const isCurrentWorkspaceOwner = useMemo(() => currentWorkspace.role === 'owner', [currentWorkspace.role])
const isCurrentWorkspaceEditor = useMemo(() => ['owner', 'admin', 'editor'].includes(currentWorkspace.role), [currentWorkspace.role])
const isCurrentWorkspaceDatasetOperator = useMemo(() => currentWorkspace.role === 'dataset_operator', [currentWorkspace.role])
const updateUserProfileAndVersion = useCallback(async () => {
if (userProfileResponse && !userProfileResponse.bodyUsed) {
try {
const result = await userProfileResponse.json()
setUserProfile(result)
if (!systemFeatures.branding.enabled) {
const current_version = userProfileResponse.headers.get('x-version')
const current_env = process.env.NODE_ENV === 'development' ? 'DEVELOPMENT' : userProfileResponse.headers.get('x-env')
const versionData = await fetchLangGeniusVersion({ url: '/version', params: { current_version } })
setLangGeniusVersionInfo({ ...versionData, current_version, latest_version: versionData.version, current_env })
}
}
catch (error) {
console.error('Failed to update user profile:', error)
if (userProfile.id === '')
setUserProfile(userProfilePlaceholder)
}
}
else if (userProfileError && userProfile.id === '') {
setUserProfile(userProfilePlaceholder)
}
}, [userProfileResponse, userProfileError, userProfile.id])
useEffect(() => {
updateUserProfileAndVersion()
}, [updateUserProfileAndVersion, userProfileResponse])
const mutateUserProfile = useCallback(() => {
queryClient.invalidateQueries({ queryKey: ['common', 'user-profile'] })
}, [queryClient])
useEffect(() => {
if (currentWorkspaceResponse)
setCurrentWorkspace(currentWorkspaceResponse)
}, [currentWorkspaceResponse])
const mutateCurrentWorkspace = useCallback(() => {
queryClient.invalidateQueries({ queryKey: ['common', 'current-workspace'] })
}, [queryClient])
// #region Zendesk conversation fields
useEffect(() => {

View File

@@ -1,15 +1,15 @@
'use client'
import { createContext, useContext, useContextSelector } from 'use-context-selector'
import useSWR from 'swr'
import { useEffect, useState } from 'react'
import dayjs from 'dayjs'
import { useTranslation } from 'react-i18next'
import { useQueryClient } from '@tanstack/react-query'
import {
fetchModelList,
fetchModelProviders,
fetchSupportRetrievalMethods,
} from '@/service/common'
useModelListByType,
useModelProviders,
useSupportRetrievalMethods,
} from '@/service/use-common'
import {
CurrentSystemQuotaTypeEnum,
ModelStatusEnum,
@@ -114,10 +114,10 @@ type ProviderContextProviderProps = {
export const ProviderContextProvider = ({
children,
}: ProviderContextProviderProps) => {
const { data: providersData, mutate: refreshModelProviders } = useSWR('/workspaces/current/model-providers', fetchModelProviders)
const fetchModelListUrlPrefix = '/workspaces/current/models/model-types/'
const { data: textGenerationModelList } = useSWR(`${fetchModelListUrlPrefix}${ModelTypeEnum.textGeneration}`, fetchModelList)
const { data: supportRetrievalMethods } = useSWR('/datasets/retrieval-setting', fetchSupportRetrievalMethods)
const queryClient = useQueryClient()
const { data: providersData } = useModelProviders()
const { data: textGenerationModelList } = useModelListByType(ModelTypeEnum.textGeneration)
const { data: supportRetrievalMethods } = useSupportRetrievalMethods()
const [plan, setPlan] = useState(defaultPlan)
const [isFetchedPlan, setIsFetchedPlan] = useState(false)
@@ -139,6 +139,10 @@ export const ProviderContextProvider = ({
const [isAllowTransferWorkspace, setIsAllowTransferWorkspace] = useState(false)
const [isAllowPublishAsCustomKnowledgePipelineTemplate, setIsAllowPublishAsCustomKnowledgePipelineTemplate] = useState(false)
const refreshModelProviders = () => {
queryClient.invalidateQueries({ queryKey: ['common', 'model-providers'] })
}
const fetchPlan = async () => {
try {
const data = await fetchCurrentPlanInfo()
@@ -226,7 +230,7 @@ export const ProviderContextProvider = ({
modelProviders: providersData?.data || [],
refreshModelProviders,
textGenerationModelList: textGenerationModelList?.data || [],
isAPIKeySet: !!textGenerationModelList?.data.some(model => model.status === ModelStatusEnum.active),
isAPIKeySet: !!textGenerationModelList?.data?.some(model => model.status === ModelStatusEnum.active),
supportRetrievalMethods: supportRetrievalMethods?.retrieval_method || [],
plan,
isFetchedPlan,

View File

@@ -1,8 +1,7 @@
'use client'
import { createContext, useContext } from 'use-context-selector'
import useSWR from 'swr'
import { fetchWorkspaces } from '@/service/common'
import { useWorkspaces } from '@/service/use-common'
import type { IWorkspace } from '@/models/common'
export type WorkspacesContextValue = {
@@ -20,7 +19,7 @@ type IWorkspaceProviderProps = {
export const WorkspaceProvider = ({
children,
}: IWorkspaceProviderProps) => {
const { data } = useSWR({ url: '/workspaces' }, fetchWorkspaces)
const { data } = useWorkspaces()
return (
<WorkspacesContext.Provider value={{