mirror of
https://github.com/langgenius/dify.git
synced 2026-06-07 16:23:44 +08:00
feat(web): create system-features vertical (#36894)
This commit is contained in:
parent
fc7716704d
commit
8fc2807194
@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { pluginInstallLimit } from '@/app/components/plugins/install-plugin/hooks/use-install-plugin-limit'
|
||||
import { InstallationScope } from '@/types/feature'
|
||||
import { InstallationScope } from '@/features/system-features/constants'
|
||||
|
||||
describe('Plugin Marketplace to Install Flow', () => {
|
||||
describe('install permission validation pipeline', () => {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import type { RenderHookOptions, RenderHookResult, RenderOptions, RenderResult } from '@testing-library/react'
|
||||
import type { ReactElement, ReactNode } from 'react'
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { render, renderHook } from '@testing-library/react'
|
||||
import { defaultSystemFeatures } from '@/features/system-features/config'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { defaultSystemFeatures } from '@/types/feature'
|
||||
|
||||
type QueryKeyProvider = {
|
||||
queryKey: () => readonly unknown[]
|
||||
@ -40,9 +40,9 @@ type DeepPartial<T> = T extends Array<infer U>
|
||||
: T
|
||||
|
||||
const buildSystemFeatures = (
|
||||
overrides: DeepPartial<SystemFeatures> = {},
|
||||
): SystemFeatures => {
|
||||
const o = overrides as Partial<SystemFeatures>
|
||||
overrides: DeepPartial<GetSystemFeaturesResponse> = {},
|
||||
): GetSystemFeaturesResponse => {
|
||||
const o = overrides as Partial<GetSystemFeaturesResponse>
|
||||
return {
|
||||
...defaultSystemFeatures,
|
||||
...o,
|
||||
@ -65,6 +65,14 @@ const buildSystemFeatures = (
|
||||
license: {
|
||||
...defaultSystemFeatures.license,
|
||||
...(o.license ?? {}),
|
||||
workspaces: {
|
||||
...defaultSystemFeatures.license.workspaces,
|
||||
...(o.license?.workspaces ?? {}),
|
||||
},
|
||||
},
|
||||
plugin_manager: {
|
||||
...defaultSystemFeatures.plugin_manager,
|
||||
...(o.plugin_manager ?? {}),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -90,10 +98,10 @@ export const createTestQueryClient = (): QueryClient =>
|
||||
|
||||
export const seedSystemFeatures = (
|
||||
queryClient: QueryClient,
|
||||
overrides: DeepPartial<SystemFeatures> = {},
|
||||
): SystemFeatures => {
|
||||
overrides: DeepPartial<GetSystemFeaturesResponse> = {},
|
||||
): GetSystemFeaturesResponse => {
|
||||
const data = buildSystemFeatures(overrides)
|
||||
queryClient.setQueryData(consoleQuery.systemFeatures.queryKey(), data)
|
||||
queryClient.setQueryData(consoleQuery.systemFeatures.get.queryKey(), data)
|
||||
return data
|
||||
}
|
||||
|
||||
@ -118,7 +126,7 @@ type SystemFeaturesTestOptions = {
|
||||
* `useSuspenseQuery` resolve immediately. Pass `null` to skip seeding and
|
||||
* keep the systemFeatures query in the pending state.
|
||||
*/
|
||||
systemFeatures?: DeepPartial<SystemFeatures> | null
|
||||
systemFeatures?: DeepPartial<GetSystemFeaturesResponse> | null
|
||||
trialModels?: readonly string[] | null
|
||||
/**
|
||||
* Seed the workflow clipboard DSL version query only for tests that need it.
|
||||
@ -130,7 +138,7 @@ type SystemFeaturesTestOptions = {
|
||||
|
||||
type SystemFeaturesWrapper = {
|
||||
queryClient: QueryClient
|
||||
systemFeatures: SystemFeatures | null
|
||||
systemFeatures: GetSystemFeaturesResponse | null
|
||||
wrapper: (props: { children: ReactNode }) => ReactElement
|
||||
}
|
||||
|
||||
@ -154,7 +162,7 @@ export const createSystemFeaturesWrapper = (
|
||||
export const renderWithSystemFeatures = (
|
||||
ui: ReactElement,
|
||||
options: SystemFeaturesTestOptions & Omit<RenderOptions, 'wrapper'> = {},
|
||||
): RenderResult & { queryClient: QueryClient, systemFeatures: SystemFeatures | null } => {
|
||||
): RenderResult & { queryClient: QueryClient, systemFeatures: GetSystemFeaturesResponse | null } => {
|
||||
const { systemFeatures: sf, trialModels, appDslVersion, queryClient: qc, ...renderOptions } = options
|
||||
const { wrapper, queryClient, systemFeatures } = createSystemFeaturesWrapper({
|
||||
systemFeatures: sf,
|
||||
@ -169,7 +177,7 @@ export const renderWithSystemFeatures = (
|
||||
export const renderHookWithSystemFeatures = <Result, Props = void>(
|
||||
callback: (props: Props) => Result,
|
||||
options: SystemFeaturesTestOptions & Omit<RenderHookOptions<Props>, 'wrapper'> = {},
|
||||
): RenderHookResult<Result, Props> & { queryClient: QueryClient, systemFeatures: SystemFeatures | null } => {
|
||||
): RenderHookResult<Result, Props> & { queryClient: QueryClient, systemFeatures: GetSystemFeaturesResponse | null } => {
|
||||
const { systemFeatures: sf, trialModels, appDslVersion, queryClient: qc, ...hookOptions } = options
|
||||
const { wrapper, queryClient, systemFeatures } = createSystemFeaturesWrapper({
|
||||
systemFeatures: sf,
|
||||
|
||||
@ -51,7 +51,7 @@ vi.mock('@/service/server', () => ({
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/service/server-system-features', () => ({
|
||||
vi.mock('@/features/system-features/server', () => ({
|
||||
serverSystemFeaturesQueryOptions: () => ({
|
||||
queryKey: ['console', 'system-features'],
|
||||
queryFn: mocks.systemFeaturesQueryFn,
|
||||
|
||||
@ -2,10 +2,10 @@ import type { ReactNode } from 'react'
|
||||
import { dehydrate, HydrationBoundary } from '@tanstack/react-query'
|
||||
import { getQueryClientServer } from '@/context/query-client-server'
|
||||
import { serverUserProfileQueryOptions } from '@/features/account-profile/server'
|
||||
import { serverSystemFeaturesQueryOptions } from '@/features/system-features/server'
|
||||
import { headers } from '@/next/headers'
|
||||
import { redirect } from '@/next/navigation'
|
||||
import { getServerConsoleClientContext, resolveServerConsoleApiUrl, serverConsoleQuery } from '@/service/server'
|
||||
import { serverSystemFeaturesQueryOptions } from '@/service/server-system-features'
|
||||
import { basePath } from '@/utils/var'
|
||||
|
||||
const CURRENT_PATHNAME_HEADER = 'x-dify-pathname'
|
||||
|
||||
@ -3,7 +3,7 @@ import { cn } from '@langgenius/dify-ui/cn'
|
||||
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import Header from '@/app/signin/_header'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
|
||||
export default function SignInLayout({ children }: any) {
|
||||
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
|
||||
|
||||
@ -5,10 +5,10 @@ import * as React from 'react'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import AppUnavailable from '@/app/components/base/app-unavailable'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { SSOProtocol } from '@/features/system-features/constants'
|
||||
import { useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { fetchWebOAuth2SSOUrl, fetchWebOIDCSSOUrl, fetchWebSAMLSSOUrl } from '@/service/share'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { SSOProtocol } from '@/types/feature'
|
||||
|
||||
const ExternalMemberSSOAuth = () => {
|
||||
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
|
||||
|
||||
@ -5,12 +5,12 @@ import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security'
|
||||
import { SSOProtocol } from '@/features/system-features/constants'
|
||||
import { useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { fetchMembersOAuth2SSOUrl, fetchMembersOIDCSSOUrl, fetchMembersSAMLSSOUrl } from '@/service/share'
|
||||
import { SSOProtocol } from '@/types/feature'
|
||||
|
||||
type SSOAuthProps = {
|
||||
protocol: SSOProtocol | ''
|
||||
protocol: string
|
||||
}
|
||||
|
||||
const SSOAuth: FC<SSOAuthProps> = ({
|
||||
|
||||
@ -4,8 +4,8 @@ import type { PropsWithChildren } from 'react'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
|
||||
export default function SignInLayout({ children }: PropsWithChildren) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@ -7,9 +7,9 @@ import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { IS_CE_EDITION } from '@/config'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { LicenseStatus } from '@/features/system-features/constants'
|
||||
import Link from '@/next/link'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { LicenseStatus } from '@/types/feature'
|
||||
import MailAndCodeAuth from './components/mail-and-code-auth'
|
||||
import MailAndPasswordAuth from './components/mail-and-password-auth'
|
||||
import SSOAuth from './components/sso-auth'
|
||||
|
||||
@ -6,9 +6,9 @@ import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import AppUnavailable from '@/app/components/base/app-unavailable'
|
||||
import { useWebAppStore } from '@/context/web-app-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
import { useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { webAppLogout } from '@/service/webapp-auth'
|
||||
import ExternalMemberSsoAuth from './components/external-member-sso-auth'
|
||||
import NormalForm from './normalForm'
|
||||
|
||||
@ -17,9 +17,9 @@ import Collapse from '@/app/components/header/account-setting/collapse'
|
||||
import { IS_CE_EDITION, validPassword } from '@/config'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { updateUserProfile } from '@/service/common'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import DeleteAccount from '../delete-account'
|
||||
|
||||
import AvatarWithEdit from './AvatarWithEdit'
|
||||
|
||||
@ -5,9 +5,9 @@ import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import Link from '@/next/link'
|
||||
import { useRouter } from '@/next/navigation'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import Avatar from './avatar'
|
||||
|
||||
const Header = () => {
|
||||
|
||||
@ -6,8 +6,8 @@ import Loading from '@/app/components/base/loading'
|
||||
import Header from '@/app/signin/_header'
|
||||
import { AppContextProvider } from '@/context/app-context-provider'
|
||||
import { isLegacyBase401, userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
|
||||
export default function SignInLayout({ children }: any) {
|
||||
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import * as React from 'react'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import Header from '../signin/_header'
|
||||
import ActivateForm from './activateForm'
|
||||
|
||||
|
||||
@ -8,9 +8,9 @@ import { RiBuildingLine, RiGlobalLine, RiVerifiedBadgeLine } from '@remixicon/re
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { AccessMode, SubjectType } from '@/models/access-control'
|
||||
import { useUpdateAccessMode } from '@/service/access-control'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import useAccessControlStore from '../../../../context/access-control-store'
|
||||
import AccessControlDialog from './access-control-dialog'
|
||||
import AccessControlItem from './access-control-item'
|
||||
|
||||
@ -35,13 +35,13 @@ import { collaborationManager } from '@/app/components/workflow/collaboration/co
|
||||
import { webSocketClient } from '@/app/components/workflow/collaboration/core/websocket-manager'
|
||||
import { WorkflowContext } from '@/app/components/workflow/context'
|
||||
import { appDefaultIconBackground } from '@/config'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useAsyncWindowOpen } from '@/hooks/use-async-window-open'
|
||||
import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
import { useAppWhiteListSubjects, useGetUserCanAccessApp } from '@/service/access-control'
|
||||
import { fetchAppDetailDirect, publishToCreatorsPlatform } from '@/service/apps'
|
||||
import { fetchInstalledAppList } from '@/service/explore'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useInvalidateAppWorkflow } from '@/service/use-workflow'
|
||||
import { fetchPublishedWorkflow } from '@/service/workflow'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
|
||||
@ -15,11 +15,11 @@ import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import SecretKeyButton from '@/app/components/develop/secret-key/secret-key-button'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useDocLink } from '@/context/i18n'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
import { usePathname, useRouter } from '@/next/navigation'
|
||||
import { useAppWhiteListSubjects } from '@/service/access-control'
|
||||
import { fetchAppDetailDirect } from '@/service/apps'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useAppWorkflow } from '@/service/use-workflow'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import { asyncRunSafe } from '@/utils'
|
||||
|
||||
@ -22,7 +22,9 @@ vi.mock('@/next/navigation', () => ({
|
||||
|
||||
vi.mock('@/service/client', () => ({
|
||||
consoleClient: {
|
||||
systemFeatures: vi.fn(),
|
||||
systemFeatures: {
|
||||
get: vi.fn(),
|
||||
},
|
||||
},
|
||||
consoleQuery: {
|
||||
apps: {
|
||||
@ -36,7 +38,9 @@ vi.mock('@/service/client', () => ({
|
||||
},
|
||||
},
|
||||
systemFeatures: {
|
||||
queryKey: () => ['console', 'systemFeatures'],
|
||||
get: {
|
||||
queryKey: () => ['console', 'systemFeatures', 'get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
@ -39,6 +39,7 @@ import { UserAvatarList } from '@/app/components/base/user-avatar-list'
|
||||
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { AppCardTags } from '@/features/tag-management/components/app-card-tags'
|
||||
import { useAsyncWindowOpen } from '@/hooks/use-async-window-open'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
@ -47,7 +48,6 @@ import { useRouter } from '@/next/navigation'
|
||||
import { useGetUserCanAccessApp } from '@/service/access-control'
|
||||
import { copyApp, exportAppConfig, updateAppInfo } from '@/service/apps'
|
||||
import { fetchInstalledAppList } from '@/service/explore'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useDeleteAppMutation } from '@/service/use-apps'
|
||||
import { fetchWorkflowDraft } from '@/service/workflow'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
|
||||
@ -12,12 +12,12 @@ import Input from '@/app/components/base/input'
|
||||
import TabSliderNew from '@/app/components/base/tab-slider-new'
|
||||
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { TagFilter } from '@/features/tag-management/components/tag-filter'
|
||||
import { CheckModal } from '@/hooks/use-pay'
|
||||
import dynamic from '@/next/dynamic'
|
||||
import { usePathname, useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import AppCard from './app-card'
|
||||
import { AppCardSkeleton } from './app-card-skeleton'
|
||||
|
||||
@ -22,7 +22,7 @@ import List from '@/app/components/base/chat/chat-with-history/sidebar/list'
|
||||
import RenameModal from '@/app/components/base/chat/chat-with-history/sidebar/rename-modal'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import MenuDropdown from '@/app/components/share/text-generation/menu-dropdown'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useChatWithHistoryContext } from '../context'
|
||||
|
||||
type Props = {
|
||||
|
||||
@ -10,7 +10,7 @@ import ActionButton from '@/app/components/base/action-button'
|
||||
import ViewFormDropdown from '@/app/components/base/chat/embedded-chatbot/inputs-form/view-form-dropdown'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { isClient } from '@/utils/client'
|
||||
import {
|
||||
useEmbeddedChatbotContext,
|
||||
|
||||
@ -11,10 +11,10 @@ import Header from '@/app/components/base/chat/embedded-chatbot/header'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import LogoHeader from '@/app/components/base/logo/logo-embedded-chat-header'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { AppSourceType } from '@/service/share'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import {
|
||||
EmbeddedChatbotContext,
|
||||
useEmbeddedChatbotContext,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import type { ChangeEvent } from 'react'
|
||||
import type { AppContextValue } from '@/context/app-context'
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import { act } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { createMockProviderContextValue } from '@/__mocks__/provider-context'
|
||||
@ -18,7 +18,7 @@ import { useProviderContext } from '@/context/provider-context'
|
||||
import { updateCurrentWorkspace } from '@/service/common'
|
||||
import useWebAppBrand from '../use-web-app-brand'
|
||||
|
||||
let currentBrandingOverrides: Partial<SystemFeatures['branding']> = {}
|
||||
let currentBrandingOverrides: Partial<GetSystemFeaturesResponse['branding']> = {}
|
||||
const renderHook = <Result, Props = void>(callback: (props: Props) => Result) =>
|
||||
renderHookWithSystemFeatures(callback, {
|
||||
systemFeatures: {
|
||||
|
||||
@ -7,8 +7,8 @@ import { getImageUploadErrorMessage, imageUpload } from '@/app/components/base/i
|
||||
import { Plan } from '@/app/components/billing/type'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { updateCurrentWorkspace } from '@/service/common'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
|
||||
const MAX_LOGO_FILE_SIZE = 5 * 1024 * 1024
|
||||
const CUSTOM_CONFIG_URL = '/workspaces/custom-config'
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useMemo } from 'react'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { LanguagesSupported } from '@/i18n-config/language'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { usePipelineTemplateList } from '@/service/use-pipeline'
|
||||
import CreateCard from './create-card'
|
||||
import TemplateCard from './template-card'
|
||||
|
||||
@ -11,11 +11,11 @@ import Input from '@/app/components/base/input'
|
||||
import CheckboxWithLabel from '@/app/components/datasets/create/website/base/checkbox-with-label'
|
||||
import { useAppContext, useSelector as useAppContextSelector } from '@/context/app-context'
|
||||
import { useExternalApiPanel } from '@/context/external-api-panel-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { TagFilter } from '@/features/tag-management/components/tag-filter'
|
||||
import { TagManagementModal } from '@/features/tag-management/components/tag-management-modal'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { useDatasetApiBaseUrl, useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
// Components
|
||||
import ExternalAPIPanel from '../external-api/external-api-panel'
|
||||
import ServiceApi from '../extra-info/service-api'
|
||||
|
||||
@ -20,12 +20,12 @@ import Banner from '@/app/components/explore/banner/banner'
|
||||
import Category from '@/app/components/explore/category'
|
||||
import CreateAppModal from '@/app/components/explore/create-app-modal'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useImportDSL } from '@/hooks/use-import-dsl'
|
||||
import {
|
||||
DSLImportMode,
|
||||
} from '@/models/app'
|
||||
import { fetchAppDetail } from '@/service/explore'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useMembers } from '@/service/use-common'
|
||||
import { useExploreAppList } from '@/service/use-explore'
|
||||
import { trackCreateApp } from '@/utils/create-app-tracking'
|
||||
|
||||
@ -10,7 +10,7 @@ import { useState } from 'react'
|
||||
import AppUnavailable from '@/app/components/base/app-unavailable'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { IS_CLOUD_EDITION } from '@/config'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useGetTryAppInfo } from '@/service/use-try-app'
|
||||
import App from './app'
|
||||
import AppInfo from './app-info'
|
||||
|
||||
@ -9,8 +9,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import { IS_CE_EDITION } from '@/config'
|
||||
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import Link from '@/next/link'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
|
||||
type IAccountSettingProps = {
|
||||
langGeniusVersionInfo: LangGeniusVersionResponse
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import type { AppContextValue } from '@/context/app-context'
|
||||
import type { ModalContextState } from '@/context/modal-context'
|
||||
import type { ProviderContextState } from '@/context/provider-context'
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import { fireEvent, screen, waitFor } from '@testing-library/react'
|
||||
import { renderWithSystemFeatures } from '@/__tests__/utils/mock-system-features'
|
||||
import { Plan } from '@/app/components/billing/type'
|
||||
@ -144,7 +144,7 @@ describe('AccountDropdown', () => {
|
||||
|
||||
const renderWithRouter = (
|
||||
ui: React.ReactElement,
|
||||
options: { systemFeatures?: DeepPartial<SystemFeatures> } = {},
|
||||
options: { systemFeatures?: DeepPartial<GetSystemFeaturesResponse> } = {},
|
||||
) => {
|
||||
return renderWithSystemFeatures(ui, {
|
||||
systemFeatures: options.systemFeatures ?? { branding: { enabled: false } },
|
||||
|
||||
@ -17,9 +17,9 @@ import { useDocLink } from '@/context/i18n'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { env } from '@/env'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import Link from '@/next/link'
|
||||
import { useRouter } from '@/next/navigation'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useLogout } from '@/service/use-common'
|
||||
import AccountAbout from '../account-about'
|
||||
import GithubStar from '../github-star'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { memo } from 'react'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useGetDataSourceListAuth } from '@/service/use-datasource'
|
||||
import Card from './card'
|
||||
import InstallFromMarketplace from './install-from-marketplace'
|
||||
|
||||
@ -11,9 +11,9 @@ import UpgradeBtn from '@/app/components/billing/upgrade-btn'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
|
||||
import { LanguagesSupported } from '@/i18n-config/language'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useMembers } from '@/service/use-common'
|
||||
import EditWorkspaceModal from './edit-workspace-modal'
|
||||
import InviteButton from './invite-button'
|
||||
|
||||
@ -4,7 +4,7 @@ import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useWorkspacePermissions } from '@/service/use-workspace'
|
||||
|
||||
type InviteButtonProps = {
|
||||
|
||||
@ -13,7 +13,7 @@ import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useWorkspacePermissions } from '@/service/use-workspace'
|
||||
|
||||
type Props = {
|
||||
|
||||
@ -10,8 +10,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import { usePluginsWithLatestVersion } from '@/app/components/plugins/hooks'
|
||||
import { IS_CLOUD_EDITION } from '@/config'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import {
|
||||
CustomConfigurationStatusEnum,
|
||||
ModelTypeEnum,
|
||||
|
||||
@ -13,9 +13,9 @@ import useRefreshPluginList from '@/app/components/plugins/install-plugin/hooks/
|
||||
import { IS_CLOUD_EDITION } from '@/config'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useSearchParams } from '@/next/navigation'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useInstallPackageFromMarketPlace } from '@/service/use-plugins'
|
||||
import { CustomConfigurationStatusEnum, ModelFeatureEnum, ModelStatusEnum, ModelTypeEnum } from '../declarations'
|
||||
import { useLanguage, useMarketplaceAllPlugins } from '../hooks'
|
||||
|
||||
@ -8,9 +8,9 @@ import { useAppContext } from '@/context/app-context'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { WorkspaceProvider } from '@/context/workspace-context-provider'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import Link from '@/next/link'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { Plan } from '../billing/type'
|
||||
import AccountDropdown from './account-dropdown'
|
||||
import AppNav from './app-nav'
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { screen } from '@testing-library/react'
|
||||
import dayjs from 'dayjs'
|
||||
import { renderWithSystemFeatures } from '@/__tests__/utils/mock-system-features'
|
||||
import { LicenseStatus } from '@/types/feature'
|
||||
import { LicenseStatus } from '@/features/system-features/constants'
|
||||
import LicenseNav from '../index'
|
||||
|
||||
describe('LicenseNav', () => {
|
||||
@ -26,7 +26,7 @@ describe('LicenseNav', () => {
|
||||
systemFeatures: {
|
||||
license: {
|
||||
status: LicenseStatus.ACTIVE,
|
||||
expired_at: null,
|
||||
expired_at: '',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@ -4,8 +4,8 @@ import { RiHourglass2Fill } from '@remixicon/react'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import dayjs from 'dayjs'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { LicenseStatus } from '@/types/feature'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { LicenseStatus } from '@/features/system-features/constants'
|
||||
import PremiumBadge from '../../base/premium-badge'
|
||||
|
||||
const LicenseNav = () => {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import type { PluginInstallationScope } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { renderHookWithSystemFeatures as renderHook } from '@/__tests__/utils/mock-system-features'
|
||||
import { InstallationScope } from '@/types/feature'
|
||||
import { InstallationScope } from '@/features/system-features/constants'
|
||||
import { pluginInstallLimit } from '../use-install-plugin-limit'
|
||||
|
||||
const basePlugin = {
|
||||
@ -117,7 +118,7 @@ describe('pluginInstallLimit', () => {
|
||||
const features = {
|
||||
plugin_installation_permission: {
|
||||
restrict_to_marketplace_only: false,
|
||||
plugin_installation_scope: 'unknown-scope' as InstallationScope,
|
||||
plugin_installation_scope: 'unknown-scope' as unknown as PluginInstallationScope,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import type { Plugin, PluginManifestInMarket } from '../../types'
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { InstallationScope } from '@/types/feature'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { InstallationScope } from '@/features/system-features/constants'
|
||||
|
||||
type PluginProps = (Plugin | PluginManifestInMarket) & { from: 'github' | 'marketplace' | 'package' }
|
||||
|
||||
export function pluginInstallLimit(plugin: PluginProps, systemFeatures: SystemFeatures) {
|
||||
export function pluginInstallLimit(plugin: PluginProps, systemFeatures: GetSystemFeaturesResponse) {
|
||||
if (systemFeatures.plugin_installation_permission.restrict_to_marketplace_only) {
|
||||
if (plugin.from === 'github' || plugin.from === 'package')
|
||||
return { canInstall: false }
|
||||
|
||||
@ -5,7 +5,7 @@ import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import useCheckInstalled from '@/app/components/plugins/install-plugin/hooks/use-check-installed'
|
||||
import { pluginInstallLimit } from '@/app/components/plugins/install-plugin/hooks/use-install-plugin-limit'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useFetchPluginsInMarketPlaceByInfo } from '@/service/use-plugins'
|
||||
|
||||
type UseInstallMultiStateParams = {
|
||||
|
||||
@ -4,7 +4,7 @@ import type { PluginDetail } from '../../../types'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import useReferenceSetting from '../../../plugin-page/use-reference-setting'
|
||||
import { AUTO_UPDATE_MODE } from '../../../reference-setting-modal/auto-update-setting/types'
|
||||
import { PluginSource } from '../../../types'
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { PluginSource } from '../types'
|
||||
|
||||
type Props = {
|
||||
|
||||
@ -17,9 +17,9 @@ import { useTranslation } from 'react-i18next'
|
||||
import useRefreshPluginList from '@/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list'
|
||||
import { API_PREFIX } from '@/config'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { isEqualOrLaterThanVersion } from '@/utils/semver'
|
||||
import { getMarketplaceUrl } from '@/utils/var'
|
||||
import Badge from '../../base/badge'
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { PLUGIN_PAGE_TABS_MAP, usePluginPageTabs } from '../hooks'
|
||||
import { PLUGIN_TYPE_SEARCH_MAP } from '../marketplace/constants'
|
||||
import {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import type { ReactElement } from 'react'
|
||||
import type { FilterState } from '../../filter-management'
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import { act, fireEvent, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { renderWithSystemFeatures } from '@/__tests__/utils/mock-system-features'
|
||||
import { InstallationScope } from '@/types/feature'
|
||||
import { InstallationScope } from '@/features/system-features/constants'
|
||||
|
||||
// ==================== Imports (after mocks) ====================
|
||||
|
||||
@ -32,7 +32,7 @@ const {
|
||||
plugin_installation_scope: 'all' as const,
|
||||
restrict_to_marketplace_only: false,
|
||||
},
|
||||
} as Partial<SystemFeatures>,
|
||||
} as Partial<GetSystemFeaturesResponse>,
|
||||
pluginList: { plugins: [] as Array<{ id: string }> } as { plugins: Array<{ id: string }> } | undefined,
|
||||
}
|
||||
return {
|
||||
@ -105,7 +105,7 @@ const setMockFilters = (filters: Partial<FilterState>) => {
|
||||
mockState.filters = { ...mockState.filters, ...filters }
|
||||
}
|
||||
|
||||
const setMockSystemFeatures = (features: Partial<SystemFeatures>) => {
|
||||
const setMockSystemFeatures = (features: Partial<GetSystemFeaturesResponse>) => {
|
||||
mockState.systemFeatures = { ...mockState.systemFeatures, ...features }
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import { MagicBox } from '@/app/components/base/icons/src/vender/solid/mediaAndD
|
||||
import InstallFromGitHub from '@/app/components/plugins/install-plugin/install-from-github'
|
||||
import InstallFromLocalPackage from '@/app/components/plugins/install-plugin/install-from-local-package'
|
||||
import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useInstalledPluginList } from '@/service/use-plugins'
|
||||
import Line from '../../marketplace/empty/line'
|
||||
import { usePluginPageContext } from '../context'
|
||||
|
||||
@ -19,11 +19,11 @@ import TabSlider from '@/app/components/base/tab-slider'
|
||||
import ReferenceSettingModal from '@/app/components/plugins/reference-setting-modal'
|
||||
import { MARKETPLACE_API_PREFIX, SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config'
|
||||
import { useDocLink } from '@/context/i18n'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { usePluginInstallation } from '@/hooks/use-query-params'
|
||||
import Link from '@/next/link'
|
||||
import { fetchBundleInfoFromMarketPlace, fetchManifestFromMarketPlace } from '@/service/plugins'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { sleep } from '@/utils'
|
||||
import { PLUGIN_PAGE_TABS_MAP } from '../hooks'
|
||||
import InstallFromLocalPackage from '../install-plugin/install-from-local-package'
|
||||
|
||||
@ -18,7 +18,7 @@ import { MagicBox } from '@/app/components/base/icons/src/vender/solid/mediaAndD
|
||||
import InstallFromGitHub from '@/app/components/plugins/install-plugin/install-from-github'
|
||||
import InstallFromLocalPackage from '@/app/components/plugins/install-plugin/install-from-local-package'
|
||||
import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
|
||||
type Props = {
|
||||
onSwitchToMarketplaceTab: () => void
|
||||
|
||||
@ -3,7 +3,7 @@ import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useInvalidateReferenceSettings, useMutationReferenceSettings, useReferenceSettings } from '@/service/use-plugins'
|
||||
import { PermissionType } from '../types'
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { PermissionType } from '@/app/components/plugins/types'
|
||||
import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import AutoUpdateSetting from './auto-update-setting'
|
||||
import { defaultValue as autoUpdateDefaultValue } from './auto-update-setting/config'
|
||||
import Label from './label'
|
||||
|
||||
@ -3,9 +3,9 @@ import type { PromptConfig, SavedMessage } from '@/models/debug'
|
||||
import type { SiteInfo } from '@/models/share'
|
||||
import type { VisionSettings } from '@/types/app'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { defaultSystemFeatures } from '@/features/system-features/config'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
import { Resolution, TransferMethod } from '@/types/app'
|
||||
import { defaultSystemFeatures } from '@/types/feature'
|
||||
import TextGenerationSidebar from '../text-generation-sidebar'
|
||||
|
||||
const runOncePropsSpy = vi.fn()
|
||||
|
||||
@ -8,11 +8,11 @@ import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { getRawInputsFromUrlParams } from '@/app/components/base/chat/utils'
|
||||
import { useWebAppStore } from '@/context/web-app-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useAppFavicon } from '@/hooks/use-app-favicon'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { changeLanguage } from '@/i18n-config/client'
|
||||
import { AppSourceType, fetchSavedMessage as doFetchSavedMessage, removeMessage, saveMessage } from '@/service/share'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { Resolution, TransferMethod } from '@/types/app'
|
||||
import { userInputsFormToPromptVariables } from '@/utils/model-config'
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import type { FC, RefObject } from 'react'
|
||||
import type { InputValueTypes, TextGenerationCustomConfig, TextGenerationRunControl } from './types'
|
||||
import type { PromptConfig, SavedMessage, TextToSpeechConfig } from '@/models/debug'
|
||||
import type { SiteInfo } from '@/models/share'
|
||||
import type { VisionFile, VisionSettings } from '@/types/app'
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import SavedItems from '@/app/components/app/text-generate/saved-items'
|
||||
@ -38,7 +38,7 @@ type TextGenerationSidebarProps = {
|
||||
runControl: TextGenerationRunControl | null
|
||||
savedMessages: SavedMessage[]
|
||||
siteInfo: SiteInfo
|
||||
systemFeatures: SystemFeatures
|
||||
systemFeatures: GetSystemFeaturesResponse
|
||||
textToSpeechConfig: TextToSpeechConfig | null
|
||||
visionConfig: VisionSettings
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ import CustomCreateCard from '@/app/components/tools/provider/custom-create-card
|
||||
import ProviderDetail from '@/app/components/tools/provider/detail'
|
||||
import WorkflowToolEmpty from '@/app/components/tools/provider/empty'
|
||||
import ToolCardSkeletonGrid from '@/app/components/tools/provider/tool-card-skeleton'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useCheckInstalled, useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import { useAllToolProviders } from '@/service/use-tools'
|
||||
import Marketplace from './marketplace'
|
||||
|
||||
@ -10,8 +10,8 @@ import { useSerialAsyncCallback } from '@/app/components/workflow/hooks/use-seri
|
||||
import { useNodesReadOnly } from '@/app/components/workflow/hooks/use-workflow'
|
||||
import { useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { API_PREFIX } from '@/config'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { postWithKeepalive } from '@/service/fetch'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { syncWorkflowDraft } from '@/service/workflow'
|
||||
import { useWorkflowRefreshDraft } from '.'
|
||||
|
||||
|
||||
@ -19,8 +19,8 @@ import {
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import { SearchMenu } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import Link from '@/next/link'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useFeaturedTriggersRecommendations } from '@/service/use-plugins'
|
||||
import { useAllTriggerPlugins, useInvalidateAllTriggerPlugins } from '@/service/use-triggers'
|
||||
import { getMarketplaceUrl } from '@/utils/var'
|
||||
|
||||
@ -21,8 +21,8 @@ import Divider from '@/app/components/base/divider'
|
||||
import { SearchMenu } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import PluginList from '@/app/components/workflow/block-selector/market-place-plugin/list'
|
||||
import { useGetLanguage } from '@/context/i18n'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import Link from '@/next/link'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { getMarketplaceUrl } from '@/utils/var'
|
||||
import { useMarketplacePlugins } from '../../plugins/marketplace/hooks'
|
||||
import { PluginCategoryEnum } from '../../plugins/types'
|
||||
|
||||
@ -14,7 +14,7 @@ import {
|
||||
} from 'react'
|
||||
import PluginList from '@/app/components/workflow/block-selector/market-place-plugin/list'
|
||||
import { useGetLanguage } from '@/context/i18n'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useMarketplacePlugins } from '../../plugins/marketplace/hooks'
|
||||
import { PluginCategoryEnum } from '../../plugins/types'
|
||||
import { BlockEnum } from '../types'
|
||||
|
||||
@ -10,7 +10,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/too
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { memo, useEffect, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useFeaturedToolsRecommendations } from '@/service/use-plugins'
|
||||
import { useAllBuiltInTools, useAllCustomTools, useAllMCPTools, useAllWorkflowTools, useInvalidateAllBuiltInTools } from '@/service/use-tools'
|
||||
import { basePath } from '@/utils/var'
|
||||
|
||||
@ -20,7 +20,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import SearchBox from '@/app/components/plugins/marketplace/search-box'
|
||||
import EditCustomToolModal from '@/app/components/tools/edit-custom-collection-modal'
|
||||
import AllTools from '@/app/components/workflow/block-selector/all-tools'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import {
|
||||
createCustomCollection,
|
||||
} from '@/service/tools'
|
||||
|
||||
@ -7,7 +7,7 @@ import type {
|
||||
} from '../types/collaboration'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { collaborationManager } from '../core/collaboration-manager'
|
||||
import { CursorService } from '../services/cursor-service'
|
||||
|
||||
|
||||
@ -54,9 +54,11 @@ vi.mock('@/context/app-context', () => ({
|
||||
|
||||
vi.mock('@/service/client', () => ({
|
||||
consoleClient: {
|
||||
systemFeatures: () => ({
|
||||
enable_collaboration_mode: globalFeatureState.enableCollaboration,
|
||||
}),
|
||||
systemFeatures: {
|
||||
get: () => ({
|
||||
enable_collaboration_mode: globalFeatureState.enableCollaboration,
|
||||
}),
|
||||
},
|
||||
workflowComments: {
|
||||
create: (...args: unknown[]) => mockCreateWorkflowComment(...args),
|
||||
delete: (...args: unknown[]) => mockDeleteWorkflowComment(...args),
|
||||
@ -73,7 +75,9 @@ vi.mock('@/service/client', () => ({
|
||||
},
|
||||
consoleQuery: {
|
||||
systemFeatures: {
|
||||
queryKey: () => ['console', 'systemFeatures'],
|
||||
get: {
|
||||
queryKey: () => ['console', 'systemFeatures', 'get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
@ -4,9 +4,9 @@ import { useCallback, useEffect, useMemo, useRef } from 'react'
|
||||
import { useReactFlow } from 'reactflow'
|
||||
import { collaborationManager } from '@/app/components/workflow/collaboration/core/collaboration-manager'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useParams } from '@/next/navigation'
|
||||
import { consoleClient } from '@/service/client'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useStore } from '../store'
|
||||
import { ControlMode } from '../types'
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useCallback } from 'react'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { useStore, useWorkflowStore } from '../store'
|
||||
import { ControlMode } from '../types'
|
||||
import { useEdgesInteractionsWithoutSync } from './use-edges-interactions-without-sync'
|
||||
|
||||
@ -19,7 +19,7 @@ vi.mock('@tanstack/react-query', () => ({
|
||||
useSuspenseQuery: mocks.useSuspenseQuery,
|
||||
}))
|
||||
|
||||
vi.mock('@/service/system-features', () => ({
|
||||
vi.mock('@/features/system-features/client', () => ({
|
||||
systemFeaturesQueryOptions: () => ({}),
|
||||
}))
|
||||
|
||||
|
||||
@ -24,8 +24,8 @@ import { useMarketplacePlugins } from '@/app/components/plugins/marketplace/hook
|
||||
import { PluginCategoryEnum } from '@/app/components/plugins/types'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
import PluginList from '@/app/components/workflow/block-selector/market-place-plugin/list'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import Link from '@/next/link'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useStrategyProviders } from '@/service/use-strategy'
|
||||
import Tools from '../../../block-selector/tools'
|
||||
import ViewTypeSelect, { ViewType } from '../../../block-selector/view-type-select'
|
||||
|
||||
@ -16,7 +16,7 @@ import {
|
||||
useReactFlow,
|
||||
useViewport,
|
||||
} from 'reactflow'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import {
|
||||
useNodesSyncDraft,
|
||||
useWorkflowReadOnly,
|
||||
|
||||
@ -35,7 +35,7 @@ vi.mock('@/service/device-flow', () => ({
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/service/system-features', () => ({
|
||||
vi.mock('@/features/system-features/client', () => ({
|
||||
systemFeaturesQueryOptions: () => ({ queryKey: ['sys'], queryFn: async () => ({}) }),
|
||||
}))
|
||||
|
||||
|
||||
@ -3,10 +3,10 @@ import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import LocaleMenu from '@/app/signin/_locale-menu'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { setLocaleOnClient } from '@/i18n-config'
|
||||
import { languages } from '@/i18n-config/language'
|
||||
import dynamic from '@/next/dynamic'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
|
||||
const DifyLogo = dynamic(() => import('@/app/components/base/logo/dify-logo'), {
|
||||
ssr: false,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
'use client'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import Header from './_header'
|
||||
|
||||
export default function DeviceLayout({ children }: { children: React.ReactNode }) {
|
||||
|
||||
@ -5,10 +5,10 @@ import { useQuery } from '@tanstack/react-query'
|
||||
import { useEffect, useState } from 'react'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { usePathname, useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { deviceLookup } from '@/service/device-flow'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import AuthorizeAccount from './components/authorize-account'
|
||||
import AuthorizeSSO from './components/authorize-sso'
|
||||
import Chooser from './components/chooser'
|
||||
|
||||
@ -3,9 +3,9 @@ import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import * as React from 'react'
|
||||
import ChangePasswordForm from '@/app/forgot-password/ChangePasswordForm'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { useSearchParams } from '@/next/navigation'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import Header from '../signin/_header'
|
||||
import ForgotPasswordForm from './ForgotPasswordForm'
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import * as React from 'react'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import Header from '../signin/_header'
|
||||
import InstallForm from './installForm'
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import Header from '../signin/_header'
|
||||
|
||||
export default function SignInLayout({ children }: any) {
|
||||
|
||||
@ -19,7 +19,7 @@ vi.mock('@/next/dynamic', () => ({
|
||||
default: () => () => null,
|
||||
}))
|
||||
|
||||
vi.mock('@/service/system-features', () => ({
|
||||
vi.mock('@/features/system-features/client', () => ({
|
||||
systemFeaturesQueryOptions: () => ({}),
|
||||
}))
|
||||
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { setLocaleOnClient } from '@/i18n-config'
|
||||
import { languages } from '@/i18n-config/language'
|
||||
import dynamic from '@/next/dynamic'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import LocaleMenu from './_locale-menu'
|
||||
|
||||
// Avoid rendering the logo and theme selector on the server
|
||||
|
||||
@ -5,12 +5,12 @@ import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security'
|
||||
import { SSOProtocol } from '@/features/system-features/constants'
|
||||
import { useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { getUserOAuth2SSOUrl, getUserOIDCSSOUrl, getUserSAMLSSOUrl } from '@/service/sso'
|
||||
import { SSOProtocol } from '@/types/feature'
|
||||
|
||||
type SSOAuthProps = {
|
||||
protocol: SSOProtocol | ''
|
||||
protocol: string
|
||||
}
|
||||
|
||||
const SSOAuth: FC<SSOAuthProps> = ({
|
||||
|
||||
@ -12,13 +12,13 @@ import Input from '@/app/components/base/input'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { LICENSE_LINK } from '@/constants/link'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { i18n, setLocaleOnClient } from '@/i18n-config'
|
||||
import { languages } from '@/i18n-config/language'
|
||||
import Link from '@/next/link'
|
||||
import { useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { activateMember } from '@/service/common'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useInvitationCheck } from '@/service/use-common'
|
||||
import { getBrowserTimezone, timezones } from '@/utils/timezone'
|
||||
import { resolvePostLoginRedirect } from '../utils/post-login-redirect'
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import Header from './_header'
|
||||
|
||||
export default function SignInLayout({ children }: any) {
|
||||
|
||||
@ -7,11 +7,11 @@ import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { IS_CE_EDITION } from '@/config'
|
||||
import { isLegacyBase401, userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { LicenseStatus } from '@/features/system-features/constants'
|
||||
import Link from '@/next/link'
|
||||
import { useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { invitationCheck } from '@/service/common'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { LicenseStatus } from '@/types/feature'
|
||||
import Loading from '../components/base/loading'
|
||||
import MailAndCodeAuth from './components/mail-and-code-auth'
|
||||
import MailAndPasswordAuth from './components/mail-and-password-auth'
|
||||
|
||||
@ -9,8 +9,8 @@ import Input from '@/app/components/base/input'
|
||||
import Split from '@/app/signin/split'
|
||||
import { emailRegex } from '@/config'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import Link from '@/next/link'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useSendMail } from '@/service/use-common'
|
||||
|
||||
type Props = {
|
||||
|
||||
@ -3,8 +3,8 @@ import { cn } from '@langgenius/dify-ui/cn'
|
||||
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import Header from '@/app/signin/_header'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
|
||||
export default function RegisterLayout({ children }: any) {
|
||||
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
|
||||
|
||||
@ -18,8 +18,8 @@ import {
|
||||
} from '@/context/app-context'
|
||||
import { env } from '@/env'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import {
|
||||
useLangGeniusVersion,
|
||||
} from '@/service/use-common'
|
||||
|
||||
@ -8,9 +8,9 @@ import { useEffect } from 'react'
|
||||
import { create } from 'zustand'
|
||||
import { getProcessedSystemVariablesFromUrlParams } from '@/app/components/base/chat/utils'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
import { usePathname, useSearchParams } from '@/next/navigation'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useGetWebAppAccessModeByCode } from '@/service/use-share'
|
||||
|
||||
type WebAppStore = {
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import { type } from '@orpc/contract'
|
||||
import { base } from '../base'
|
||||
|
||||
export const systemFeaturesContract = base
|
||||
.route({
|
||||
path: '/system-features',
|
||||
method: 'GET',
|
||||
})
|
||||
.output(type<SystemFeatures>())
|
||||
@ -18,7 +18,6 @@ import {
|
||||
import { changePreferredProviderTypeContract, modelProvidersModelsContract } from './console/model-providers'
|
||||
import { notificationContract, notificationDismissContract } from './console/notification'
|
||||
import { pluginCheckInstalledContract, pluginLatestVersionsContract } from './console/plugins'
|
||||
import { systemFeaturesContract } from './console/system'
|
||||
import {
|
||||
tagBindingCreateContract,
|
||||
tagBindingRemoveContract,
|
||||
@ -80,7 +79,6 @@ export const consoleRouterContract = {
|
||||
get: accountProfileContract,
|
||||
},
|
||||
},
|
||||
systemFeatures: systemFeaturesContract,
|
||||
apps: {
|
||||
...communityContract.apps,
|
||||
list: appListContract,
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { defaultSystemFeatures } from '@/types/feature'
|
||||
import { defaultSystemFeatures } from '../config'
|
||||
|
||||
type LoadOptions = {
|
||||
cloudEnv?: Partial<typeof defaultCloudEnv>
|
||||
isCloudEdition: boolean
|
||||
systemFeaturesResult?: SystemFeatures
|
||||
systemFeaturesResult?: GetSystemFeaturesResponse
|
||||
systemFeaturesError?: Error
|
||||
}
|
||||
|
||||
@ -52,18 +52,22 @@ const loadSystemFeaturesModule = async ({
|
||||
...cloudEnv,
|
||||
},
|
||||
}))
|
||||
vi.doMock('../client', () => ({
|
||||
vi.doMock('@/service/client', () => ({
|
||||
consoleClient: {
|
||||
systemFeatures,
|
||||
systemFeatures: {
|
||||
get: systemFeatures,
|
||||
},
|
||||
},
|
||||
consoleQuery: {
|
||||
systemFeatures: {
|
||||
queryKey: () => queryKey,
|
||||
get: {
|
||||
queryKey: () => queryKey,
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
const module = await import('../system-features')
|
||||
const module = await import('../client')
|
||||
|
||||
return {
|
||||
module,
|
||||
@ -93,19 +97,23 @@ const loadServerSystemFeaturesModule = async ({
|
||||
...cloudEnv,
|
||||
},
|
||||
}))
|
||||
vi.doMock('../server', () => ({
|
||||
vi.doMock('@/service/server', () => ({
|
||||
getServerConsoleClientContext,
|
||||
serverConsoleClient: {
|
||||
systemFeatures,
|
||||
systemFeatures: {
|
||||
get: systemFeatures,
|
||||
},
|
||||
},
|
||||
serverConsoleQuery: {
|
||||
systemFeatures: {
|
||||
queryKey: () => queryKey,
|
||||
get: {
|
||||
queryKey: () => queryKey,
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
const module = await import('../server-system-features')
|
||||
const module = await import('../server')
|
||||
|
||||
return {
|
||||
getServerConsoleClientContext,
|
||||
@ -124,7 +132,7 @@ describe('systemFeaturesQueryOptions', () => {
|
||||
const data = await options.queryFn?.(queryContext)
|
||||
|
||||
expect(systemFeatures).not.toHaveBeenCalled()
|
||||
expect(options.staleTime).toBe(Infinity)
|
||||
expect(options.staleTime).toBe('static')
|
||||
expect(data).toMatchObject({
|
||||
enable_marketplace: true,
|
||||
enable_email_code_login: true,
|
||||
@ -215,7 +223,7 @@ describe('serverSystemFeaturesQueryOptions', () => {
|
||||
|
||||
expect(getServerConsoleClientContext).not.toHaveBeenCalled()
|
||||
expect(systemFeatures).not.toHaveBeenCalled()
|
||||
expect(options.staleTime).toBe(Infinity)
|
||||
expect(options.staleTime).toBe('static')
|
||||
expect(data).toMatchObject({
|
||||
enable_marketplace: false,
|
||||
enable_email_password_login: true,
|
||||
@ -1,9 +1,8 @@
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import { queryOptions } from '@tanstack/react-query'
|
||||
import { IS_CLOUD_EDITION } from '@/config'
|
||||
import { cloudSystemFeatures } from '@/config/cloud-system-features'
|
||||
import { defaultSystemFeatures } from '@/types/feature'
|
||||
import { consoleClient, consoleQuery } from './client'
|
||||
import { consoleClient, consoleQuery } from '@/service/client'
|
||||
import { cloudSystemFeatures, defaultSystemFeatures } from './config'
|
||||
|
||||
/**
|
||||
* Soft-fallback to defaults so the dashboard stays usable when /system-features fails.
|
||||
@ -15,26 +14,26 @@ import { consoleClient, consoleQuery } from './client'
|
||||
* is a small, dependency-free endpoint in the community edition.
|
||||
*
|
||||
* For Cloud, this query is intentionally local-only and uses `staleTime:
|
||||
* Infinity`: the payload comes from frontend config/defaults, so refetching
|
||||
* would only re-run the same local merge. For non-Cloud, do not override
|
||||
* 'static'`: the payload comes from frontend config/defaults, so invalidation
|
||||
* should not re-run the same local merge. For non-Cloud, do not override
|
||||
* `staleTime`: inherit the 5-minute default from query-client-server.ts.
|
||||
*/
|
||||
export const systemFeaturesQueryOptions = () => {
|
||||
const queryKey = consoleQuery.systemFeatures.queryKey()
|
||||
const queryKey = consoleQuery.systemFeatures.get.queryKey()
|
||||
|
||||
if (IS_CLOUD_EDITION) {
|
||||
return queryOptions<SystemFeatures>({
|
||||
return queryOptions<GetSystemFeaturesResponse>({
|
||||
queryKey,
|
||||
queryFn: async () => cloudSystemFeatures,
|
||||
staleTime: Infinity,
|
||||
staleTime: 'static',
|
||||
})
|
||||
}
|
||||
|
||||
return queryOptions<SystemFeatures>({
|
||||
return queryOptions<GetSystemFeaturesResponse>({
|
||||
queryKey,
|
||||
queryFn: async () => {
|
||||
try {
|
||||
return await consoleClient.systemFeatures()
|
||||
return await consoleClient.systemFeatures.get()
|
||||
}
|
||||
catch (err) {
|
||||
console.error('[systemFeatures] fetch failed, using defaults', err)
|
||||
@ -1,8 +1,58 @@
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import { env } from '@/env'
|
||||
import { defaultSystemFeatures, InstallationScope, LicenseStatus } from '@/types/feature'
|
||||
import { InstallationScope, LicenseStatus } from './constants'
|
||||
|
||||
export const cloudSystemFeatures: SystemFeatures = {
|
||||
export const defaultSystemFeatures = {
|
||||
sso_enforced_for_signin: false,
|
||||
sso_enforced_for_signin_protocol: '',
|
||||
enable_marketplace: false,
|
||||
enable_email_code_login: false,
|
||||
enable_email_password_login: true,
|
||||
enable_social_oauth_login: false,
|
||||
enable_collaboration_mode: true,
|
||||
is_allow_create_workspace: false,
|
||||
is_allow_register: false,
|
||||
is_email_setup: false,
|
||||
enable_change_email: true,
|
||||
max_plugin_package_size: 15728640,
|
||||
license: {
|
||||
status: LicenseStatus.NONE,
|
||||
expired_at: '',
|
||||
workspaces: {
|
||||
enabled: false,
|
||||
size: 0,
|
||||
limit: 0,
|
||||
},
|
||||
},
|
||||
branding: {
|
||||
enabled: false,
|
||||
login_page_logo: '',
|
||||
workspace_logo: '',
|
||||
favicon: '',
|
||||
application_title: '',
|
||||
},
|
||||
webapp_auth: {
|
||||
enabled: false,
|
||||
allow_sso: false,
|
||||
sso_config: {
|
||||
protocol: '',
|
||||
},
|
||||
allow_email_code_login: false,
|
||||
allow_email_password_login: false,
|
||||
},
|
||||
plugin_installation_permission: {
|
||||
plugin_installation_scope: InstallationScope.ALL,
|
||||
restrict_to_marketplace_only: false,
|
||||
},
|
||||
plugin_manager: {
|
||||
enabled: false,
|
||||
},
|
||||
enable_creators_platform: false,
|
||||
enable_trial_app: false,
|
||||
enable_explore_banner: false,
|
||||
} satisfies GetSystemFeaturesResponse
|
||||
|
||||
export const cloudSystemFeatures = {
|
||||
...defaultSystemFeatures,
|
||||
sso_enforced_for_signin: false,
|
||||
sso_enforced_for_signin_protocol: '',
|
||||
@ -49,4 +99,4 @@ export const cloudSystemFeatures: SystemFeatures = {
|
||||
enable_creators_platform: env.NEXT_PUBLIC_CREATORS_PLATFORM_FEATURES_ENABLED,
|
||||
enable_trial_app: env.NEXT_PUBLIC_ENABLE_TRIAL_APP,
|
||||
enable_explore_banner: env.NEXT_PUBLIC_ENABLE_EXPLORE_BANNER,
|
||||
}
|
||||
} satisfies GetSystemFeaturesResponse
|
||||
23
web/features/system-features/constants.ts
Normal file
23
web/features/system-features/constants.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
|
||||
export const SSOProtocol = {
|
||||
SAML: 'saml',
|
||||
OIDC: 'oidc',
|
||||
OAuth2: 'oauth2',
|
||||
} as const
|
||||
|
||||
export const LicenseStatus = {
|
||||
NONE: 'none',
|
||||
INACTIVE: 'inactive',
|
||||
ACTIVE: 'active',
|
||||
EXPIRING: 'expiring',
|
||||
EXPIRED: 'expired',
|
||||
LOST: 'lost',
|
||||
} as const satisfies Record<string, GetSystemFeaturesResponse['license']['status']>
|
||||
|
||||
export const InstallationScope = {
|
||||
ALL: 'all',
|
||||
NONE: 'none',
|
||||
OFFICIAL_ONLY: 'official_only',
|
||||
OFFICIAL_AND_PARTNER: 'official_and_specific_partners',
|
||||
} as const satisfies Record<string, GetSystemFeaturesResponse['plugin_installation_permission']['plugin_installation_scope']>
|
||||
@ -1,30 +1,29 @@
|
||||
import type { SystemFeatures } from '@/types/feature'
|
||||
import type { GetSystemFeaturesResponse } from '@dify/contracts/api/console/system-features/types.gen'
|
||||
import { queryOptions } from '@tanstack/react-query'
|
||||
import { IS_CLOUD_EDITION } from '@/config'
|
||||
import { cloudSystemFeatures } from '@/config/cloud-system-features'
|
||||
import { defaultSystemFeatures } from '@/types/feature'
|
||||
import {
|
||||
getServerConsoleClientContext,
|
||||
serverConsoleClient,
|
||||
serverConsoleQuery,
|
||||
} from './server'
|
||||
} from '@/service/server'
|
||||
import { cloudSystemFeatures, defaultSystemFeatures } from './config'
|
||||
|
||||
export const serverSystemFeaturesQueryOptions = () => {
|
||||
const queryKey = serverConsoleQuery.systemFeatures.queryKey()
|
||||
const queryKey = serverConsoleQuery.systemFeatures.get.queryKey()
|
||||
|
||||
if (IS_CLOUD_EDITION) {
|
||||
return queryOptions<SystemFeatures>({
|
||||
return queryOptions<GetSystemFeaturesResponse>({
|
||||
queryKey,
|
||||
queryFn: async () => cloudSystemFeatures,
|
||||
staleTime: Infinity,
|
||||
staleTime: 'static',
|
||||
})
|
||||
}
|
||||
|
||||
return queryOptions<SystemFeatures>({
|
||||
return queryOptions<GetSystemFeaturesResponse>({
|
||||
queryKey,
|
||||
queryFn: async () => {
|
||||
try {
|
||||
return await serverConsoleClient.systemFeatures(undefined, {
|
||||
return await serverConsoleClient.systemFeatures.get(undefined, {
|
||||
context: await getServerConsoleClientContext(),
|
||||
})
|
||||
}
|
||||
@ -2,8 +2,8 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useFavicon, useTitle } from 'ahooks'
|
||||
import { useEffect } from 'react'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { defaultSystemFeatures } from '@/types/feature'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { defaultSystemFeatures } from '@/features/system-features/config'
|
||||
import { basePath } from '@/utils/var'
|
||||
|
||||
export default function useDocumentTitle(title: string) {
|
||||
|
||||
@ -61,7 +61,8 @@ describe('server console oRPC client', () => {
|
||||
})
|
||||
|
||||
it('should call contracts with forwarded cookies, csrf header, and no-store cache', async () => {
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response(JSON.stringify({ feature: { billing: false } }), {
|
||||
const { defaultSystemFeatures } = await import('@/features/system-features/config')
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response(JSON.stringify(defaultSystemFeatures), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
@ -70,7 +71,7 @@ describe('server console oRPC client', () => {
|
||||
vi.stubGlobal('fetch', fetchMock)
|
||||
const { getServerConsoleClientContext, serverConsoleClient } = await import('../server')
|
||||
|
||||
await serverConsoleClient.systemFeatures(undefined, {
|
||||
await serverConsoleClient.systemFeatures.get(undefined, {
|
||||
context: await getServerConsoleClientContext(),
|
||||
})
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { AccessControlAccount, AccessControlGroup, AccessMode, Subject } from '@/models/access-control'
|
||||
import type { App } from '@/types/app'
|
||||
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { get, post } from './base'
|
||||
import { getUserCanAccess } from './share'
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import type { App, AppCategory } from '@/models/explore'
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { consoleQuery } from './client'
|
||||
import { fetchAppList, fetchBanners, fetchInstalledAppList, fetchInstalledAppMeta, fetchInstalledAppParams, getAppAccessModeByAppId, uninstallApp, updatePinStatus } from './explore'
|
||||
|
||||
|
||||
@ -1,115 +0,0 @@
|
||||
export const SSOProtocol = {
|
||||
SAML: 'saml',
|
||||
OIDC: 'oidc',
|
||||
OAuth2: 'oauth2',
|
||||
} as const
|
||||
|
||||
export type SSOProtocol = typeof SSOProtocol[keyof typeof SSOProtocol]
|
||||
|
||||
export const LicenseStatus = {
|
||||
NONE: 'none',
|
||||
INACTIVE: 'inactive',
|
||||
ACTIVE: 'active',
|
||||
EXPIRING: 'expiring',
|
||||
EXPIRED: 'expired',
|
||||
LOST: 'lost',
|
||||
} as const
|
||||
|
||||
export type LicenseStatus = typeof LicenseStatus[keyof typeof LicenseStatus]
|
||||
|
||||
export const InstallationScope = {
|
||||
ALL: 'all',
|
||||
NONE: 'none',
|
||||
OFFICIAL_ONLY: 'official_only',
|
||||
OFFICIAL_AND_PARTNER: 'official_and_specific_partners',
|
||||
} as const
|
||||
|
||||
export type InstallationScope = typeof InstallationScope[keyof typeof InstallationScope]
|
||||
|
||||
type License = {
|
||||
status: LicenseStatus
|
||||
expired_at: string | null
|
||||
}
|
||||
|
||||
export type SystemFeatures = {
|
||||
plugin_installation_permission: {
|
||||
plugin_installation_scope: InstallationScope
|
||||
restrict_to_marketplace_only: boolean
|
||||
}
|
||||
sso_enforced_for_signin: boolean
|
||||
sso_enforced_for_signin_protocol: SSOProtocol | ''
|
||||
sso_enforced_for_web: boolean
|
||||
sso_enforced_for_web_protocol: SSOProtocol | ''
|
||||
enable_marketplace: boolean
|
||||
enable_change_email: boolean
|
||||
enable_email_code_login: boolean
|
||||
enable_email_password_login: boolean
|
||||
enable_social_oauth_login: boolean
|
||||
enable_collaboration_mode: boolean
|
||||
is_allow_create_workspace: boolean
|
||||
is_allow_register: boolean
|
||||
is_email_setup: boolean
|
||||
license: License
|
||||
branding: {
|
||||
enabled: boolean
|
||||
login_page_logo: string
|
||||
workspace_logo: string
|
||||
favicon: string
|
||||
application_title: string
|
||||
}
|
||||
webapp_auth: {
|
||||
enabled: boolean
|
||||
allow_sso: boolean
|
||||
sso_config: {
|
||||
protocol: SSOProtocol | ''
|
||||
}
|
||||
allow_email_code_login: boolean
|
||||
allow_email_password_login: boolean
|
||||
}
|
||||
enable_creators_platform: boolean
|
||||
enable_trial_app: boolean
|
||||
enable_explore_banner: boolean
|
||||
}
|
||||
|
||||
export const defaultSystemFeatures: SystemFeatures = {
|
||||
plugin_installation_permission: {
|
||||
plugin_installation_scope: InstallationScope.ALL,
|
||||
restrict_to_marketplace_only: false,
|
||||
},
|
||||
sso_enforced_for_signin: false,
|
||||
sso_enforced_for_signin_protocol: '',
|
||||
sso_enforced_for_web: false,
|
||||
sso_enforced_for_web_protocol: '',
|
||||
enable_marketplace: false,
|
||||
enable_change_email: false,
|
||||
enable_email_code_login: false,
|
||||
enable_email_password_login: false,
|
||||
enable_social_oauth_login: false,
|
||||
enable_collaboration_mode: false,
|
||||
is_allow_create_workspace: false,
|
||||
is_allow_register: false,
|
||||
is_email_setup: false,
|
||||
license: {
|
||||
status: LicenseStatus.NONE,
|
||||
expired_at: '',
|
||||
},
|
||||
branding: {
|
||||
enabled: false,
|
||||
login_page_logo: '',
|
||||
workspace_logo: '',
|
||||
favicon: '',
|
||||
application_title: 'test title',
|
||||
},
|
||||
webapp_auth: {
|
||||
enabled: false,
|
||||
allow_sso: false,
|
||||
sso_config: {
|
||||
protocol: '',
|
||||
},
|
||||
allow_email_code_login: false,
|
||||
allow_email_password_login: false,
|
||||
},
|
||||
enable_creators_platform: false,
|
||||
enable_trial_app: false,
|
||||
enable_explore_banner: false,
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user