Spaces:
Paused
Paused
| 'use client' | |
| import { createRef, useCallback, useEffect, useMemo, useRef, useState } from 'react' | |
| import useSWR from 'swr' | |
| import { createContext, useContext, useContextSelector } from 'use-context-selector' | |
| import type { FC, ReactNode } from 'react' | |
| import { fetchAppList } from '@/service/apps' | |
| import Loading from '@/app/components/base/loading' | |
| import { fetchCurrentWorkspace, fetchLanggeniusVersion, fetchUserProfile, getSystemFeatures } from '@/service/common' | |
| import type { App } from '@/types/app' | |
| import { Theme } from '@/types/app' | |
| import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common' | |
| import MaintenanceNotice from '@/app/components/header/maintenance-notice' | |
| import type { SystemFeatures } from '@/types/feature' | |
| import { defaultSystemFeatures } from '@/types/feature' | |
| export type AppContextValue = { | |
| theme: Theme | |
| setTheme: (theme: Theme) => void | |
| apps: App[] | |
| systemFeatures: SystemFeatures | |
| mutateApps: VoidFunction | |
| userProfile: UserProfileResponse | |
| mutateUserProfile: VoidFunction | |
| currentWorkspace: ICurrentWorkspace | |
| isCurrentWorkspaceManager: boolean | |
| isCurrentWorkspaceOwner: boolean | |
| isCurrentWorkspaceEditor: boolean | |
| isCurrentWorkspaceDatasetOperator: boolean | |
| mutateCurrentWorkspace: VoidFunction | |
| pageContainerRef: React.RefObject<HTMLDivElement> | |
| langeniusVersionInfo: LangGeniusVersionResponse | |
| useSelector: typeof useSelector | |
| } | |
| const initialLangeniusVersionInfo = { | |
| current_env: '', | |
| current_version: '', | |
| latest_version: '', | |
| release_date: '', | |
| release_notes: '', | |
| version: '', | |
| can_auto_update: false, | |
| } | |
| const initialWorkspaceInfo: ICurrentWorkspace = { | |
| id: '', | |
| name: '', | |
| plan: '', | |
| status: '', | |
| created_at: 0, | |
| role: 'normal', | |
| providers: [], | |
| in_trail: true, | |
| } | |
| const AppContext = createContext<AppContextValue>({ | |
| theme: Theme.light, | |
| systemFeatures: defaultSystemFeatures, | |
| setTheme: () => { }, | |
| apps: [], | |
| mutateApps: () => { }, | |
| userProfile: { | |
| id: '', | |
| name: '', | |
| email: '', | |
| avatar: '', | |
| is_password_set: false, | |
| }, | |
| currentWorkspace: initialWorkspaceInfo, | |
| isCurrentWorkspaceManager: false, | |
| isCurrentWorkspaceOwner: false, | |
| isCurrentWorkspaceEditor: false, | |
| isCurrentWorkspaceDatasetOperator: false, | |
| mutateUserProfile: () => { }, | |
| mutateCurrentWorkspace: () => { }, | |
| pageContainerRef: createRef(), | |
| langeniusVersionInfo: initialLangeniusVersionInfo, | |
| useSelector, | |
| }) | |
| export function useSelector<T>(selector: (value: AppContextValue) => T): T { | |
| return useContextSelector(AppContext, selector) | |
| } | |
| export type AppContextProviderProps = { | |
| children: ReactNode | |
| } | |
| export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) => { | |
| const pageContainerRef = useRef<HTMLDivElement>(null) | |
| const { data: appList, mutate: mutateApps } = useSWR({ url: '/apps', params: { page: 1, limit: 30, name: '' } }, fetchAppList) | |
| const { data: userProfileResponse, mutate: mutateUserProfile } = useSWR({ url: '/account/profile', params: {} }, fetchUserProfile) | |
| const { data: currentWorkspaceResponse, mutate: mutateCurrentWorkspace } = useSWR({ url: '/workspaces/current', params: {} }, fetchCurrentWorkspace) | |
| const { data: systemFeatures } = useSWR({ url: '/console/system-features' }, getSystemFeatures, { | |
| fallbackData: defaultSystemFeatures, | |
| }) | |
| const [userProfile, setUserProfile] = useState<UserProfileResponse>() | |
| const [langeniusVersionInfo, setLangeniusVersionInfo] = useState<LangGeniusVersionResponse>(initialLangeniusVersionInfo) | |
| 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) { | |
| const result = await userProfileResponse.json() | |
| setUserProfile(result) | |
| 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 } }) | |
| setLangeniusVersionInfo({ ...versionData, current_version, latest_version: versionData.version, current_env }) | |
| } | |
| }, [userProfileResponse]) | |
| useEffect(() => { | |
| updateUserProfileAndVersion() | |
| }, [updateUserProfileAndVersion, userProfileResponse]) | |
| useEffect(() => { | |
| if (currentWorkspaceResponse) | |
| setCurrentWorkspace(currentWorkspaceResponse) | |
| }, [currentWorkspaceResponse]) | |
| const [theme, setTheme] = useState<Theme>(Theme.light) | |
| const handleSetTheme = useCallback((theme: Theme) => { | |
| setTheme(theme) | |
| globalThis.document.documentElement.setAttribute('data-theme', theme) | |
| }, []) | |
| useEffect(() => { | |
| globalThis.document.documentElement.setAttribute('data-theme', theme) | |
| // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, []) | |
| if (!appList || !userProfile) | |
| return <Loading type='app' /> | |
| return ( | |
| <AppContext.Provider value={{ | |
| theme, | |
| setTheme: handleSetTheme, | |
| apps: appList.data, | |
| systemFeatures, | |
| mutateApps, | |
| userProfile, | |
| mutateUserProfile, | |
| pageContainerRef, | |
| langeniusVersionInfo, | |
| useSelector, | |
| currentWorkspace, | |
| isCurrentWorkspaceManager, | |
| isCurrentWorkspaceOwner, | |
| isCurrentWorkspaceEditor, | |
| isCurrentWorkspaceDatasetOperator, | |
| mutateCurrentWorkspace, | |
| }}> | |
| <div className='flex flex-col h-full overflow-y-auto'> | |
| {globalThis.document?.body?.getAttribute('data-public-maintenance-notice') && <MaintenanceNotice />} | |
| <div ref={pageContainerRef} className='grow relative flex flex-col overflow-y-auto overflow-x-hidden bg-background-body'> | |
| {children} | |
| </div> | |
| </div> | |
| </AppContext.Provider> | |
| ) | |
| } | |
| export const useAppContext = () => useContext(AppContext) | |
| export default AppContext | |