mirror of
https://github.com/langgenius/dify.git
synced 2026-09-08 11:04:27 +08:00
refactor(web): move app context layout styles to shell (#38511)
This commit is contained in:
parent
31b17513c2
commit
2c6ec1a761
@ -1,8 +1,9 @@
|
|||||||
import type { ReactNode } from 'react'
|
import * as React from 'react'
|
||||||
import AmplitudeProvider from '@/app/components/base/amplitude'
|
import AmplitudeProvider from '@/app/components/base/amplitude'
|
||||||
import { GoogleAnalyticsScripts } from '@/app/components/base/ga'
|
import { GoogleAnalyticsScripts } from '@/app/components/base/ga'
|
||||||
import Zendesk from '@/app/components/base/zendesk'
|
import Zendesk from '@/app/components/base/zendesk'
|
||||||
import { EducationVerifyActionRecorder } from '@/app/components/education-verify-action-recorder'
|
import { EducationVerifyActionRecorder } from '@/app/components/education-verify-action-recorder'
|
||||||
|
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
|
||||||
import MainNavLayout from '@/app/components/main-nav/layout'
|
import MainNavLayout from '@/app/components/main-nav/layout'
|
||||||
import { NextRouteStateBridge } from '@/app/components/next-route-state'
|
import { NextRouteStateBridge } from '@/app/components/next-route-state'
|
||||||
import { OAuthRegistrationAnalytics } from '@/app/components/oauth-registration-analytics'
|
import { OAuthRegistrationAnalytics } from '@/app/components/oauth-registration-analytics'
|
||||||
@ -17,32 +18,35 @@ export default async function Layout({
|
|||||||
children,
|
children,
|
||||||
detailSidebar,
|
detailSidebar,
|
||||||
}: {
|
}: {
|
||||||
children: ReactNode
|
children: React.ReactNode
|
||||||
detailSidebar: ReactNode
|
detailSidebar: React.ReactNode
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<>
|
<React.Fragment>
|
||||||
<GoogleAnalyticsScripts />
|
<GoogleAnalyticsScripts />
|
||||||
<AmplitudeProvider />
|
<AmplitudeProvider />
|
||||||
<OAuthRegistrationAnalytics />
|
<OAuthRegistrationAnalytics />
|
||||||
<EducationVerifyActionRecorder />
|
<EducationVerifyActionRecorder />
|
||||||
<CommonLayoutHydrationBoundary>
|
<CommonLayoutHydrationBoundary>
|
||||||
<NextRouteStateBridge>
|
<NextRouteStateBridge>
|
||||||
<AppContextProvider>
|
<div className="flex h-full flex-col overflow-hidden">
|
||||||
<EventEmitterContextProvider>
|
<MaintenanceNotice />
|
||||||
<ProviderContextProvider>
|
<AppContextProvider>
|
||||||
<ModalContextProvider>
|
<EventEmitterContextProvider>
|
||||||
<MainNavLayout detailSidebar={detailSidebar}>
|
<ProviderContextProvider>
|
||||||
{children}
|
<ModalContextProvider>
|
||||||
</MainNavLayout>
|
<MainNavLayout detailSidebar={detailSidebar}>
|
||||||
<CommonLayoutGlobalMounts />
|
{children}
|
||||||
</ModalContextProvider>
|
</MainNavLayout>
|
||||||
</ProviderContextProvider>
|
<CommonLayoutGlobalMounts />
|
||||||
</EventEmitterContextProvider>
|
</ModalContextProvider>
|
||||||
</AppContextProvider>
|
</ProviderContextProvider>
|
||||||
|
</EventEmitterContextProvider>
|
||||||
|
</AppContextProvider>
|
||||||
|
</div>
|
||||||
</NextRouteStateBridge>
|
</NextRouteStateBridge>
|
||||||
</CommonLayoutHydrationBoundary>
|
</CommonLayoutHydrationBoundary>
|
||||||
<Zendesk />
|
<Zendesk />
|
||||||
</>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import type { ReactNode } from 'react'
|
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { CommonLayoutHydrationBoundary } from '@/app/(commonLayout)/hydration-boundary'
|
import { CommonLayoutHydrationBoundary } from '@/app/(commonLayout)/hydration-boundary'
|
||||||
import AmplitudeProvider from '@/app/components/base/amplitude'
|
import AmplitudeProvider from '@/app/components/base/amplitude'
|
||||||
import { GoogleAnalyticsScripts } from '@/app/components/base/ga'
|
import { GoogleAnalyticsScripts } from '@/app/components/base/ga'
|
||||||
import { EducationVerifyActionRecorder } from '@/app/components/education-verify-action-recorder'
|
import { EducationVerifyActionRecorder } from '@/app/components/education-verify-action-recorder'
|
||||||
import HeaderWrapper from '@/app/components/header/header-wrapper'
|
import HeaderWrapper from '@/app/components/header/header-wrapper'
|
||||||
|
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
|
||||||
import { OAuthRegistrationAnalytics } from '@/app/components/oauth-registration-analytics'
|
import { OAuthRegistrationAnalytics } from '@/app/components/oauth-registration-analytics'
|
||||||
import { AppContextProvider } from '@/context/app-context-provider'
|
import { AppContextProvider } from '@/context/app-context-provider'
|
||||||
import { EventEmitterContextProvider } from '@/context/event-emitter-provider'
|
import { EventEmitterContextProvider } from '@/context/event-emitter-provider'
|
||||||
@ -12,30 +12,32 @@ import { ModalContextProvider } from '@/context/modal-context-provider'
|
|||||||
import { ProviderContextProvider } from '@/context/provider-context-provider'
|
import { ProviderContextProvider } from '@/context/provider-context-provider'
|
||||||
import Header from './header'
|
import Header from './header'
|
||||||
|
|
||||||
const Layout = async ({ children }: { children: ReactNode }) => {
|
export default async function Layout({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<React.Fragment>
|
||||||
<GoogleAnalyticsScripts />
|
<GoogleAnalyticsScripts />
|
||||||
<AmplitudeProvider />
|
<AmplitudeProvider />
|
||||||
<OAuthRegistrationAnalytics />
|
<OAuthRegistrationAnalytics />
|
||||||
<EducationVerifyActionRecorder />
|
<EducationVerifyActionRecorder />
|
||||||
<CommonLayoutHydrationBoundary>
|
<CommonLayoutHydrationBoundary>
|
||||||
<AppContextProvider>
|
<div className="flex h-full flex-col overflow-hidden bg-background-body">
|
||||||
<EventEmitterContextProvider>
|
<MaintenanceNotice />
|
||||||
<ProviderContextProvider>
|
<AppContextProvider>
|
||||||
<ModalContextProvider>
|
<EventEmitterContextProvider>
|
||||||
<HeaderWrapper>
|
<ProviderContextProvider>
|
||||||
<Header />
|
<ModalContextProvider>
|
||||||
</HeaderWrapper>
|
<HeaderWrapper>
|
||||||
<div className="relative flex h-0 shrink-0 grow flex-col overflow-y-auto bg-components-panel-bg">
|
<Header />
|
||||||
{children}
|
</HeaderWrapper>
|
||||||
</div>
|
<div className="relative flex h-0 min-h-0 shrink-0 grow flex-col overflow-y-auto bg-components-panel-bg">
|
||||||
</ModalContextProvider>
|
{children}
|
||||||
</ProviderContextProvider>
|
</div>
|
||||||
</EventEmitterContextProvider>
|
</ModalContextProvider>
|
||||||
</AppContextProvider>
|
</ProviderContextProvider>
|
||||||
|
</EventEmitterContextProvider>
|
||||||
|
</AppContextProvider>
|
||||||
|
</div>
|
||||||
</CommonLayoutHydrationBoundary>
|
</CommonLayoutHydrationBoundary>
|
||||||
</>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
export default Layout
|
|
||||||
|
|||||||
@ -4,10 +4,18 @@ import { useLanguage } from '@/app/components/header/account-setting/model-provi
|
|||||||
import { NOTICE_I18N } from '@/i18n-config/language'
|
import { NOTICE_I18N } from '@/i18n-config/language'
|
||||||
import MaintenanceNotice from '../maintenance-notice'
|
import MaintenanceNotice from '../maintenance-notice'
|
||||||
|
|
||||||
|
const mockEnv = vi.hoisted(() => ({
|
||||||
|
NEXT_PUBLIC_MAINTENANCE_NOTICE: 'true',
|
||||||
|
}))
|
||||||
|
|
||||||
vi.mock('@/app/components/base/icons/src/vender/line/general', () => ({
|
vi.mock('@/app/components/base/icons/src/vender/line/general', () => ({
|
||||||
X: (props: React.SVGProps<SVGSVGElement>) => <svg {...props} />,
|
X: (props: React.SVGProps<SVGSVGElement>) => <svg {...props} />,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
vi.mock('@/env', () => ({
|
||||||
|
env: mockEnv,
|
||||||
|
}))
|
||||||
|
|
||||||
vi.mock(
|
vi.mock(
|
||||||
'@/app/components/header/account-setting/model-provider-page/hooks',
|
'@/app/components/header/account-setting/model-provider-page/hooks',
|
||||||
() => ({
|
() => ({
|
||||||
@ -44,6 +52,7 @@ describe('MaintenanceNotice', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks()
|
vi.clearAllMocks()
|
||||||
localStorage.clear()
|
localStorage.clear()
|
||||||
|
mockEnv.NEXT_PUBLIC_MAINTENANCE_NOTICE = 'true'
|
||||||
vi.mocked(useLanguage).mockReturnValue('en_US')
|
vi.mocked(useLanguage).mockReturnValue('en_US')
|
||||||
setNoticeHref('#')
|
setNoticeHref('#')
|
||||||
})
|
})
|
||||||
@ -71,6 +80,14 @@ describe('MaintenanceNotice', () => {
|
|||||||
const { container } = render(<MaintenanceNotice />)
|
const { container } = render(<MaintenanceNotice />)
|
||||||
expect(container.firstChild).toBeNull()
|
expect(container.firstChild).toBeNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should not render when the notice env flag is disabled', () => {
|
||||||
|
mockEnv.NEXT_PUBLIC_MAINTENANCE_NOTICE = ''
|
||||||
|
|
||||||
|
const { container } = render(<MaintenanceNotice />)
|
||||||
|
|
||||||
|
expect(container.firstChild).toBeNull()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('User Interactions', () => {
|
describe('User Interactions', () => {
|
||||||
|
|||||||
@ -1,11 +1,21 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { X } from '@/app/components/base/icons/src/vender/line/general'
|
import { X } from '@/app/components/base/icons/src/vender/line/general'
|
||||||
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||||
|
import { env } from '@/env'
|
||||||
import { NOTICE_I18N } from '@/i18n-config/language'
|
import { NOTICE_I18N } from '@/i18n-config/language'
|
||||||
import { useHideMaintenanceNotice } from './storage'
|
import { useHideMaintenanceNotice } from './storage'
|
||||||
|
|
||||||
const MaintenanceNotice = () => {
|
function MaintenanceNotice() {
|
||||||
|
if (!env.NEXT_PUBLIC_MAINTENANCE_NOTICE)
|
||||||
|
return null
|
||||||
|
|
||||||
|
return <MaintenanceNoticeContent />
|
||||||
|
}
|
||||||
|
|
||||||
|
function MaintenanceNoticeContent() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const locale = useLanguage()
|
const locale = useLanguage()
|
||||||
|
|
||||||
|
|||||||
@ -2,14 +2,13 @@
|
|||||||
|
|
||||||
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
||||||
import type { PostWorkspacesCurrentResponse } from '@dify/contracts/api/console/workspaces/types.gen'
|
import type { PostWorkspacesCurrentResponse } from '@dify/contracts/api/console/workspaces/types.gen'
|
||||||
import type { FC, ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
import type { ICurrentWorkspace, LangGeniusVersionResponse } from '@/models/common'
|
import type { ICurrentWorkspace, LangGeniusVersionResponse } from '@/models/common'
|
||||||
import { useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query'
|
import { useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query'
|
||||||
import { useCallback, useEffect, useMemo } from 'react'
|
import { useCallback, useEffect, useMemo } from 'react'
|
||||||
import { setUserId, setUserProperties } from '@/app/components/base/amplitude'
|
import { setUserId, setUserProperties } from '@/app/components/base/amplitude'
|
||||||
import { flushRegistrationSuccess } from '@/app/components/base/amplitude/registration-tracking'
|
import { flushRegistrationSuccess } from '@/app/components/base/amplitude/registration-tracking'
|
||||||
import { setZendeskConversationFields } from '@/app/components/base/zendesk/utils'
|
import { setZendeskConversationFields } from '@/app/components/base/zendesk/utils'
|
||||||
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
|
|
||||||
import { ZENDESK_FIELD_IDS } from '@/config'
|
import { ZENDESK_FIELD_IDS } from '@/config'
|
||||||
import {
|
import {
|
||||||
AppContext,
|
AppContext,
|
||||||
@ -18,7 +17,6 @@ import {
|
|||||||
userProfilePlaceholder,
|
userProfilePlaceholder,
|
||||||
useSelector,
|
useSelector,
|
||||||
} from '@/context/app-context'
|
} from '@/context/app-context'
|
||||||
import { env } from '@/env'
|
|
||||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||||
import { useWorkspacePermissionKeys } from '@/service/access-control/use-permission-keys'
|
import { useWorkspacePermissionKeys } from '@/service/access-control/use-permission-keys'
|
||||||
@ -66,7 +64,7 @@ const normalizeCurrentWorkspace = (workspace?: PostWorkspacesCurrentResponse): I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) => {
|
export function AppContextProvider({ children }: AppContextProviderProps) {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
|
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
|
||||||
const { data: userProfileResp } = useSuspenseQuery(userProfileQueryOptions())
|
const { data: userProfileResp } = useSuspenseQuery(userProfileQueryOptions())
|
||||||
@ -192,12 +190,7 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
|||||||
workspacePermissionKeys: workspacePermissionKeysQuery.data?.workspace.permission_keys ?? emptyWorkspacePermissionKeys,
|
workspacePermissionKeys: workspacePermissionKeysQuery.data?.workspace.permission_keys ?? emptyWorkspacePermissionKeys,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex h-full flex-col overflow-hidden">
|
{children}
|
||||||
{env.NEXT_PUBLIC_MAINTENANCE_NOTICE && <MaintenanceNotice />}
|
|
||||||
<div className="relative flex h-0 min-h-0 grow flex-col overflow-hidden bg-background-body">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AppContext.Provider>
|
</AppContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user