Perf: remove user profile loading (#22710)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import type { ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
import SwrInitor from '@/app/components/swr-initor'
|
import SwrInitializer from '@/app/components/swr-initializer'
|
||||||
import { AppContextProvider } from '@/context/app-context'
|
import { AppContextProvider } from '@/context/app-context'
|
||||||
import GA, { GaType } from '@/app/components/base/ga'
|
import GA, { GaType } from '@/app/components/base/ga'
|
||||||
import HeaderWrapper from '@/app/components/header/header-wrapper'
|
import HeaderWrapper from '@/app/components/header/header-wrapper'
|
||||||
@@ -13,7 +13,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<GA gaType={GaType.admin} />
|
<GA gaType={GaType.admin} />
|
||||||
<SwrInitor>
|
<SwrInitializer>
|
||||||
<AppContextProvider>
|
<AppContextProvider>
|
||||||
<EventEmitterContextProvider>
|
<EventEmitterContextProvider>
|
||||||
<ProviderContextProvider>
|
<ProviderContextProvider>
|
||||||
@@ -26,7 +26,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
|||||||
</ProviderContextProvider>
|
</ProviderContextProvider>
|
||||||
</EventEmitterContextProvider>
|
</EventEmitterContextProvider>
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</SwrInitor>
|
</SwrInitializer>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import useSWR from 'swr'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import {
|
import {
|
||||||
RiGraduationCapFill,
|
RiGraduationCapFill,
|
||||||
@@ -22,6 +23,8 @@ import PremiumBadge from '@/app/components/base/premium-badge'
|
|||||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||||
import EmailChangeModal from './email-change-modal'
|
import EmailChangeModal from './email-change-modal'
|
||||||
import { validPassword } from '@/config'
|
import { validPassword } from '@/config'
|
||||||
|
import { fetchAppList } from '@/service/apps'
|
||||||
|
import type { App } from '@/types/app'
|
||||||
|
|
||||||
const titleClassName = `
|
const titleClassName = `
|
||||||
system-sm-semibold text-text-secondary
|
system-sm-semibold text-text-secondary
|
||||||
@@ -33,7 +36,9 @@ const descriptionClassName = `
|
|||||||
export default function AccountPage() {
|
export default function AccountPage() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { systemFeatures } = useGlobalPublicStore()
|
const { systemFeatures } = useGlobalPublicStore()
|
||||||
const { mutateUserProfile, userProfile, apps } = useAppContext()
|
const { data: appList } = useSWR({ url: '/apps', params: { page: 1, limit: 100, name: '' } }, fetchAppList)
|
||||||
|
const apps = appList?.data || []
|
||||||
|
const { mutateUserProfile, userProfile } = useAppContext()
|
||||||
const { isEducationAccount } = useProviderContext()
|
const { isEducationAccount } = useProviderContext()
|
||||||
const { notify } = useContext(ToastContext)
|
const { notify } = useContext(ToastContext)
|
||||||
const [editNameModalVisible, setEditNameModalVisible] = useState(false)
|
const [editNameModalVisible, setEditNameModalVisible] = useState(false)
|
||||||
@@ -202,7 +207,7 @@ export default function AccountPage() {
|
|||||||
{!!apps.length && (
|
{!!apps.length && (
|
||||||
<Collapse
|
<Collapse
|
||||||
title={`${t('common.account.showAppLength', { length: apps.length })}`}
|
title={`${t('common.account.showAppLength', { length: apps.length })}`}
|
||||||
items={apps.map(app => ({ ...app, key: app.id, name: app.name }))}
|
items={apps.map((app: App) => ({ ...app, key: app.id, name: app.name }))}
|
||||||
renderItem={renderAppItem}
|
renderItem={renderAppItem}
|
||||||
wrapperClassName='mt-2'
|
wrapperClassName='mt-2'
|
||||||
/>
|
/>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import type { ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
import Header from './header'
|
import Header from './header'
|
||||||
import SwrInitor from '@/app/components/swr-initor'
|
import SwrInitor from '@/app/components/swr-initializer'
|
||||||
import { AppContextProvider } from '@/context/app-context'
|
import { AppContextProvider } from '@/context/app-context'
|
||||||
import GA, { GaType } from '@/app/components/base/ga'
|
import GA, { GaType } from '@/app/components/base/ga'
|
||||||
import HeaderWrapper from '@/app/components/header/header-wrapper'
|
import HeaderWrapper from '@/app/components/header/header-wrapper'
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { useContext, useContextSelector } from 'use-context-selector'
|
import { useContext } from 'use-context-selector'
|
||||||
import React, { useCallback, useState } from 'react'
|
import React, { useCallback, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
RiDeleteBinLine,
|
RiDeleteBinLine,
|
||||||
@@ -15,7 +15,7 @@ import AppIcon from '../base/app-icon'
|
|||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||||
import { ToastContext } from '@/app/components/base/toast'
|
import { ToastContext } from '@/app/components/base/toast'
|
||||||
import AppsContext, { useAppContext } from '@/context/app-context'
|
import { useAppContext } from '@/context/app-context'
|
||||||
import { useProviderContext } from '@/context/provider-context'
|
import { useProviderContext } from '@/context/provider-context'
|
||||||
import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps'
|
import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps'
|
||||||
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
|
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
|
||||||
@@ -73,11 +73,6 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
|
|||||||
const [showImportDSLModal, setShowImportDSLModal] = useState<boolean>(false)
|
const [showImportDSLModal, setShowImportDSLModal] = useState<boolean>(false)
|
||||||
const [secretEnvList, setSecretEnvList] = useState<EnvironmentVariable[]>([])
|
const [secretEnvList, setSecretEnvList] = useState<EnvironmentVariable[]>([])
|
||||||
|
|
||||||
const mutateApps = useContextSelector(
|
|
||||||
AppsContext,
|
|
||||||
state => state.mutateApps,
|
|
||||||
)
|
|
||||||
|
|
||||||
const onEdit: CreateAppModalProps['onConfirm'] = useCallback(async ({
|
const onEdit: CreateAppModalProps['onConfirm'] = useCallback(async ({
|
||||||
name,
|
name,
|
||||||
icon_type,
|
icon_type,
|
||||||
@@ -106,12 +101,11 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
|
|||||||
message: t('app.editDone'),
|
message: t('app.editDone'),
|
||||||
})
|
})
|
||||||
setAppDetail(app)
|
setAppDetail(app)
|
||||||
mutateApps()
|
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
notify({ type: 'error', message: t('app.editFailed') })
|
notify({ type: 'error', message: t('app.editFailed') })
|
||||||
}
|
}
|
||||||
}, [appDetail, mutateApps, notify, setAppDetail, t])
|
}, [appDetail, notify, setAppDetail, t])
|
||||||
|
|
||||||
const onCopy: DuplicateAppModalProps['onConfirm'] = async ({ name, icon_type, icon, icon_background }) => {
|
const onCopy: DuplicateAppModalProps['onConfirm'] = async ({ name, icon_type, icon, icon_background }) => {
|
||||||
if (!appDetail)
|
if (!appDetail)
|
||||||
@@ -131,7 +125,6 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
|
|||||||
message: t('app.newApp.appCreated'),
|
message: t('app.newApp.appCreated'),
|
||||||
})
|
})
|
||||||
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
|
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
|
||||||
mutateApps()
|
|
||||||
onPlanInfoChanged()
|
onPlanInfoChanged()
|
||||||
getRedirection(true, newApp, replace)
|
getRedirection(true, newApp, replace)
|
||||||
}
|
}
|
||||||
@@ -186,7 +179,6 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
|
|||||||
try {
|
try {
|
||||||
await deleteApp(appDetail.id)
|
await deleteApp(appDetail.id)
|
||||||
notify({ type: 'success', message: t('app.appDeleted') })
|
notify({ type: 'success', message: t('app.appDeleted') })
|
||||||
mutateApps()
|
|
||||||
onPlanInfoChanged()
|
onPlanInfoChanged()
|
||||||
setAppDetail()
|
setAppDetail()
|
||||||
replace('/apps')
|
replace('/apps')
|
||||||
@@ -198,7 +190,7 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
setShowConfirmDelete(false)
|
setShowConfirmDelete(false)
|
||||||
}, [appDetail, mutateApps, notify, onPlanInfoChanged, replace, setAppDetail, t])
|
}, [appDetail, notify, onPlanInfoChanged, replace, setAppDetail, t])
|
||||||
|
|
||||||
const { isCurrentWorkspaceEditor } = useAppContext()
|
const { isCurrentWorkspaceEditor } = useAppContext()
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ import { useCallback, useRef, useState } from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { useContext, useContextSelector } from 'use-context-selector'
|
import { useContext } from 'use-context-selector'
|
||||||
import { RiArrowRightLine, RiArrowRightSLine, RiCommandLine, RiCornerDownLeftLine, RiExchange2Fill } from '@remixicon/react'
|
import { RiArrowRightLine, RiArrowRightSLine, RiCommandLine, RiCornerDownLeftLine, RiExchange2Fill } from '@remixicon/react'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useDebounceFn, useKeyPress } from 'ahooks'
|
import { useDebounceFn, useKeyPress } from 'ahooks'
|
||||||
@@ -15,7 +15,7 @@ import Button from '@/app/components/base/button'
|
|||||||
import Divider from '@/app/components/base/divider'
|
import Divider from '@/app/components/base/divider'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
import { basePath } from '@/utils/var'
|
import { basePath } from '@/utils/var'
|
||||||
import AppsContext, { useAppContext } from '@/context/app-context'
|
import { useAppContext } from '@/context/app-context'
|
||||||
import { useProviderContext } from '@/context/provider-context'
|
import { useProviderContext } from '@/context/provider-context'
|
||||||
import { ToastContext } from '@/app/components/base/toast'
|
import { ToastContext } from '@/app/components/base/toast'
|
||||||
import type { AppMode } from '@/types/app'
|
import type { AppMode } from '@/types/app'
|
||||||
@@ -41,7 +41,6 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { push } = useRouter()
|
const { push } = useRouter()
|
||||||
const { notify } = useContext(ToastContext)
|
const { notify } = useContext(ToastContext)
|
||||||
const mutateApps = useContextSelector(AppsContext, state => state.mutateApps)
|
|
||||||
|
|
||||||
const [appMode, setAppMode] = useState<AppMode>('advanced-chat')
|
const [appMode, setAppMode] = useState<AppMode>('advanced-chat')
|
||||||
const [appIcon, setAppIcon] = useState<AppIconSelection>({ type: 'emoji', icon: '🤖', background: '#FFEAD5' })
|
const [appIcon, setAppIcon] = useState<AppIconSelection>({ type: 'emoji', icon: '🤖', background: '#FFEAD5' })
|
||||||
@@ -80,7 +79,6 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
|
|||||||
notify({ type: 'success', message: t('app.newApp.appCreated') })
|
notify({ type: 'success', message: t('app.newApp.appCreated') })
|
||||||
onSuccess()
|
onSuccess()
|
||||||
onClose()
|
onClose()
|
||||||
mutateApps()
|
|
||||||
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
|
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
|
||||||
getRedirection(isCurrentWorkspaceEditor, app, push)
|
getRedirection(isCurrentWorkspaceEditor, app, push)
|
||||||
}
|
}
|
||||||
@@ -88,7 +86,7 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
|
|||||||
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
||||||
}
|
}
|
||||||
isCreatingRef.current = false
|
isCreatingRef.current = false
|
||||||
}, [name, notify, t, appMode, appIcon, description, onSuccess, onClose, mutateApps, push, isCurrentWorkspaceEditor])
|
}, [name, notify, t, appMode, appIcon, description, onSuccess, onClose, push, isCurrentWorkspaceEditor])
|
||||||
|
|
||||||
const { run: handleCreateApp } = useDebounceFn(onCreate, { wait: 300 })
|
const { run: handleCreateApp } = useDebounceFn(onCreate, { wait: 300 })
|
||||||
useKeyPress(['meta.enter', 'ctrl.enter'], () => {
|
useKeyPress(['meta.enter', 'ctrl.enter'], () => {
|
||||||
|
@@ -90,10 +90,10 @@ const Embedded = ({ siteInfo, isShow, onClose, appBaseUrl, accessToken, classNam
|
|||||||
const [option, setOption] = useState<Option>('iframe')
|
const [option, setOption] = useState<Option>('iframe')
|
||||||
const [isCopied, setIsCopied] = useState<OptionStatus>({ iframe: false, scripts: false, chromePlugin: false })
|
const [isCopied, setIsCopied] = useState<OptionStatus>({ iframe: false, scripts: false, chromePlugin: false })
|
||||||
|
|
||||||
const { langeniusVersionInfo } = useAppContext()
|
const { langGeniusVersionInfo } = useAppContext()
|
||||||
const themeBuilder = useThemeContext()
|
const themeBuilder = useThemeContext()
|
||||||
themeBuilder.buildTheme(siteInfo?.chat_color_theme ?? null, siteInfo?.chat_color_theme_inverted ?? false)
|
themeBuilder.buildTheme(siteInfo?.chat_color_theme ?? null, siteInfo?.chat_color_theme_inverted ?? false)
|
||||||
const isTestEnv = langeniusVersionInfo.current_env === 'TESTING' || langeniusVersionInfo.current_env === 'DEVELOPMENT'
|
const isTestEnv = langGeniusVersionInfo.current_env === 'TESTING' || langGeniusVersionInfo.current_env === 'DEVELOPMENT'
|
||||||
const onClickCopy = () => {
|
const onClickCopy = () => {
|
||||||
if (option === 'chromePlugin') {
|
if (option === 'chromePlugin') {
|
||||||
const splitUrl = OPTION_MAP[option].getContent(appBaseUrl, accessToken).split(': ')
|
const splitUrl = OPTION_MAP[option].getContent(appBaseUrl, accessToken).split(': ')
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { useContext, useContextSelector } from 'use-context-selector'
|
import { useContext } from 'use-context-selector'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { RiBuildingLine, RiGlobalLine, RiLockLine, RiMoreFill, RiVerifiedBadgeLine } from '@remixicon/react'
|
import { RiBuildingLine, RiGlobalLine, RiLockLine, RiMoreFill, RiVerifiedBadgeLine } from '@remixicon/react'
|
||||||
@@ -11,7 +11,7 @@ import Toast, { ToastContext } from '@/app/components/base/toast'
|
|||||||
import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps'
|
import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps'
|
||||||
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
|
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
|
||||||
import AppIcon from '@/app/components/base/app-icon'
|
import AppIcon from '@/app/components/base/app-icon'
|
||||||
import AppsContext, { useAppContext } from '@/context/app-context'
|
import { useAppContext } from '@/context/app-context'
|
||||||
import type { HtmlContentProps } from '@/app/components/base/popover'
|
import type { HtmlContentProps } from '@/app/components/base/popover'
|
||||||
import CustomPopover from '@/app/components/base/popover'
|
import CustomPopover from '@/app/components/base/popover'
|
||||||
import Divider from '@/app/components/base/divider'
|
import Divider from '@/app/components/base/divider'
|
||||||
@@ -65,11 +65,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
|||||||
const { onPlanInfoChanged } = useProviderContext()
|
const { onPlanInfoChanged } = useProviderContext()
|
||||||
const { push } = useRouter()
|
const { push } = useRouter()
|
||||||
|
|
||||||
const mutateApps = useContextSelector(
|
|
||||||
AppsContext,
|
|
||||||
state => state.mutateApps,
|
|
||||||
)
|
|
||||||
|
|
||||||
const [showEditModal, setShowEditModal] = useState(false)
|
const [showEditModal, setShowEditModal] = useState(false)
|
||||||
const [showDuplicateModal, setShowDuplicateModal] = useState(false)
|
const [showDuplicateModal, setShowDuplicateModal] = useState(false)
|
||||||
const [showSwitchModal, setShowSwitchModal] = useState<boolean>(false)
|
const [showSwitchModal, setShowSwitchModal] = useState<boolean>(false)
|
||||||
@@ -83,7 +78,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
|||||||
notify({ type: 'success', message: t('app.appDeleted') })
|
notify({ type: 'success', message: t('app.appDeleted') })
|
||||||
if (onRefresh)
|
if (onRefresh)
|
||||||
onRefresh()
|
onRefresh()
|
||||||
mutateApps()
|
|
||||||
onPlanInfoChanged()
|
onPlanInfoChanged()
|
||||||
}
|
}
|
||||||
catch (e: any) {
|
catch (e: any) {
|
||||||
@@ -93,7 +87,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
setShowConfirmDelete(false)
|
setShowConfirmDelete(false)
|
||||||
}, [app.id, mutateApps, notify, onPlanInfoChanged, onRefresh, t])
|
}, [app.id, notify, onPlanInfoChanged, onRefresh, t])
|
||||||
|
|
||||||
const onEdit: CreateAppModalProps['onConfirm'] = useCallback(async ({
|
const onEdit: CreateAppModalProps['onConfirm'] = useCallback(async ({
|
||||||
name,
|
name,
|
||||||
@@ -122,12 +116,11 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
|||||||
})
|
})
|
||||||
if (onRefresh)
|
if (onRefresh)
|
||||||
onRefresh()
|
onRefresh()
|
||||||
mutateApps()
|
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
notify({ type: 'error', message: t('app.editFailed') })
|
notify({ type: 'error', message: t('app.editFailed') })
|
||||||
}
|
}
|
||||||
}, [app.id, mutateApps, notify, onRefresh, t])
|
}, [app.id, notify, onRefresh, t])
|
||||||
|
|
||||||
const onCopy: DuplicateAppModalProps['onConfirm'] = async ({ name, icon_type, icon, icon_background }) => {
|
const onCopy: DuplicateAppModalProps['onConfirm'] = async ({ name, icon_type, icon, icon_background }) => {
|
||||||
try {
|
try {
|
||||||
@@ -147,7 +140,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
|||||||
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
|
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
|
||||||
if (onRefresh)
|
if (onRefresh)
|
||||||
onRefresh()
|
onRefresh()
|
||||||
mutateApps()
|
|
||||||
onPlanInfoChanged()
|
onPlanInfoChanged()
|
||||||
getRedirection(isCurrentWorkspaceEditor, newApp, push)
|
getRedirection(isCurrentWorkspaceEditor, newApp, push)
|
||||||
}
|
}
|
||||||
@@ -195,16 +187,14 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
|||||||
const onSwitch = () => {
|
const onSwitch = () => {
|
||||||
if (onRefresh)
|
if (onRefresh)
|
||||||
onRefresh()
|
onRefresh()
|
||||||
mutateApps()
|
|
||||||
setShowSwitchModal(false)
|
setShowSwitchModal(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onUpdateAccessControl = useCallback(() => {
|
const onUpdateAccessControl = useCallback(() => {
|
||||||
if (onRefresh)
|
if (onRefresh)
|
||||||
onRefresh()
|
onRefresh()
|
||||||
mutateApps()
|
|
||||||
setShowAccessControl(false)
|
setShowAccessControl(false)
|
||||||
}, [onRefresh, mutateApps, setShowAccessControl])
|
}, [onRefresh, setShowAccessControl])
|
||||||
|
|
||||||
const Operations = (props: HtmlContentProps) => {
|
const Operations = (props: HtmlContentProps) => {
|
||||||
const { data: userCanAccessApp, isLoading: isGettingUserCanAccessApp } = useGetUserCanAccessApp({ appId: app?.id, enabled: (!!props?.open && systemFeatures.webapp_auth.enabled) })
|
const { data: userCanAccessApp, isLoading: isGettingUserCanAccessApp } = useGetUserCanAccessApp({ appId: app?.id, enabled: (!!props?.open && systemFeatures.webapp_auth.enabled) })
|
||||||
@@ -325,7 +315,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
|||||||
dateFormat: `${t('datasetDocuments.segment.dateTimeFormat')}`,
|
dateFormat: `${t('datasetDocuments.segment.dateTimeFormat')}`,
|
||||||
})
|
})
|
||||||
return `${t('datasetDocuments.segment.editedAt')} ${timeText}`
|
return `${t('datasetDocuments.segment.editedAt')} ${timeText}`
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [app.updated_at, app.created_at])
|
}, [app.updated_at, app.created_at])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -45,7 +45,7 @@ const Avatar = ({
|
|||||||
className={cn(textClassName, 'scale-[0.4] text-center text-white')}
|
className={cn(textClassName, 'scale-[0.4] text-center text-white')}
|
||||||
style={style}
|
style={style}
|
||||||
>
|
>
|
||||||
{name[0].toLocaleUpperCase()}
|
{name && name[0].toLocaleUpperCase()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@@ -21,7 +21,7 @@ const AppsFull: FC<{ loc: string; className?: string; }> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { plan } = useProviderContext()
|
const { plan } = useProviderContext()
|
||||||
const { userProfile, langeniusVersionInfo } = useAppContext()
|
const { userProfile, langGeniusVersionInfo } = useAppContext()
|
||||||
const isTeam = plan.type === Plan.team
|
const isTeam = plan.type === Plan.team
|
||||||
const usage = plan.usage.buildApps
|
const usage = plan.usage.buildApps
|
||||||
const total = plan.total.buildApps
|
const total = plan.total.buildApps
|
||||||
@@ -62,7 +62,7 @@ const AppsFull: FC<{ loc: string; className?: string; }> = ({
|
|||||||
)}
|
)}
|
||||||
{plan.type !== Plan.sandbox && plan.type !== Plan.professional && (
|
{plan.type !== Plan.sandbox && plan.type !== Plan.professional && (
|
||||||
<Button variant='secondary-accent'>
|
<Button variant='secondary-accent'>
|
||||||
<a target='_blank' rel='noopener noreferrer' href={mailToSupport(userProfile.email, plan.type, langeniusVersionInfo.current_version)}>
|
<a target='_blank' rel='noopener noreferrer' href={mailToSupport(userProfile.email, plan.type, langGeniusVersionInfo.current_version)}>
|
||||||
{t('billing.apps.contactUs')}
|
{t('billing.apps.contactUs')}
|
||||||
</a>
|
</a>
|
||||||
</Button>
|
</Button>
|
||||||
|
@@ -43,10 +43,10 @@ Object.defineProperty(globalThis, 'sessionStorage', {
|
|||||||
value: sessionStorage,
|
value: sessionStorage,
|
||||||
})
|
})
|
||||||
|
|
||||||
const BrowserInitor = ({
|
const BrowserInitializer = ({
|
||||||
children,
|
children,
|
||||||
}: { children: React.ReactNode }) => {
|
}: { children: React.ReactElement }) => {
|
||||||
return children
|
return children
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BrowserInitor
|
export default BrowserInitializer
|
@@ -12,16 +12,16 @@ import { noop } from 'lodash-es'
|
|||||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||||
|
|
||||||
type IAccountSettingProps = {
|
type IAccountSettingProps = {
|
||||||
langeniusVersionInfo: LangGeniusVersionResponse
|
langGeniusVersionInfo: LangGeniusVersionResponse
|
||||||
onCancel: () => void
|
onCancel: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AccountAbout({
|
export default function AccountAbout({
|
||||||
langeniusVersionInfo,
|
langGeniusVersionInfo,
|
||||||
onCancel,
|
onCancel,
|
||||||
}: IAccountSettingProps) {
|
}: IAccountSettingProps) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const isLatest = langeniusVersionInfo.current_version === langeniusVersionInfo.latest_version
|
const isLatest = langGeniusVersionInfo.current_version === langGeniusVersionInfo.latest_version
|
||||||
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
|
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -43,7 +43,7 @@ export default function AccountAbout({
|
|||||||
/>
|
/>
|
||||||
: <DifyLogo size='large' className='mx-auto' />}
|
: <DifyLogo size='large' className='mx-auto' />}
|
||||||
|
|
||||||
<div className='text-center text-xs font-normal text-text-tertiary'>Version {langeniusVersionInfo?.current_version}</div>
|
<div className='text-center text-xs font-normal text-text-tertiary'>Version {langGeniusVersionInfo?.current_version}</div>
|
||||||
<div className='flex flex-col items-center gap-2 text-center text-xs font-normal text-text-secondary'>
|
<div className='flex flex-col items-center gap-2 text-center text-xs font-normal text-text-secondary'>
|
||||||
<div>© {dayjs().year()} LangGenius, Inc., Contributors.</div>
|
<div>© {dayjs().year()} LangGenius, Inc., Contributors.</div>
|
||||||
<div className='text-text-accent'>
|
<div className='text-text-accent'>
|
||||||
@@ -63,8 +63,8 @@ export default function AccountAbout({
|
|||||||
<div className='text-xs font-medium text-text-tertiary'>
|
<div className='text-xs font-medium text-text-tertiary'>
|
||||||
{
|
{
|
||||||
isLatest
|
isLatest
|
||||||
? t('common.about.latestAvailable', { version: langeniusVersionInfo.latest_version })
|
? t('common.about.latestAvailable', { version: langGeniusVersionInfo.latest_version })
|
||||||
: t('common.about.nowAvailable', { version: langeniusVersionInfo.latest_version })
|
: t('common.about.nowAvailable', { version: langGeniusVersionInfo.latest_version })
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center'>
|
<div className='flex items-center'>
|
||||||
@@ -80,7 +80,7 @@ export default function AccountAbout({
|
|||||||
!isLatest && !IS_CE_EDITION && (
|
!isLatest && !IS_CE_EDITION && (
|
||||||
<Button variant='primary' size='small'>
|
<Button variant='primary' size='small'>
|
||||||
<Link
|
<Link
|
||||||
href={langeniusVersionInfo.release_notes}
|
href={langGeniusVersionInfo.release_notes}
|
||||||
target='_blank' rel='noopener noreferrer'
|
target='_blank' rel='noopener noreferrer'
|
||||||
>
|
>
|
||||||
{t('common.about.updateNow')}
|
{t('common.about.updateNow')}
|
||||||
|
@@ -45,7 +45,7 @@ export default function AppSelector() {
|
|||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const docLink = useDocLink()
|
const docLink = useDocLink()
|
||||||
const { userProfile, langeniusVersionInfo, isCurrentWorkspaceOwner } = useAppContext()
|
const { userProfile, langGeniusVersionInfo, isCurrentWorkspaceOwner } = useAppContext()
|
||||||
const { isEducationAccount } = useProviderContext()
|
const { isEducationAccount } = useProviderContext()
|
||||||
const { setShowAccountSettingModal } = useModalContext()
|
const { setShowAccountSettingModal } = useModalContext()
|
||||||
|
|
||||||
@@ -180,8 +180,8 @@ export default function AppSelector() {
|
|||||||
<RiInformation2Line className='size-4 shrink-0 text-text-tertiary' />
|
<RiInformation2Line className='size-4 shrink-0 text-text-tertiary' />
|
||||||
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.about')}</div>
|
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.about')}</div>
|
||||||
<div className='flex shrink-0 items-center'>
|
<div className='flex shrink-0 items-center'>
|
||||||
<div className='system-xs-regular mr-2 text-text-tertiary'>{langeniusVersionInfo.current_version}</div>
|
<div className='system-xs-regular mr-2 text-text-tertiary'>{langGeniusVersionInfo.current_version}</div>
|
||||||
<Indicator color={langeniusVersionInfo.current_version === langeniusVersionInfo.latest_version ? 'green' : 'orange'} />
|
<Indicator color={langGeniusVersionInfo.current_version === langGeniusVersionInfo.latest_version ? 'green' : 'orange'} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@@ -217,7 +217,7 @@ export default function AppSelector() {
|
|||||||
}
|
}
|
||||||
</Menu>
|
</Menu>
|
||||||
{
|
{
|
||||||
aboutVisible && <AccountAbout onCancel={() => setAboutVisible(false)} langeniusVersionInfo={langeniusVersionInfo} />
|
aboutVisible && <AccountAbout onCancel={() => setAboutVisible(false)} langGeniusVersionInfo={langGeniusVersionInfo} />
|
||||||
}
|
}
|
||||||
</div >
|
</div >
|
||||||
)
|
)
|
||||||
|
@@ -16,7 +16,7 @@ export default function Support() {
|
|||||||
`
|
`
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { plan } = useProviderContext()
|
const { plan } = useProviderContext()
|
||||||
const { userProfile, langeniusVersionInfo } = useAppContext()
|
const { userProfile, langGeniusVersionInfo } = useAppContext()
|
||||||
const canEmailSupport = plan.type === Plan.professional || plan.type === Plan.team || plan.type === Plan.enterprise
|
const canEmailSupport = plan.type === Plan.professional || plan.type === Plan.team || plan.type === Plan.enterprise
|
||||||
|
|
||||||
return <Menu as="div" className="relative h-full w-full">
|
return <Menu as="div" className="relative h-full w-full">
|
||||||
@@ -53,7 +53,7 @@ export default function Support() {
|
|||||||
className={cn(itemClassName, 'group justify-between',
|
className={cn(itemClassName, 'group justify-between',
|
||||||
'data-[active]:bg-state-base-hover',
|
'data-[active]:bg-state-base-hover',
|
||||||
)}
|
)}
|
||||||
href={mailToSupport(userProfile.email, plan.type, langeniusVersionInfo.current_version)}
|
href={mailToSupport(userProfile.email, plan.type, langGeniusVersionInfo.current_version)}
|
||||||
target='_blank' rel='noopener noreferrer'>
|
target='_blank' rel='noopener noreferrer'>
|
||||||
<RiMailSendLine className='size-4 shrink-0 text-text-tertiary' />
|
<RiMailSendLine className='size-4 shrink-0 text-text-tertiary' />
|
||||||
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.emailSupport')}</div>
|
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.emailSupport')}</div>
|
||||||
|
@@ -12,8 +12,8 @@ const headerEnvClassName: { [k: string]: string } = {
|
|||||||
|
|
||||||
const EnvNav = () => {
|
const EnvNav = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { langeniusVersionInfo } = useAppContext()
|
const { langGeniusVersionInfo } = useAppContext()
|
||||||
const showEnvTag = langeniusVersionInfo.current_env === 'TESTING' || langeniusVersionInfo.current_env === 'DEVELOPMENT'
|
const showEnvTag = langGeniusVersionInfo.current_env === 'TESTING' || langGeniusVersionInfo.current_env === 'DEVELOPMENT'
|
||||||
|
|
||||||
if (!showEnvTag)
|
if (!showEnvTag)
|
||||||
return null
|
return null
|
||||||
@@ -21,10 +21,10 @@ const EnvNav = () => {
|
|||||||
return (
|
return (
|
||||||
<div className={`
|
<div className={`
|
||||||
mr-1 flex h-[22px] items-center rounded-md border px-2 text-xs font-medium
|
mr-1 flex h-[22px] items-center rounded-md border px-2 text-xs font-medium
|
||||||
${headerEnvClassName[langeniusVersionInfo.current_env]}
|
${headerEnvClassName[langGeniusVersionInfo.current_env]}
|
||||||
`}>
|
`}>
|
||||||
{
|
{
|
||||||
langeniusVersionInfo.current_env === 'TESTING' && (
|
langGeniusVersionInfo.current_env === 'TESTING' && (
|
||||||
<>
|
<>
|
||||||
<Beaker02 className='h-3 w-3' />
|
<Beaker02 className='h-3 w-3' />
|
||||||
<div className='ml-1 max-[1280px]:hidden'>{t('common.environment.testing')}</div>
|
<div className='ml-1 max-[1280px]:hidden'>{t('common.environment.testing')}</div>
|
||||||
@@ -32,7 +32,7 @@ const EnvNav = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
langeniusVersionInfo.current_env === 'DEVELOPMENT' && (
|
langGeniusVersionInfo.current_env === 'DEVELOPMENT' && (
|
||||||
<>
|
<>
|
||||||
<TerminalSquare className='h-3 w-3' />
|
<TerminalSquare className='h-3 w-3' />
|
||||||
<div className='ml-1 max-[1280px]:hidden'>{t('common.environment.development')}</div>
|
<div className='ml-1 max-[1280px]:hidden'>{t('common.environment.development')}</div>
|
||||||
|
@@ -48,7 +48,6 @@ const Installed: FC<Props> = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier)
|
if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier)
|
||||||
onInstalled()
|
onInstalled()
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [hasInstalled])
|
}, [hasInstalled])
|
||||||
|
|
||||||
const [isInstalling, setIsInstalling] = React.useState(false)
|
const [isInstalling, setIsInstalling] = React.useState(false)
|
||||||
@@ -105,12 +104,12 @@ const Installed: FC<Props> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { langeniusVersionInfo } = useAppContext()
|
const { langGeniusVersionInfo } = useAppContext()
|
||||||
const isDifyVersionCompatible = useMemo(() => {
|
const isDifyVersionCompatible = useMemo(() => {
|
||||||
if (!langeniusVersionInfo.current_version)
|
if (!langGeniusVersionInfo.current_version)
|
||||||
return true
|
return true
|
||||||
return gte(langeniusVersionInfo.current_version, payload.meta.minimum_dify_version ?? '0.0.0')
|
return gte(langGeniusVersionInfo.current_version, payload.meta.minimum_dify_version ?? '0.0.0')
|
||||||
}, [langeniusVersionInfo.current_version, payload.meta.minimum_dify_version])
|
}, [langGeniusVersionInfo.current_version, payload.meta.minimum_dify_version])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@@ -59,7 +59,6 @@ const Installed: FC<Props> = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier)
|
if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier)
|
||||||
onInstalled()
|
onInstalled()
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [hasInstalled])
|
}, [hasInstalled])
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
@@ -120,12 +119,12 @@ const Installed: FC<Props> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { langeniusVersionInfo } = useAppContext()
|
const { langGeniusVersionInfo } = useAppContext()
|
||||||
const { data: pluginDeclaration } = usePluginDeclarationFromMarketPlace(uniqueIdentifier)
|
const { data: pluginDeclaration } = usePluginDeclarationFromMarketPlace(uniqueIdentifier)
|
||||||
const isDifyVersionCompatible = useMemo(() => {
|
const isDifyVersionCompatible = useMemo(() => {
|
||||||
if (!pluginDeclaration || !langeniusVersionInfo.current_version) return true
|
if (!pluginDeclaration || !langGeniusVersionInfo.current_version) return true
|
||||||
return gte(langeniusVersionInfo.current_version, pluginDeclaration?.manifest.meta.minimum_dify_version ?? '0.0.0')
|
return gte(langGeniusVersionInfo.current_version, pluginDeclaration?.manifest.meta.minimum_dify_version ?? '0.0.0')
|
||||||
}, [langeniusVersionInfo.current_version, pluginDeclaration])
|
}, [langGeniusVersionInfo.current_version, pluginDeclaration])
|
||||||
|
|
||||||
const { canInstall } = useInstallPluginLimit({ ...payload, from: 'marketplace' })
|
const { canInstall } = useInstallPluginLimit({ ...payload, from: 'marketplace' })
|
||||||
return (
|
return (
|
||||||
|
@@ -62,13 +62,13 @@ const PluginItem: FC<Props> = ({
|
|||||||
return [PluginSource.github, PluginSource.marketplace].includes(source) ? author : ''
|
return [PluginSource.github, PluginSource.marketplace].includes(source) ? author : ''
|
||||||
}, [source, author])
|
}, [source, author])
|
||||||
|
|
||||||
const { langeniusVersionInfo } = useAppContext()
|
const { langGeniusVersionInfo } = useAppContext()
|
||||||
|
|
||||||
const isDifyVersionCompatible = useMemo(() => {
|
const isDifyVersionCompatible = useMemo(() => {
|
||||||
if (!langeniusVersionInfo.current_version)
|
if (!langGeniusVersionInfo.current_version)
|
||||||
return true
|
return true
|
||||||
return gte(langeniusVersionInfo.current_version, declarationMeta.minimum_dify_version ?? '0.0.0')
|
return gte(langGeniusVersionInfo.current_version, declarationMeta.minimum_dify_version ?? '0.0.0')
|
||||||
}, [declarationMeta.minimum_dify_version, langeniusVersionInfo.current_version])
|
}, [declarationMeta.minimum_dify_version, langGeniusVersionInfo.current_version])
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
refreshPluginList({ category } as any)
|
refreshPluginList({ category } as any)
|
||||||
|
@@ -5,9 +5,9 @@ import * as Sentry from '@sentry/react'
|
|||||||
|
|
||||||
const isDevelopment = process.env.NODE_ENV === 'development'
|
const isDevelopment = process.env.NODE_ENV === 'development'
|
||||||
|
|
||||||
const SentryInit = ({
|
const SentryInitializer = ({
|
||||||
children,
|
children,
|
||||||
}: { children: React.ReactNode }) => {
|
}: { children: React.ReactElement }) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const SENTRY_DSN = document?.body?.getAttribute('data-public-sentry-dsn')
|
const SENTRY_DSN = document?.body?.getAttribute('data-public-sentry-dsn')
|
||||||
if (!isDevelopment && SENTRY_DSN) {
|
if (!isDevelopment && SENTRY_DSN) {
|
||||||
@@ -26,4 +26,4 @@ const SentryInit = ({
|
|||||||
return children
|
return children
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SentryInit
|
export default SentryInitializer
|
@@ -10,12 +10,12 @@ import {
|
|||||||
EDUCATION_VERIFY_URL_SEARCHPARAMS_ACTION,
|
EDUCATION_VERIFY_URL_SEARCHPARAMS_ACTION,
|
||||||
} from '@/app/education-apply/constants'
|
} from '@/app/education-apply/constants'
|
||||||
|
|
||||||
type SwrInitorProps = {
|
type SwrInitializerProps = {
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
}
|
}
|
||||||
const SwrInitor = ({
|
const SwrInitializer = ({
|
||||||
children,
|
children,
|
||||||
}: SwrInitorProps) => {
|
}: SwrInitializerProps) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
const consoleToken = decodeURIComponent(searchParams.get('access_token') || '')
|
const consoleToken = decodeURIComponent(searchParams.get('access_token') || '')
|
||||||
@@ -86,4 +86,4 @@ const SwrInitor = ({
|
|||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SwrInitor
|
export default SwrInitializer
|
@@ -1,10 +1,10 @@
|
|||||||
import RoutePrefixHandle from './routePrefixHandle'
|
import RoutePrefixHandle from './routePrefixHandle'
|
||||||
import type { Viewport } from 'next'
|
import type { Viewport } from 'next'
|
||||||
import I18nServer from './components/i18n-server'
|
import I18nServer from './components/i18n-server'
|
||||||
import BrowserInitor from './components/browser-initor'
|
import BrowserInitializer from './components/browser-initializer'
|
||||||
import SentryInitor from './components/sentry-initor'
|
import SentryInitializer from './components/sentry-initializer'
|
||||||
import { getLocaleOnServer } from '@/i18n/server'
|
import { getLocaleOnServer } from '@/i18n/server'
|
||||||
import { TanstackQueryIniter } from '@/context/query-client'
|
import { TanstackQueryInitializer } from '@/context/query-client'
|
||||||
import { ThemeProvider } from 'next-themes'
|
import { ThemeProvider } from 'next-themes'
|
||||||
import './styles/globals.css'
|
import './styles/globals.css'
|
||||||
import './styles/markdown.scss'
|
import './styles/markdown.scss'
|
||||||
@@ -62,9 +62,9 @@ const LocaleLayout = async ({
|
|||||||
className="color-scheme h-full select-auto"
|
className="color-scheme h-full select-auto"
|
||||||
{...datasetMap}
|
{...datasetMap}
|
||||||
>
|
>
|
||||||
<BrowserInitor>
|
<BrowserInitializer>
|
||||||
<SentryInitor>
|
<SentryInitializer>
|
||||||
<TanstackQueryIniter>
|
<TanstackQueryInitializer>
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
attribute='data-theme'
|
attribute='data-theme'
|
||||||
defaultTheme='system'
|
defaultTheme='system'
|
||||||
@@ -77,9 +77,9 @@ const LocaleLayout = async ({
|
|||||||
</GlobalPublicStoreProvider>
|
</GlobalPublicStoreProvider>
|
||||||
</I18nServer>
|
</I18nServer>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</TanstackQueryIniter>
|
</TanstackQueryInitializer>
|
||||||
</SentryInitor>
|
</SentryInitializer>
|
||||||
</BrowserInitor>
|
</BrowserInitializer>
|
||||||
<RoutePrefixHandle />
|
<RoutePrefixHandle />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@@ -1,20 +1,15 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { createRef, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
import { createContext, useContext, useContextSelector } from 'use-context-selector'
|
import { createContext, useContext, useContextSelector } from 'use-context-selector'
|
||||||
import type { FC, ReactNode } from 'react'
|
import type { FC, ReactNode } from 'react'
|
||||||
import { fetchAppList } from '@/service/apps'
|
import { fetchCurrentWorkspace, fetchLangGeniusVersion, fetchUserProfile } from '@/service/common'
|
||||||
import Loading from '@/app/components/base/loading'
|
|
||||||
import { fetchCurrentWorkspace, fetchLanggeniusVersion, fetchUserProfile } from '@/service/common'
|
|
||||||
import type { App } from '@/types/app'
|
|
||||||
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
|
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
|
||||||
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
|
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
|
||||||
import { noop } from 'lodash-es'
|
import { noop } from 'lodash-es'
|
||||||
|
|
||||||
export type AppContextValue = {
|
export type AppContextValue = {
|
||||||
apps: App[]
|
|
||||||
mutateApps: VoidFunction
|
|
||||||
userProfile: UserProfileResponse
|
userProfile: UserProfileResponse
|
||||||
mutateUserProfile: VoidFunction
|
mutateUserProfile: VoidFunction
|
||||||
currentWorkspace: ICurrentWorkspace
|
currentWorkspace: ICurrentWorkspace
|
||||||
@@ -23,13 +18,21 @@ export type AppContextValue = {
|
|||||||
isCurrentWorkspaceEditor: boolean
|
isCurrentWorkspaceEditor: boolean
|
||||||
isCurrentWorkspaceDatasetOperator: boolean
|
isCurrentWorkspaceDatasetOperator: boolean
|
||||||
mutateCurrentWorkspace: VoidFunction
|
mutateCurrentWorkspace: VoidFunction
|
||||||
pageContainerRef: React.RefObject<HTMLDivElement>
|
langGeniusVersionInfo: LangGeniusVersionResponse
|
||||||
langeniusVersionInfo: LangGeniusVersionResponse
|
|
||||||
useSelector: typeof useSelector
|
useSelector: typeof useSelector
|
||||||
isLoadingCurrentWorkspace: boolean
|
isLoadingCurrentWorkspace: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialLangeniusVersionInfo = {
|
const userProfilePlaceholder = {
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
avatar: '',
|
||||||
|
avatar_url: '',
|
||||||
|
is_password_set: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialLangGeniusVersionInfo = {
|
||||||
current_env: '',
|
current_env: '',
|
||||||
current_version: '',
|
current_version: '',
|
||||||
latest_version: '',
|
latest_version: '',
|
||||||
@@ -50,16 +53,7 @@ const initialWorkspaceInfo: ICurrentWorkspace = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const AppContext = createContext<AppContextValue>({
|
const AppContext = createContext<AppContextValue>({
|
||||||
apps: [],
|
userProfile: userProfilePlaceholder,
|
||||||
mutateApps: noop,
|
|
||||||
userProfile: {
|
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
email: '',
|
|
||||||
avatar: '',
|
|
||||||
avatar_url: '',
|
|
||||||
is_password_set: false,
|
|
||||||
},
|
|
||||||
currentWorkspace: initialWorkspaceInfo,
|
currentWorkspace: initialWorkspaceInfo,
|
||||||
isCurrentWorkspaceManager: false,
|
isCurrentWorkspaceManager: false,
|
||||||
isCurrentWorkspaceOwner: false,
|
isCurrentWorkspaceOwner: false,
|
||||||
@@ -67,8 +61,7 @@ const AppContext = createContext<AppContextValue>({
|
|||||||
isCurrentWorkspaceDatasetOperator: false,
|
isCurrentWorkspaceDatasetOperator: false,
|
||||||
mutateUserProfile: noop,
|
mutateUserProfile: noop,
|
||||||
mutateCurrentWorkspace: noop,
|
mutateCurrentWorkspace: noop,
|
||||||
pageContainerRef: createRef(),
|
langGeniusVersionInfo: initialLangGeniusVersionInfo,
|
||||||
langeniusVersionInfo: initialLangeniusVersionInfo,
|
|
||||||
useSelector,
|
useSelector,
|
||||||
isLoadingCurrentWorkspace: false,
|
isLoadingCurrentWorkspace: false,
|
||||||
})
|
})
|
||||||
@@ -82,14 +75,11 @@ export type AppContextProviderProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) => {
|
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: userProfileResponse, mutate: mutateUserProfile } = useSWR({ url: '/account/profile', params: {} }, fetchUserProfile)
|
||||||
const { data: currentWorkspaceResponse, mutate: mutateCurrentWorkspace, isLoading: isLoadingCurrentWorkspace } = useSWR({ url: '/workspaces/current', params: {} }, fetchCurrentWorkspace)
|
const { data: currentWorkspaceResponse, mutate: mutateCurrentWorkspace, isLoading: isLoadingCurrentWorkspace } = useSWR({ url: '/workspaces/current', params: {} }, fetchCurrentWorkspace)
|
||||||
|
|
||||||
const [userProfile, setUserProfile] = useState<UserProfileResponse>()
|
const [userProfile, setUserProfile] = useState<UserProfileResponse>(userProfilePlaceholder)
|
||||||
const [langeniusVersionInfo, setLangeniusVersionInfo] = useState<LangGeniusVersionResponse>(initialLangeniusVersionInfo)
|
const [langGeniusVersionInfo, setLangGeniusVersionInfo] = useState<LangGeniusVersionResponse>(initialLangGeniusVersionInfo)
|
||||||
const [currentWorkspace, setCurrentWorkspace] = useState<ICurrentWorkspace>(initialWorkspaceInfo)
|
const [currentWorkspace, setCurrentWorkspace] = useState<ICurrentWorkspace>(initialWorkspaceInfo)
|
||||||
const isCurrentWorkspaceManager = useMemo(() => ['owner', 'admin'].includes(currentWorkspace.role), [currentWorkspace.role])
|
const isCurrentWorkspaceManager = useMemo(() => ['owner', 'admin'].includes(currentWorkspace.role), [currentWorkspace.role])
|
||||||
const isCurrentWorkspaceOwner = useMemo(() => currentWorkspace.role === 'owner', [currentWorkspace.role])
|
const isCurrentWorkspaceOwner = useMemo(() => currentWorkspace.role === 'owner', [currentWorkspace.role])
|
||||||
@@ -101,8 +91,8 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
|||||||
setUserProfile(result)
|
setUserProfile(result)
|
||||||
const current_version = userProfileResponse.headers.get('x-version')
|
const current_version = userProfileResponse.headers.get('x-version')
|
||||||
const current_env = process.env.NODE_ENV === 'development' ? 'DEVELOPMENT' : userProfileResponse.headers.get('x-env')
|
const current_env = process.env.NODE_ENV === 'development' ? 'DEVELOPMENT' : userProfileResponse.headers.get('x-env')
|
||||||
const versionData = await fetchLanggeniusVersion({ url: '/version', params: { current_version } })
|
const versionData = await fetchLangGeniusVersion({ url: '/version', params: { current_version } })
|
||||||
setLangeniusVersionInfo({ ...versionData, current_version, latest_version: versionData.version, current_env })
|
setLangGeniusVersionInfo({ ...versionData, current_version, latest_version: versionData.version, current_env })
|
||||||
}
|
}
|
||||||
}, [userProfileResponse])
|
}, [userProfileResponse])
|
||||||
|
|
||||||
@@ -115,17 +105,11 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
|||||||
setCurrentWorkspace(currentWorkspaceResponse)
|
setCurrentWorkspace(currentWorkspaceResponse)
|
||||||
}, [currentWorkspaceResponse])
|
}, [currentWorkspaceResponse])
|
||||||
|
|
||||||
if (!appList || !userProfile)
|
|
||||||
return <Loading type='app' />
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppContext.Provider value={{
|
<AppContext.Provider value={{
|
||||||
apps: appList.data,
|
|
||||||
mutateApps,
|
|
||||||
userProfile,
|
userProfile,
|
||||||
mutateUserProfile,
|
mutateUserProfile,
|
||||||
pageContainerRef,
|
langGeniusVersionInfo,
|
||||||
langeniusVersionInfo,
|
|
||||||
useSelector,
|
useSelector,
|
||||||
currentWorkspace,
|
currentWorkspace,
|
||||||
isCurrentWorkspaceManager,
|
isCurrentWorkspaceManager,
|
||||||
@@ -137,7 +121,7 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
|||||||
}}>
|
}}>
|
||||||
<div className='flex h-full flex-col overflow-y-auto'>
|
<div className='flex h-full flex-col overflow-y-auto'>
|
||||||
{globalThis.document?.body?.getAttribute('data-public-maintenance-notice') && <MaintenanceNotice />}
|
{globalThis.document?.body?.getAttribute('data-public-maintenance-notice') && <MaintenanceNotice />}
|
||||||
<div ref={pageContainerRef} className='relative flex grow flex-col overflow-y-auto overflow-x-hidden bg-background-body'>
|
<div className='relative flex grow flex-col overflow-y-auto overflow-x-hidden bg-background-body'>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -14,7 +14,7 @@ const client = new QueryClient({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const TanstackQueryIniter: FC<PropsWithChildren> = (props) => {
|
export const TanstackQueryInitializer: FC<PropsWithChildren> = (props) => {
|
||||||
const { children } = props
|
const { children } = props
|
||||||
return <QueryClientProvider client={client}>
|
return <QueryClientProvider client={client}>
|
||||||
{children}
|
{children}
|
||||||
|
@@ -88,7 +88,7 @@ export const logout: Fetcher<CommonResponse, { url: string; params: Record<strin
|
|||||||
return get<CommonResponse>(url, params)
|
return get<CommonResponse>(url, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchLanggeniusVersion: Fetcher<LangGeniusVersionResponse, { url: string; params: Record<string, any> }> = ({ url, params }) => {
|
export const fetchLangGeniusVersion: Fetcher<LangGeniusVersionResponse, { url: string; params: Record<string, any> }> = ({ url, params }) => {
|
||||||
return get<LangGeniusVersionResponse>(url, { params })
|
return get<LangGeniusVersionResponse>(url, { params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user