From cd0e88c680dec24dcd423b880302104f13d28462 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Tue, 11 Aug 2026 16:30:49 +0800 Subject: [PATCH] refactor(web): read dataset profile from query cache (#40468) --- .../__tests__/layout-main.spec.tsx | 7 ------ .../[datasetId]/layout-main.tsx | 7 ++++-- .../app-sidebar/dataset-detail-section.tsx | 7 ++++-- .../__tests__/dropdown-callbacks.spec.tsx | 4 ---- .../dataset-info/__tests__/index.spec.tsx | 4 ---- .../app-sidebar/dataset-info/dropdown.tsx | 7 ++++-- .../settings-modal/__tests__/index.spec.tsx | 2 ++ .../access-config/__tests__/index.spec.tsx | 5 ----- .../datasets/access-config/index.tsx | 7 ++++-- .../datasets/create/__tests__/index.spec.tsx | 20 +++++++++-------- web/app/components/datasets/create/index.tsx | 9 ++++++-- .../documents/__tests__/index.spec.tsx | 22 +++++++++++-------- .../document-list/__tests__/index.spec.tsx | 8 ------- .../components/document-table-row.tsx | 8 +++++-- .../datasets/documents/components/list.tsx | 9 ++++++-- .../__tests__/index.spec.tsx | 10 --------- .../documents/create-from-pipeline/index.tsx | 9 +++++--- .../datasets/documents/detail/index.tsx | 9 ++++++-- .../components/datasets/documents/index.tsx | 9 ++++++-- .../datasets/extra-info/api-access/card.tsx | 8 +++++-- .../hit-testing/__tests__/index.spec.tsx | 7 ++---- .../components/datasets/hit-testing/index.tsx | 9 ++++++-- .../datasets/list/__tests__/index.spec.tsx | 5 ----- .../dataset-card/__tests__/index.spec.tsx | 16 +++++++++----- .../__tests__/operations-dropdown.spec.tsx | 5 ----- .../components/operations-dropdown.tsx | 7 ++++-- .../datasets/list/dataset-card/index.tsx | 9 ++++++-- .../settings/form/__tests__/index.spec.tsx | 8 ------- .../__tests__/basic-info-section.spec.tsx | 5 ----- .../hooks/__tests__/use-form-state.spec.ts | 14 +++++------- .../settings/form/hooks/use-form-state.ts | 9 ++++++-- .../settings/permission-selector/index.tsx | 8 ++++--- .../rag-pipeline/components/conversion.tsx | 8 +++++-- .../publisher/__tests__/index.spec.tsx | 12 ++-------- .../publisher/__tests__/popup.spec.tsx | 10 --------- .../rag-pipeline-header/publisher/popup.tsx | 7 ++++-- .../components/rag-pipeline-main.tsx | 8 +++++-- 37 files changed, 161 insertions(+), 157 deletions(-) diff --git a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/__tests__/layout-main.spec.tsx b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/__tests__/layout-main.spec.tsx index 0c7e4a461e4..4d762a61749 100644 --- a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/__tests__/layout-main.spec.tsx +++ b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/__tests__/layout-main.spec.tsx @@ -24,13 +24,6 @@ vi.mock('@/service/knowledge/use-dataset', () => ({ useDatasetDetail: vi.fn(), })) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - - return createAccountStateModuleMock(() => ({ - userProfile: { id: 'user-1' }, - })) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx index bffbf673d54..5f54b122873 100644 --- a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx +++ b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx @@ -8,13 +8,13 @@ import * as React from 'react' import { useEffect } from 'react' import { useTranslation } from 'react-i18next' import Loading from '@/app/components/base/loading' -import { userProfileIdAtom } from '@/context/account-state' import DatasetDetailContext from '@/context/dataset-detail' import { workspacePermissionKeysAtom, workspacePermissionKeysLoadingAtom, } from '@/context/permission-state' import { currentWorkspaceLoadingAtom } from '@/context/workspace-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { systemFeaturesQueryOptions } from '@/features/system-features/client' import useDocumentTitle from '@/hooks/use-document-title' import { usePathname, useRouter } from '@/next/navigation' @@ -65,7 +65,10 @@ const DatasetDetailLayout: FC = (props) => { ...systemFeaturesQueryOptions(), select: ({ rbac_enabled }) => rbac_enabled, }) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const { data: datasetRes, error, refetch: mutateDatasetRes } = useDatasetDetail(datasetId) diff --git a/web/app/components/app-sidebar/dataset-detail-section.tsx b/web/app/components/app-sidebar/dataset-detail-section.tsx index 77cd0b82c5c..5599b8ca689 100644 --- a/web/app/components/app-sidebar/dataset-detail-section.tsx +++ b/web/app/components/app-sidebar/dataset-detail-section.tsx @@ -19,9 +19,9 @@ import { useTranslation } from 'react-i18next' import Divider from '@/app/components/base/divider' import { PipelineFill, PipelineLine } from '@/app/components/base/icons/src/vender/pipeline' import ExtraInfo from '@/app/components/datasets/extra-info' -import { userProfileIdAtom } from '@/context/account-state' import DatasetDetailContext from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { systemFeaturesQueryOptions } from '@/features/system-features/client' import { usePathname } from '@/next/navigation' import { useDatasetDetail, useDatasetRelatedApps } from '@/service/knowledge/use-dataset' @@ -43,7 +43,10 @@ const DatasetDetailSection = ({ expand = true }: DatasetDetailSectionProps) => { const pathname = usePathname() const datasetId = getDatasetIdFromPathname(pathname) const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions()) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const isRbacEnabled = systemFeatures.rbac_enabled const { data: datasetRes, refetch: mutateDatasetRes } = useDatasetDetail(datasetId ?? '') diff --git a/web/app/components/app-sidebar/dataset-info/__tests__/dropdown-callbacks.spec.tsx b/web/app/components/app-sidebar/dataset-info/__tests__/dropdown-callbacks.spec.tsx index cb3979a6323..86826918303 100644 --- a/web/app/components/app-sidebar/dataset-info/__tests__/dropdown-callbacks.spec.tsx +++ b/web/app/components/app-sidebar/dataset-info/__tests__/dropdown-callbacks.spec.tsx @@ -106,10 +106,6 @@ vi.mock('@/context/dataset-detail', () => ({ selector({ dataset: mockDataset }), })) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - return createAccountStateModuleMock(() => mockConsoleState.current) -}) vi.mock('@/context/permission-state', async () => { const { createPermissionStateModuleMock } = await import('@/test/console/state-fixture') return createPermissionStateModuleMock(() => mockConsoleState.current) diff --git a/web/app/components/app-sidebar/dataset-info/__tests__/index.spec.tsx b/web/app/components/app-sidebar/dataset-info/__tests__/index.spec.tsx index 37d5d4ef9f3..dd31a2787aa 100644 --- a/web/app/components/app-sidebar/dataset-info/__tests__/index.spec.tsx +++ b/web/app/components/app-sidebar/dataset-info/__tests__/index.spec.tsx @@ -119,10 +119,6 @@ vi.mock('@/context/dataset-detail', () => ({ selector({ dataset: mockDataset }), })) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - return createAccountStateModuleMock(() => mockConsoleState.current) -}) vi.mock('@/context/permission-state', async () => { const { createPermissionStateModuleMock } = await import('@/test/console/state-fixture') return createPermissionStateModuleMock(() => mockConsoleState.current) diff --git a/web/app/components/app-sidebar/dataset-info/dropdown.tsx b/web/app/components/app-sidebar/dataset-info/dropdown.tsx index f95a950d272..20c2c10c69d 100644 --- a/web/app/components/app-sidebar/dataset-info/dropdown.tsx +++ b/web/app/components/app-sidebar/dataset-info/dropdown.tsx @@ -20,9 +20,9 @@ import { useAtomValue } from 'jotai' import * as React from 'react' import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { systemFeaturesQueryOptions } from '@/features/system-features/client' import { useRouter } from '@/next/navigation' import { checkIsUsedInApp, deleteDataset } from '@/service/datasets' @@ -69,7 +69,10 @@ const DropDown = ({ expand, triggerClassName }: DropDownProps) => { const [showConfirmDelete, setShowConfirmDelete] = useState(false) const dataset = useDatasetDetailContextWithSelector((state) => state.dataset) as DataSet - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions()) const isRbacEnabled = systemFeatures.rbac_enabled diff --git a/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx b/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx index cdefed550c4..6f30a45fbf6 100644 --- a/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx +++ b/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx @@ -16,6 +16,7 @@ import { import { consoleQuery } from '@/service/client' import { updateDatasetSetting } from '@/service/datasets' import { useMembers } from '@/service/use-common' +import { seedAccountProfileQuery } from '@/test/console/account-profile' import { renderWithConsoleQuery as render } from '@/test/console/query-data' import { createSystemFeaturesFixture } from '@/test/console/system-features' import { RETRIEVE_METHOD } from '@/types/app' @@ -203,6 +204,7 @@ const renderWithProviders = (dataset: DataSet) => { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, staleTime: Number.POSITIVE_INFINITY } }, }) + seedAccountProfileQuery(queryClient, { id: 'user-1' }) queryClient.setQueryData(systemFeaturesQueryOptions().queryKey, createSystemFeaturesFixture()) queryClient.setQueryData(consoleQuery.datasets.retrievalSetting.get.queryOptions().queryKey, { retrieval_method: [RETRIEVE_METHOD.semantic, RETRIEVE_METHOD.fullText, RETRIEVE_METHOD.hybrid], diff --git a/web/app/components/datasets/access-config/__tests__/index.spec.tsx b/web/app/components/datasets/access-config/__tests__/index.spec.tsx index 4aa1cf8e6c8..fa7dfc08de2 100644 --- a/web/app/components/datasets/access-config/__tests__/index.spec.tsx +++ b/web/app/components/datasets/access-config/__tests__/index.spec.tsx @@ -82,11 +82,6 @@ vi.mock('@/context/dataset-detail', () => ({ ), })) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - - return createAccountStateModuleMock(() => mockConsoleState) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/access-config/index.tsx b/web/app/components/datasets/access-config/index.tsx index dbe9a983275..ab811bb7d35 100644 --- a/web/app/components/datasets/access-config/index.tsx +++ b/web/app/components/datasets/access-config/index.tsx @@ -14,10 +14,10 @@ import { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import AccessRulesEditor from '@/app/components/access-rules-editor' import Loading from '@/app/components/base/loading' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { useLocale } from '@/context/i18n' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { systemFeaturesQueryOptions } from '@/features/system-features/client' import { getAccessControlTemplateLanguage } from '@/i18n-config/language' import { @@ -38,7 +38,10 @@ const DatasetAccessConfigPage = ({ datasetId }: DatasetAccessConfigPageProps) => const locale = useLocale() const language = useMemo(() => getAccessControlTemplateLanguage(locale), [locale]) const dataset = useDatasetDetailContextWithSelector((state) => state.dataset) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const { data: isRbacEnabled } = useSuspenseQuery({ ...systemFeaturesQueryOptions(), diff --git a/web/app/components/datasets/create/__tests__/index.spec.tsx b/web/app/components/datasets/create/__tests__/index.spec.tsx index ed47b36d7d1..6a80a5eb1f6 100644 --- a/web/app/components/datasets/create/__tests__/index.spec.tsx +++ b/web/app/components/datasets/create/__tests__/index.spec.tsx @@ -6,11 +6,13 @@ import type { TopBarProps } from '../top-bar' import type { DataSourceAuth } from '@/app/components/header/account-setting/data-source-page-new/types' import type { NotionPage } from '@/models/common' import type { DataSet, FileItem } from '@/models/datasets' +import { QueryClientProvider } from '@tanstack/react-query' import { fireEvent, screen, waitFor } from '@testing-library/react' import * as React from 'react' import { DataSourceProvider } from '@/models/common' import { ChunkingMode, DatasetPermission, DataSourceType } from '@/models/datasets' -import { render } from '@/test/console/render' +import { createAccountProfileQueryClient } from '@/test/console/account-profile' +import { render as renderWithConsoleState } from '@/test/console/render' import { RETRIEVE_METHOD } from '@/types/app' import DatasetUpdateForm from '../index' @@ -42,15 +44,15 @@ let mockCurrentUserId = 'user-1' let mockWorkspacePermissionKeys = ['dataset.create_and_management'] let mockIsLoadingWorkspacePermissionKeys = false -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') +const render = (ui: Parameters[0]) => { + const queryClient = createAccountProfileQueryClient({ id: mockCurrentUserId }) + return renderWithConsoleState(ui, { + wrapper: ({ children }: { children: React.ReactNode }) => ( + {children} + ), + }) +} - return createAccountStateModuleMock(() => ({ - userProfile: { id: mockCurrentUserId }, - workspacePermissionKeys: mockWorkspacePermissionKeys, - isLoadingWorkspacePermissionKeys: mockIsLoadingWorkspacePermissionKeys, - })) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/create/index.tsx b/web/app/components/datasets/create/index.tsx index c10abf8b8b2..edadbcacfce 100644 --- a/web/app/components/datasets/create/index.tsx +++ b/web/app/components/datasets/create/index.tsx @@ -1,4 +1,5 @@ 'use client' + import type { NotionPage } from '@/models/common' import type { CrawlOptions, @@ -7,6 +8,7 @@ import type { FileItem, } from '@/models/datasets' import type { RETRIEVE_METHOD } from '@/types/app' +import { useSuspenseQuery } from '@tanstack/react-query' import { produce } from 'immer' import { useAtomValue } from 'jotai' import { useQueryState } from 'nuqs' @@ -19,12 +21,12 @@ import { settingsQueryParamName, settingsQueryParser, } from '@/app/components/header/account-setting/query-params' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { workspacePermissionKeysAtom, workspacePermissionKeysLoadingAtom, } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { DataSourceProvider } from '@/models/common' import { DataSourceType } from '@/models/datasets' import { useRouter } from '@/next/navigation' @@ -56,7 +58,10 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => { const router = useRouter() const [, setSettingsDestination] = useQueryState(settingsQueryParamName, settingsQueryParser) const datasetDetail = useDatasetDetailContextWithSelector((state) => state.dataset) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const isLoadingWorkspacePermissionKeys = useAtomValue(workspacePermissionKeysLoadingAtom) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const { data: embeddingsDefaultModel } = useDefaultModel(ModelTypeEnum.textEmbedding) diff --git a/web/app/components/datasets/documents/__tests__/index.spec.tsx b/web/app/components/datasets/documents/__tests__/index.spec.tsx index 14cff5eaad3..f3a4e1834a5 100644 --- a/web/app/components/datasets/documents/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/__tests__/index.spec.tsx @@ -1,13 +1,25 @@ +import type { ReactNode } from 'react' import type { DocumentListResponse } from '@/models/datasets' +import { QueryClientProvider } from '@tanstack/react-query' import { act, fireEvent, screen } from '@testing-library/react' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { useProviderContext } from '@/context/provider-context' import { DataSourceType } from '@/models/datasets' import { useDocumentList } from '@/service/knowledge/use-document' -import { render } from '@/test/console/render' +import { createAccountProfileQueryClient } from '@/test/console/account-profile' +import { render as renderWithConsoleState } from '@/test/console/render' import { useDocumentsPageState } from '../hooks/use-documents-page-state' import Documents from '../index' +const render = (ui: Parameters[0]) => { + const queryClient = createAccountProfileQueryClient({ id: 'test-user' }) + return renderWithConsoleState(ui, { + wrapper: ({ children }: { children: ReactNode }) => ( + {children} + ), + }) +} + // Type for mock selector function - use `as MockState` to bypass strict type checking in tests type MockSelector = Parameters[0] type MockState = Parameters[0] @@ -48,14 +60,6 @@ vi.mock('@/context/provider-context', () => ({ })), })) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - - return createAccountStateModuleMock(() => ({ - userProfile: { id: 'test-user' }, - workspacePermissionKeys: ['dataset.create_and_management'], - })) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/documents/components/document-list/__tests__/index.spec.tsx b/web/app/components/datasets/documents/components/document-list/__tests__/index.spec.tsx index 966d6c3781b..a7c6a05f539 100644 --- a/web/app/components/datasets/documents/components/document-list/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/components/document-list/__tests__/index.spec.tsx @@ -38,14 +38,6 @@ vi.mock('@/context/dataset-detail', () => ({ }), })) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - - return createAccountStateModuleMock(() => ({ - userProfile: { id: 'user-1' }, - workspacePermissionKeys: ['dataset.create_and_management'], - })) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/documents/components/document-list/components/document-table-row.tsx b/web/app/components/datasets/documents/components/document-list/components/document-table-row.tsx index 586eb657172..ddb9b5e854a 100644 --- a/web/app/components/datasets/documents/components/document-list/components/document-table-row.tsx +++ b/web/app/components/datasets/documents/components/document-list/components/document-table-row.tsx @@ -1,6 +1,7 @@ import type { SimpleDocumentDetail } from '@/models/datasets' import { Checkbox } from '@langgenius/dify-ui/checkbox' import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' +import { useSuspenseQuery } from '@tanstack/react-query' import { pick } from 'es-toolkit/object' import { useAtomValue } from 'jotai' import * as React from 'react' @@ -10,9 +11,9 @@ import ChunkingModeLabel from '@/app/components/datasets/common/chunking-mode-la import Operations from '@/app/components/datasets/documents/components/operations' import SummaryStatus from '@/app/components/datasets/documents/detail/completed/common/summary-status' import StatusItem from '@/app/components/datasets/documents/status-item' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import useTimestamp from '@/hooks/use-timestamp' import { DataSourceType } from '@/models/datasets' import { useRouter, useSearchParams } from '@/next/navigation' @@ -63,7 +64,10 @@ const DocumentTableRow = React.memo( const searchParams = useSearchParams() const documentNameId = React.useId() const dataset = useDatasetDetailContextWithSelector((s) => s.dataset) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const datasetACLCapabilities = React.useMemo( () => diff --git a/web/app/components/datasets/documents/components/list.tsx b/web/app/components/datasets/documents/components/list.tsx index ff4b0612d37..5a53f1701ae 100644 --- a/web/app/components/datasets/documents/components/list.tsx +++ b/web/app/components/datasets/documents/components/list.tsx @@ -1,17 +1,19 @@ 'use client' + import type { SimpleDocumentDetail } from '@/models/datasets' import { Checkbox } from '@langgenius/dify-ui/checkbox' import { CheckboxGroup } from '@langgenius/dify-ui/checkbox-group' import { Pagination } from '@langgenius/dify-ui/pagination' +import { useSuspenseQuery } from '@tanstack/react-query' import { useBoolean } from 'ahooks' import { useAtomValue } from 'jotai' import { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import EditMetadataBatchModal from '@/app/components/datasets/metadata/edit-metadata-batch/modal' import useBatchEditDocumentMetadata from '@/app/components/datasets/metadata/hooks/use-batch-edit-document-metadata' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector as useDatasetDetailContext } from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { ChunkingMode, DocumentActionType } from '@/models/datasets' import { getDatasetACLCapabilities } from '@/utils/permission' import BatchAction from '../detail/completed/common/batch-action' @@ -63,7 +65,10 @@ const DocumentList = ({ const pageSize = pagination.limit ?? 10 const totalPages = Math.max(Math.ceil(pagination.total / pageSize), 1) const datasetConfig = useDatasetDetailContext((s) => s.dataset) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const datasetACLCapabilities = useMemo( () => diff --git a/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx index f9d7e45089e..d56098c62f1 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx @@ -30,16 +30,6 @@ vi.mock('@/context/provider-context', () => ({ ) => selector({ plan: mockPlan, enableBilling: true }), })) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - - return createAccountStateModuleMock(() => ({ - userProfile: { id: 'user-1' }, - workspacePermissionKeys: ['dataset.create_and_management'], - isLoadingWorkspacePermissionKeys: false, - })) -}) - vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/documents/create-from-pipeline/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/index.tsx index 6e1286c480f..42ac31c89a1 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/index.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/index.tsx @@ -4,7 +4,7 @@ import type { DataSourceNodeType } from '@/app/components/workflow/nodes/data-so import type { Node } from '@/app/components/workflow/types' import type { FileIndexingEstimateResponse } from '@/models/datasets' import type { InitialDocumentDetail } from '@/models/pipeline' -import { useQuery } from '@tanstack/react-query' +import { useQuery, useSuspenseQuery } from '@tanstack/react-query' import { useBoolean } from 'ahooks' import { useAtomValue } from 'jotai' import { useCallback, useEffect, useMemo, useState } from 'react' @@ -12,13 +12,13 @@ import { useTranslation } from 'react-i18next' import Loading from '@/app/components/base/loading' import { PlanUpgradeModal } from '@/app/components/billing/plan-upgrade-modal' import { Plan } from '@/app/components/billing/type' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { workspacePermissionKeysAtom, workspacePermissionKeysLoadingAtom, } from '@/context/permission-state' import { useProviderContextSelector } from '@/context/provider-context' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { DatasourceType } from '@/models/pipeline' import { useRouter } from '@/next/navigation' import { consoleQuery } from '@/service/client' @@ -47,7 +47,10 @@ const CreateFormPipeline = () => { const enableBilling = useProviderContextSelector((state) => state.enableBilling) const dataset = useDatasetDetailContextWithSelector((s) => s.dataset) const pipelineId = dataset?.pipeline_id - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const isLoadingWorkspacePermissionKeys = useAtomValue(workspacePermissionKeysLoadingAtom) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const dataSourceStore = useDataSourceStore() diff --git a/web/app/components/datasets/documents/detail/index.tsx b/web/app/components/datasets/documents/detail/index.tsx index 51f5c3996b9..4d442f6dc22 100644 --- a/web/app/components/datasets/documents/detail/index.tsx +++ b/web/app/components/datasets/documents/detail/index.tsx @@ -1,9 +1,11 @@ 'use client' + import type { FC } from 'react' import type { DocumentDisplayStatus, FileItem, FullDocumentDetail } from '@/models/datasets' import type { SegmentImportStatus } from '@/types/dataset' import { cn } from '@langgenius/dify-ui/cn' import { toast } from '@langgenius/dify-ui/toast' +import { useSuspenseQuery } from '@tanstack/react-query' import { useAtomValue } from 'jotai' import * as React from 'react' import { useCallback, useMemo, useState } from 'react' @@ -12,9 +14,9 @@ import Divider from '@/app/components/base/divider' import FloatRightContainer from '@/app/components/base/float-right-container' import Loading from '@/app/components/base/loading' import Metadata from '@/app/components/datasets/metadata/metadata-document' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import { ChunkingMode, DisplayStatusList } from '@/models/datasets' import { useRouter, useSearchParams } from '@/next/navigation' @@ -60,7 +62,10 @@ const DocumentDetail: FC = ({ datasetId, documentId }) => { const isMobile = media === MediaType.mobile const dataset = useDatasetDetailContextWithSelector((s) => s.dataset) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const embeddingAvailable = !!dataset?.embedding_available const datasetACLCapabilities = useMemo( diff --git a/web/app/components/datasets/documents/index.tsx b/web/app/components/datasets/documents/index.tsx index b042dc7bd98..44b9660aa1a 100644 --- a/web/app/components/datasets/documents/index.tsx +++ b/web/app/components/datasets/documents/index.tsx @@ -1,12 +1,14 @@ 'use client' + import type { FC } from 'react' +import { useSuspenseQuery } from '@tanstack/react-query' import { useAtomValue } from 'jotai' import { useCallback } from 'react' import Loading from '@/app/components/base/loading' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' import { useProviderContext } from '@/context/provider-context' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { DataSourceType } from '@/models/datasets' import { useRouter } from '@/next/navigation' import { @@ -37,7 +39,10 @@ const Documents: FC = ({ datasetId }) => { const isFreePlan = plan.type === 'sandbox' const dataset = useDatasetDetailContextWithSelector((s) => s.dataset) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const embeddingAvailable = !!dataset?.embedding_available const datasetACLCapabilities = getDatasetACLCapabilities(dataset?.permission_keys, { diff --git a/web/app/components/datasets/extra-info/api-access/card.tsx b/web/app/components/datasets/extra-info/api-access/card.tsx index 31e01ea348f..d6aa8ab59d1 100644 --- a/web/app/components/datasets/extra-info/api-access/card.tsx +++ b/web/app/components/datasets/extra-info/api-access/card.tsx @@ -1,13 +1,14 @@ import { cn } from '@langgenius/dify-ui/cn' import { StatusDot } from '@langgenius/dify-ui/status-dot' import { Switch } from '@langgenius/dify-ui/switch' +import { useSuspenseQuery } from '@tanstack/react-query' import { useAtomValue } from 'jotai' import * as React from 'react' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { useDatasetApiAccessUrl } from '@/hooks/use-api-access-url' import Link from '@/next/link' import { @@ -25,7 +26,10 @@ const Card = ({ apiEnabled }: CardProps) => { const datasetId = useDatasetDetailContextWithSelector((state) => state.dataset?.id) const dataset = useDatasetDetailContextWithSelector((state) => state.dataset) const mutateDatasetRes = useDatasetDetailContextWithSelector((state) => state.mutateDatasetRes) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const { mutateAsync: enableDatasetServiceApi } = useEnableDatasetServiceApi() const { mutateAsync: disableDatasetServiceApi } = useDisableDatasetServiceApi() diff --git a/web/app/components/datasets/hit-testing/__tests__/index.spec.tsx b/web/app/components/datasets/hit-testing/__tests__/index.spec.tsx index a3480b34bfa..dcf8190e7fa 100644 --- a/web/app/components/datasets/hit-testing/__tests__/index.spec.tsx +++ b/web/app/components/datasets/hit-testing/__tests__/index.spec.tsx @@ -5,6 +5,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { screen, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { describe, expect, it, vi } from 'vitest' +import { seedAccountProfileQuery } from '@/test/console/account-profile' import { render } from '@/test/console/render' import { RETRIEVE_METHOD } from '@/types/app' import HitTestingPage from '../index' @@ -116,11 +117,6 @@ vi.mock('@/context/dataset-detail', () => ({ ), })) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - - return createAccountStateModuleMock(() => mockConsoleState) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') @@ -307,6 +303,7 @@ const createConsoleQueryClient = () => const TestWrapper = ({ children }: { children: ReactNode }) => { const queryClient = createConsoleQueryClient() + seedAccountProfileQuery(queryClient, mockConsoleState.userProfile) return {children} } diff --git a/web/app/components/datasets/hit-testing/index.tsx b/web/app/components/datasets/hit-testing/index.tsx index e592492e8ea..46029b40338 100644 --- a/web/app/components/datasets/hit-testing/index.tsx +++ b/web/app/components/datasets/hit-testing/index.tsx @@ -1,4 +1,5 @@ 'use client' + import type { FC } from 'react' import type { ExternalKnowledgeBaseHitTesting, @@ -19,6 +20,7 @@ import { DrawerViewport, } from '@langgenius/dify-ui/drawer' import { Pagination } from '@langgenius/dify-ui/pagination' +import { useSuspenseQuery } from '@tanstack/react-query' import { useBoolean } from 'ahooks' import { useAtomValue } from 'jotai' import * as React from 'react' @@ -28,9 +30,9 @@ import { useContext } from 'use-context-selector' import FloatRightContainer from '@/app/components/base/float-right-container' import Loading from '@/app/components/base/loading' import docStyle from '@/app/components/datasets/documents/detail/completed/style.module.css' -import { userProfileIdAtom } from '@/context/account-state' import DatasetDetailContext from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import { useDatasetTestingRecords } from '@/service/knowledge/use-dataset' import { @@ -67,7 +69,10 @@ const HitTestingPage: FC = ({ datasetId }: Props) => { const [currPage, setCurrPage] = useState(0) const { dataset: currentDataset } = useContext(DatasetDetailContext) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const canRunRetrievalRecall = getDatasetACLCapabilities(currentDataset?.permission_keys, { currentUserId, diff --git a/web/app/components/datasets/list/__tests__/index.spec.tsx b/web/app/components/datasets/list/__tests__/index.spec.tsx index eeaedba150d..bf302324b02 100644 --- a/web/app/components/datasets/list/__tests__/index.spec.tsx +++ b/web/app/components/datasets/list/__tests__/index.spec.tsx @@ -85,11 +85,6 @@ vi.mock('@/next/navigation', () => ({ // Mock app context -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - - return createAccountStateModuleMock(() => mockConsoleState) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/list/dataset-card/__tests__/index.spec.tsx b/web/app/components/datasets/list/dataset-card/__tests__/index.spec.tsx index 46dd4ff15f4..8a07e3d9826 100644 --- a/web/app/components/datasets/list/dataset-card/__tests__/index.spec.tsx +++ b/web/app/components/datasets/list/dataset-card/__tests__/index.spec.tsx @@ -1,11 +1,13 @@ import type { DataSet } from '@/models/datasets' +import { QueryClientProvider } from '@tanstack/react-query' import { fireEvent, screen } from '@testing-library/react' import * as React from 'react' import { beforeEach, describe, expect, it, vi } from 'vitest' import { IndexingType } from '@/app/components/datasets/create/step-two' import { STEP_BY_STEP_TOUR_TARGETS } from '@/app/components/step-by-step-tour/target-registry' import { ChunkingMode, DatasetPermission, DataSourceType } from '@/models/datasets' -import { render } from '@/test/console/render' +import { createAccountProfileQueryClient } from '@/test/console/account-profile' +import { render as renderWithConsoleState } from '@/test/console/render' import { DatasetACLPermission } from '@/utils/permission' import DatasetCardFooter from '../components/dataset-card-footer' import Description from '../components/description' @@ -63,11 +65,15 @@ let mockConsoleState = { workspacePermissionKeys: [] as string[], } -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') +const render = (ui: Parameters[0]) => { + const queryClient = createAccountProfileQueryClient(mockConsoleState.userProfile) + return renderWithConsoleState(ui, { + wrapper: ({ children }: { children: React.ReactNode }) => ( + {children} + ), + }) +} - return createAccountStateModuleMock(() => mockConsoleState) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/list/dataset-card/components/__tests__/operations-dropdown.spec.tsx b/web/app/components/datasets/list/dataset-card/components/__tests__/operations-dropdown.spec.tsx index 9cc3f750a41..dd0c20942b6 100644 --- a/web/app/components/datasets/list/dataset-card/components/__tests__/operations-dropdown.spec.tsx +++ b/web/app/components/datasets/list/dataset-card/components/__tests__/operations-dropdown.spec.tsx @@ -22,11 +22,6 @@ const render = (ui: Parameters[0]) => }, }) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - - return createAccountStateModuleMock(() => mockConsoleState) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/list/dataset-card/components/operations-dropdown.tsx b/web/app/components/datasets/list/dataset-card/components/operations-dropdown.tsx index 2b7a269cea9..e7c3663774e 100644 --- a/web/app/components/datasets/list/dataset-card/components/operations-dropdown.tsx +++ b/web/app/components/datasets/list/dataset-card/components/operations-dropdown.tsx @@ -12,8 +12,8 @@ import { getStepByStepTourDropdownMenuContentProps, useStepByStepTourControlledDropdown, } from '@/app/components/step-by-step-tour/dropdown-menu' -import { userProfileIdAtom } from '@/context/account-state' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { systemFeaturesQueryOptions } from '@/features/system-features/client' import { getDatasetACLCapabilities } from '@/utils/permission' import Operations from '../operations' @@ -43,7 +43,10 @@ const OperationsDropdown = ({ }) const open = operationsMenu.open const setOpen = operationsMenu.onOpenChange - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const { data: isRbacEnabled } = useSuspenseQuery({ ...systemFeaturesQueryOptions(), diff --git a/web/app/components/datasets/list/dataset-card/index.tsx b/web/app/components/datasets/list/dataset-card/index.tsx index df280b6e2de..549fdee6143 100644 --- a/web/app/components/datasets/list/dataset-card/index.tsx +++ b/web/app/components/datasets/list/dataset-card/index.tsx @@ -1,13 +1,15 @@ 'use client' + import type { KeyboardEvent, MouseEvent } from 'react' import type { DataSet } from '@/models/datasets' import { cn } from '@langgenius/dify-ui/cn' import { toast } from '@langgenius/dify-ui/toast' +import { useSuspenseQuery } from '@tanstack/react-query' import { useAtomValue } from 'jotai' import { useMemo } from 'react' import { useTranslation } from 'react-i18next' -import { userProfileIdAtom } from '@/context/account-state' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { DatasetCardTags } from '@/features/tag-management/components/dataset-card-tags' import { useRouter } from '@/next/navigation' import { @@ -44,7 +46,10 @@ const DatasetCard = ({ }: DatasetCardProps) => { const { t } = useTranslation() const { push } = useRouter() - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const datasetCard = useDatasetCardController({ dataset, onSuccess }) diff --git a/web/app/components/datasets/settings/form/__tests__/index.spec.tsx b/web/app/components/datasets/settings/form/__tests__/index.spec.tsx index bf7622291e6..345b3c595e0 100644 --- a/web/app/components/datasets/settings/form/__tests__/index.spec.tsx +++ b/web/app/components/datasets/settings/form/__tests__/index.spec.tsx @@ -28,14 +28,6 @@ const mockUserProfile = { } let mockWorkspacePermissionKeys = ['dataset.create_and_management'] -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - - return createAccountStateModuleMock(() => ({ - userProfile: mockUserProfile, - workspacePermissionKeys: mockWorkspacePermissionKeys, - })) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/settings/form/components/__tests__/basic-info-section.spec.tsx b/web/app/components/datasets/settings/form/components/__tests__/basic-info-section.spec.tsx index e7b41259aff..63926bcbcfc 100644 --- a/web/app/components/datasets/settings/form/components/__tests__/basic-info-section.spec.tsx +++ b/web/app/components/datasets/settings/form/components/__tests__/basic-info-section.spec.tsx @@ -22,11 +22,6 @@ const mockConsoleState = vi.hoisted(() => ({ // Mock app-context -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - - return createAccountStateModuleMock(() => mockConsoleState) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/settings/form/hooks/__tests__/use-form-state.spec.ts b/web/app/components/datasets/settings/form/hooks/__tests__/use-form-state.spec.ts index bed86036f61..814074e6f7c 100644 --- a/web/app/components/datasets/settings/form/hooks/__tests__/use-form-state.spec.ts +++ b/web/app/components/datasets/settings/form/hooks/__tests__/use-form-state.spec.ts @@ -7,7 +7,8 @@ import { DataSourceType, WeightedScoreEnum, } from '@/models/datasets' -import { renderHook } from '@/test/console/render' +import { createAccountProfileQueryWrapper } from '@/test/console/account-profile' +import { renderHook as renderHookWithConsoleState } from '@/test/console/render' import { RETRIEVE_METHOD } from '@/types/app' import { DatasetACLPermission } from '@/utils/permission' import { IndexingType } from '../../../../create/step-two' @@ -22,14 +23,11 @@ const { mockToastSuccess, mockToastError } = vi.hoisted(() => ({ const mockMutateDatasets = vi.fn() const mockInvalidDatasetList = vi.fn() -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') +const renderHook = (callback: () => ReturnType) => + renderHookWithConsoleState(callback, { + wrapper: createAccountProfileQueryWrapper({ id: 'user-1' }), + }) - return createAccountStateModuleMock(() => ({ - userProfile: { id: 'user-1' }, - workspacePermissionKeys: [], - })) -}) vi.mock('@/context/workspace-state', async () => { const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture') diff --git a/web/app/components/datasets/settings/form/hooks/use-form-state.ts b/web/app/components/datasets/settings/form/hooks/use-form-state.ts index 33c18d18f82..b02939980d9 100644 --- a/web/app/components/datasets/settings/form/hooks/use-form-state.ts +++ b/web/app/components/datasets/settings/form/hooks/use-form-state.ts @@ -1,19 +1,21 @@ 'use client' + import type { AppIconSelection } from '@/app/components/base/app-icon-picker' import type { DefaultModel } from '@/app/components/header/account-setting/model-provider-page/declarations' import type { Member } from '@/models/common' import type { IconInfo, SummaryIndexSetting as SummaryIndexSettingType } from '@/models/datasets' import type { RetrievalConfig } from '@/types/app' import { toast } from '@langgenius/dify-ui/toast' +import { useSuspenseQuery } from '@tanstack/react-query' import { useAtomValue } from 'jotai' import { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model' import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { DatasetPermission } from '@/models/datasets' import { updateDatasetSetting } from '@/service/datasets' import { useInvalidDatasetList } from '@/service/knowledge/use-dataset' @@ -32,7 +34,10 @@ export const useFormState = () => { const { t } = useTranslation() const currentDataset = useDatasetDetailContextWithSelector((state) => state.dataset) const mutateDatasets = useDatasetDetailContextWithSelector((state) => state.mutateDatasetRes) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const datasetACLCapabilities = useMemo( () => diff --git a/web/app/components/datasets/settings/permission-selector/index.tsx b/web/app/components/datasets/settings/permission-selector/index.tsx index ca1dd037a48..dfd41376f5a 100644 --- a/web/app/components/datasets/settings/permission-selector/index.tsx +++ b/web/app/components/datasets/settings/permission-selector/index.tsx @@ -6,10 +6,9 @@ import { Popover, PopoverContent, PopoverTitle, PopoverTrigger } from '@langgeni import { RadioGroup } from '@langgenius/dify-ui/radio' import { useSuspenseQuery } from '@tanstack/react-query' import { useDebounceFn } from 'ahooks' -import { useAtomValue } from 'jotai' import { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' -import { userProfileAtom } from '@/context/account-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { systemFeaturesQueryOptions } from '@/features/system-features/client' import { DatasetPermission } from '@/models/datasets' import MemberItem from './member-item' @@ -33,7 +32,10 @@ const PermissionSelector = ({ onMemberSelect, }: PermissionSelectorProps) => { const { t } = useTranslation() - const userProfile = useAtomValue(userProfileAtom) + const { data: userProfile } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile, + }) const { data: isRbacEnabled } = useSuspenseQuery({ ...systemFeaturesQueryOptions(), select: ({ rbac_enabled }) => rbac_enabled, diff --git a/web/app/components/rag-pipeline/components/conversion.tsx b/web/app/components/rag-pipeline/components/conversion.tsx index b29a77dac9d..0e873ff1990 100644 --- a/web/app/components/rag-pipeline/components/conversion.tsx +++ b/web/app/components/rag-pipeline/components/conversion.tsx @@ -9,13 +9,14 @@ import { } from '@langgenius/dify-ui/alert-dialog' import { Button } from '@langgenius/dify-ui/button' import { toast } from '@langgenius/dify-ui/toast' +import { useSuspenseQuery } from '@tanstack/react-query' import { useAtomValue } from 'jotai' import * as React from 'react' import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { useParams } from '@/next/navigation' import { datasetDetailQueryKeyPrefix } from '@/service/knowledge/use-dataset' import { useInvalid } from '@/service/use-base' @@ -27,7 +28,10 @@ const Conversion = () => { const { t } = useTranslation() const { datasetId } = useParams() const dataset = useDatasetDetailContextWithSelector((state) => state.dataset) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const [showConfirmModal, setShowConfirmModal] = useState(false) const { mutateAsync: convert, isPending } = useConvertDatasetToPipeline() diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx index 89ff198d01b..513bd0d516a 100644 --- a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx +++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx @@ -3,6 +3,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { act, fireEvent, screen, waitFor } from '@testing-library/react' import * as React from 'react' import { beforeEach, describe, expect, it, vi } from 'vitest' +import { seedAccountProfileQuery } from '@/test/console/account-profile' import { seedSystemFeatures } from '@/test/console/query-data' import { render } from '@/test/console/render' import Publisher from '../index' @@ -113,16 +114,6 @@ vi.mock('@/context/dataset-detail', () => ({ }, })) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - return createAccountStateModuleMock(() => ({ - userProfile: { - id: mockCurrentUserId, - }, - isLoadingWorkspacePermissionKeys: mockIsLoadingWorkspacePermissionKeys, - workspacePermissionKeys: mockWorkspacePermissionKeys, - })) -}) vi.mock('@/context/permission-state', async () => { const { createPermissionStateModuleMock } = await import('@/test/console/state-fixture') return createPermissionStateModuleMock(() => ({ @@ -267,6 +258,7 @@ const createQueryClient = () => const renderWithQueryClient = (ui: React.ReactElement) => { const queryClient = createQueryClient() + seedAccountProfileQuery(queryClient, { id: 'user-1' }) seedSystemFeatures(queryClient, { deployment_edition: 'CLOUD' }) return render({ui}) } diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/popup.spec.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/popup.spec.tsx index caf958a996a..f91c8515985 100644 --- a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/popup.spec.tsx +++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/popup.spec.tsx @@ -137,16 +137,6 @@ vi.mock('@/context/dataset-detail', () => ({ }), })) -vi.mock('@/context/account-state', async () => { - const { createAccountStateModuleMock } = await import('@/test/console/state-fixture') - return createAccountStateModuleMock(() => ({ - userProfile: { - id: mockCurrentUserId, - }, - isLoadingWorkspacePermissionKeys: mockIsLoadingWorkspacePermissionKeys, - workspacePermissionKeys: mockWorkspacePermissionKeys, - })) -}) vi.mock('@/context/permission-state', async () => { const { createPermissionStateModuleMock } = await import('@/test/console/state-fixture') return createPermissionStateModuleMock(() => ({ diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx index 14facb05ffa..aedcef6fb68 100644 --- a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx +++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx @@ -25,7 +25,6 @@ import { SparklesSoft } from '@/app/components/base/icons/src/public/common' import PremiumBadge from '@/app/components/base/premium-badge' import { useChecklistBeforePublish } from '@/app/components/workflow/hooks/use-checklist' import { useStore, useWorkflowStore } from '@/app/components/workflow/store' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { useModalContextSelector } from '@/context/modal-context' import { @@ -33,6 +32,7 @@ import { workspacePermissionKeysLoadingAtom, } from '@/context/permission-state' import { useProviderContextSelector } from '@/context/provider-context' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { systemFeaturesQueryOptions } from '@/features/system-features/client' import { useDatasetApiAccessUrl } from '@/hooks/use-api-access-url' import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now' @@ -74,7 +74,10 @@ export function Popup({ const pipelineId = useStore((s) => s.pipelineId) const dataset = useDatasetDetailContextWithSelector((s) => s.dataset) const mutateDatasetRes = useDatasetDetailContextWithSelector((s) => s.mutateDatasetRes) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const isLoadingWorkspacePermissionKeys = useAtomValue(workspacePermissionKeysLoadingAtom) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const [published, setPublished] = useState(false) diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-main.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-main.tsx index c6a2b53fd88..98bbe021d96 100644 --- a/web/app/components/rag-pipeline/components/rag-pipeline-main.tsx +++ b/web/app/components/rag-pipeline/components/rag-pipeline-main.tsx @@ -1,13 +1,14 @@ import type { WorkflowProps } from '@/app/components/workflow' import type { Shape as HooksStoreShape } from '@/app/components/workflow/hooks-store' +import { useSuspenseQuery } from '@tanstack/react-query' import { useAtomValue } from 'jotai' import { useCallback, useMemo } from 'react' import { WorkflowWithInnerContext } from '@/app/components/workflow' import { useSetWorkflowVarsWithValue } from '@/app/components/workflow/hooks/use-fetch-workflow-inspect-vars' import { useWorkflowStore } from '@/app/components/workflow/store' -import { userProfileIdAtom } from '@/context/account-state' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { workspacePermissionKeysAtom } from '@/context/permission-state' +import { userProfileQueryOptions } from '@/features/account-profile/client' import { getDatasetACLCapabilities } from '@/utils/permission' import { useAvailableNodesMetaData } from '../hooks/use-available-nodes-meta-data' import { useConfigsMap } from '../hooks/use-configs-map' @@ -24,7 +25,10 @@ type RagPipelineMainProps = Pick const RagPipelineMain = ({ nodes, edges, viewport }: RagPipelineMainProps) => { const workflowStore = useWorkflowStore() const dataset = useDatasetDetailContextWithSelector((s) => s.dataset) - const currentUserId = useAtomValue(userProfileIdAtom) + const { data: currentUserId } = useSuspenseQuery({ + ...userProfileQueryOptions(), + select: (data) => data.profile.id, + }) const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom) const datasetACLCapabilities = useMemo( () =>