mirror of
https://github.com/langgenius/dify.git
synced 2026-06-07 16:32:01 +08:00
fix(web): use generated account-profile contracts (#36927)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
3cd0da303a
commit
dea4e66456
@ -18,7 +18,7 @@ from controllers.common.fields import (
|
||||
SimpleResultResponse,
|
||||
VerificationTokenResponse,
|
||||
)
|
||||
from controllers.common.schema import register_response_schema_models, register_schema_models
|
||||
from controllers.common.schema import query_params_from_model, register_response_schema_models, register_schema_models
|
||||
from controllers.console import console_ns
|
||||
from controllers.console.auth.error import (
|
||||
EmailAlreadyInUseError,
|
||||
@ -48,7 +48,7 @@ from fields.base import ResponseModel
|
||||
from fields.member_fields import Account as AccountResponse
|
||||
from graphon.file import helpers as file_helpers
|
||||
from libs.datetime_utils import naive_utc_now
|
||||
from libs.helper import EmailStr, extract_remote_ip, timezone, to_timestamp
|
||||
from libs.helper import EmailStr, dump_response, extract_remote_ip, timezone, to_timestamp
|
||||
from libs.login import current_account_with_tenant, login_required
|
||||
from models import AccountIntegrate, InvitationCode
|
||||
from models.account import AccountStatus, InvitationCodeStatus
|
||||
@ -329,9 +329,9 @@ class AccountNameApi(Resource):
|
||||
|
||||
@console_ns.route("/account/avatar")
|
||||
class AccountAvatarApi(Resource):
|
||||
@console_ns.expect(console_ns.models[AccountAvatarQuery.__name__])
|
||||
@console_ns.doc("get_account_avatar")
|
||||
@console_ns.doc(description="Get account avatar url")
|
||||
@console_ns.doc(params=query_params_from_model(AccountAvatarQuery))
|
||||
@console_ns.response(200, "Success", console_ns.models[AvatarUrlResponse.__name__])
|
||||
@setup_required
|
||||
@login_required
|
||||
@ -342,7 +342,7 @@ class AccountAvatarApi(Resource):
|
||||
avatar = args.avatar
|
||||
|
||||
if avatar.startswith(("http://", "https://")):
|
||||
return {"avatar_url": avatar}
|
||||
return dump_response(AvatarUrlResponse, {"avatar_url": avatar})
|
||||
|
||||
upload_file = db.session.scalar(select(UploadFile).where(UploadFile.id == avatar).limit(1))
|
||||
if upload_file is None:
|
||||
@ -355,7 +355,7 @@ class AccountAvatarApi(Resource):
|
||||
raise NotFound("Avatar file not found")
|
||||
|
||||
avatar_url = file_helpers.get_signed_file_url(upload_file_id=upload_file.id)
|
||||
return {"avatar_url": avatar_url}
|
||||
return dump_response(AvatarUrlResponse, {"avatar_url": avatar_url})
|
||||
|
||||
@console_ns.expect(console_ns.models[AccountAvatarPayload.__name__])
|
||||
@setup_required
|
||||
|
||||
@ -27,7 +27,7 @@ Get account avatar url
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| payload | body | | Yes | [AccountAvatarQuery](#accountavatarquery) |
|
||||
| avatar | query | Avatar file ID | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
|
||||
@ -140,3 +140,23 @@ def test_service_document_list_documents_query_params_render(monkeypatch: pytest
|
||||
|
||||
for name in ("page", "limit", "keyword", "status"):
|
||||
assert params[name]["in"] == "query"
|
||||
|
||||
|
||||
def test_console_account_avatar_query_param_renders_as_query(monkeypatch: pytest.MonkeyPatch):
|
||||
from configs import dify_config
|
||||
from controllers.console import bp as console_bp
|
||||
|
||||
monkeypatch.setattr(dify_config, "SWAGGER_UI_ENABLED", True)
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config["TESTING"] = True
|
||||
app.config["RESTX_INCLUDE_ALL_MODELS"] = True
|
||||
app.register_blueprint(console_bp)
|
||||
|
||||
payload = app.test_client().get("/console/api/swagger.json").get_json()
|
||||
operation = payload["paths"]["/account/avatar"]["get"]
|
||||
params = _parameters_by_name(operation)
|
||||
|
||||
assert "payload" not in params
|
||||
assert params["avatar"]["in"] == "query"
|
||||
assert params["avatar"]["required"] is True
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
import type { ReactNode } from 'react'
|
||||
import { act, fireEvent, screen, waitFor } from '@testing-library/react'
|
||||
import { AccountProfileQueryProvider, createAccountProfileQueryClient } from '@/test/account-profile-query'
|
||||
import { renderWithNuqs } from '@/test/nuqs-testing'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import ConversationList from '../list'
|
||||
@ -234,12 +235,15 @@ const renderConversationList = ({
|
||||
logs?: any
|
||||
searchParams?: string
|
||||
} = {}) => {
|
||||
const queryClient = createAccountProfileQueryClient({ timezone: 'Asia/Shanghai' })
|
||||
return renderWithNuqs(
|
||||
<ConversationList
|
||||
appDetail={appDetail}
|
||||
logs={logs}
|
||||
onRefresh={mockOnRefresh}
|
||||
/>,
|
||||
<AccountProfileQueryProvider queryClient={queryClient}>
|
||||
<ConversationList
|
||||
appDetail={appDetail}
|
||||
logs={logs}
|
||||
onRefresh={mockOnRefresh}
|
||||
/>
|
||||
</AccountProfileQueryProvider>,
|
||||
{ searchParams },
|
||||
)
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import { StatusDot } from '@langgenius/dify-ui/status-dot'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiCloseLine, RiEditFill } from '@remixicon/react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import dayjs from 'dayjs'
|
||||
import timezone from 'dayjs/plugin/timezone'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
@ -40,7 +41,7 @@ import CopyIcon from '@/app/components/base/copy-icon'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import MessageLogModal from '@/app/components/base/message-log-modal'
|
||||
import { WorkflowContextProvider } from '@/app/components/workflow/context'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
import { fetchChatMessages, updateLogMessageAnnotations, updateLogMessageFeedbacks } from '@/service/log'
|
||||
@ -158,7 +159,10 @@ type IDetailPanel = {
|
||||
function DetailPanel({ detail, onFeedback }: IDetailPanel) {
|
||||
const MIN_ITEMS_FOR_SCROLL_LOADING = 8
|
||||
const SCROLL_DEBOUNCE_MS = 200
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
const { data: timezone } = useQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: data => data.profile.timezone ?? undefined,
|
||||
})
|
||||
const { formatTime } = useTimestamp()
|
||||
const { onClose, appDetail } = useContext(DrawerContext)
|
||||
const { currentLogItem, setCurrentLogItem, showMessageLogModal, setShowMessageLogModal, showPromptLogModal, setShowPromptLogModal, currentLogModalActiveTab } = useAppStore(useShallow((state: AppStoreState) => ({
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
import type { FC } from 'react'
|
||||
import type { App } from '@/types/app'
|
||||
import { Pagination } from '@langgenius/dify-ui/pagination'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useDebounce } from 'ahooks'
|
||||
import dayjs from 'dayjs'
|
||||
import timezone from 'dayjs/plugin/timezone'
|
||||
@ -13,7 +14,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import EmptyElement from '@/app/components/app/log/empty-element'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { APP_PAGE_LIMIT } from '@/config'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { useWorkflowLogs } from '@/service/use-log'
|
||||
import Filter, { TIME_PERIOD_MAPPING } from './filter'
|
||||
import List from './list'
|
||||
@ -33,7 +34,10 @@ export type QueryParam = {
|
||||
|
||||
const Logs: FC<ILogsProps> = ({ appDetail }) => {
|
||||
const { t } = useTranslation()
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
const { data: timezone } = useQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: data => data.profile.timezone ?? undefined,
|
||||
})
|
||||
const [queryParams, setQueryParams] = useState<QueryParam>({ status: 'all', period: '2' })
|
||||
const [currPage, setCurrPage] = React.useState<number>(0)
|
||||
const debouncedQueryParams = useDebounce(queryParams, { wait: 500 })
|
||||
|
||||
@ -64,6 +64,13 @@ vi.mock('@/utils/model-config', () => ({
|
||||
formatBooleanInputs: vi.fn((forms, inputs) => inputs),
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/use-timestamp', () => ({
|
||||
default: () => ({
|
||||
formatTime: (timestamp: number) => `formatted-${timestamp}`,
|
||||
formatDate: (value: string) => `formatted-${value}`,
|
||||
}),
|
||||
}))
|
||||
|
||||
type ChatHookReturn = ReturnType<typeof useChat>
|
||||
|
||||
const mockAppData = {
|
||||
|
||||
@ -10,6 +10,13 @@ vi.mock('../context', () => ({
|
||||
})),
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/use-timestamp', () => ({
|
||||
default: () => ({
|
||||
formatTime: (timestamp: number) => `formatted-${timestamp}`,
|
||||
formatDate: (value: string) => `formatted-${value}`,
|
||||
}),
|
||||
}))
|
||||
|
||||
describe('Answer Component', () => {
|
||||
const defaultProps = {
|
||||
item: {
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
||||
import type { Mock } from 'vitest'
|
||||
import type { UsagePlanInfo } from '@/app/components/billing/type'
|
||||
import type { AppContextValue } from '@/context/app-context'
|
||||
import type { ProviderContextState } from '@/context/provider-context'
|
||||
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
|
||||
import type { ICurrentWorkspace, LangGeniusVersionResponse } from '@/models/common'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { Plan } from '@/app/components/billing/type'
|
||||
import { mailToSupport } from '@/app/components/header/utils/util'
|
||||
@ -59,7 +60,7 @@ const buildProviderContext = (overrides: Partial<ProviderContextState> = {}): Pr
|
||||
})
|
||||
|
||||
const buildAppContext = (overrides: Partial<AppContextValue> = {}): AppContextValue => {
|
||||
const userProfile: UserProfileResponse = {
|
||||
const userProfile: GetAccountProfileResponse = {
|
||||
id: 'user-id',
|
||||
name: 'Test User',
|
||||
email: 'user@example.com',
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import type { ReactElement } from 'react'
|
||||
import { fireEvent, render as rtlRender, screen } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { createAccountProfileQueryWrapper } from '@/test/account-profile-query'
|
||||
import WrappedDatePicker from '../date-picker'
|
||||
|
||||
type TriggerArgs = {
|
||||
@ -44,6 +46,11 @@ vi.mock('@/hooks/use-timestamp', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
const render = (ui: ReactElement) => {
|
||||
const Wrapper = createAccountProfileQueryWrapper()
|
||||
return rtlRender(ui, { wrapper: Wrapper })
|
||||
}
|
||||
|
||||
describe('WrappedDatePicker', () => {
|
||||
describe('Rendering', () => {
|
||||
it('should render without crashing', () => {
|
||||
|
||||
@ -4,11 +4,12 @@ import {
|
||||
RiCalendarLine,
|
||||
RiCloseCircleFill,
|
||||
} from '@remixicon/react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import DatePicker from '@/app/components/base/date-and-time-picker/date-picker'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
|
||||
type Props = {
|
||||
@ -24,7 +25,10 @@ const WrappedDatePicker = ({
|
||||
onChange,
|
||||
}: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
const { data: timezone } = useQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: data => data.profile.timezone ?? undefined,
|
||||
})
|
||||
const { formatTime: formatTimestamp } = useTimestamp()
|
||||
|
||||
const handleDateChange = useCallback((date?: dayjs.Dayjs) => {
|
||||
|
||||
@ -51,6 +51,12 @@ vi.mock('@/next/navigation', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/use-timestamp', () => ({
|
||||
default: () => ({
|
||||
formatTime: (timestamp: number) => `formatted-${timestamp}`,
|
||||
}),
|
||||
}))
|
||||
|
||||
describe('MetadataDocument', () => {
|
||||
const mockDocDetail = {
|
||||
id: 'doc-1',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { UserProfileResponse } from '@/models/common'
|
||||
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
||||
import { ToastHost } from '@langgenius/dify-ui/toast'
|
||||
import { act, fireEvent, render, screen, waitFor, within } from '@testing-library/react'
|
||||
import { languages } from '@/i18n-config/language'
|
||||
@ -9,7 +9,7 @@ import LanguagePage from '../index'
|
||||
const mockRefresh = vi.fn()
|
||||
const mockMutateUserProfile = vi.fn()
|
||||
let mockLocale: string | undefined = 'en-US'
|
||||
let mockUserProfile: UserProfileResponse
|
||||
let mockUserProfile: GetAccountProfileResponse
|
||||
|
||||
vi.mock('@langgenius/dify-ui/select', async () => {
|
||||
const React = await import('react')
|
||||
@ -89,7 +89,7 @@ vi.mock('@/i18n-config', () => ({
|
||||
|
||||
const updateUserProfileMock = vi.mocked(updateUserProfile)
|
||||
|
||||
const createUserProfile = (overrides: Partial<UserProfileResponse> = {}): UserProfileResponse => ({
|
||||
const createUserProfile = (overrides: Partial<GetAccountProfileResponse> = {}): GetAccountProfileResponse => ({
|
||||
id: 'user-id',
|
||||
name: 'Test User',
|
||||
email: 'test@example.com',
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import type { ReactElement } from 'react'
|
||||
import type { PluginDetail } from '@/app/components/plugins/types'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { fireEvent, render as rtlRender, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { PluginCategoryEnum, PluginSource } from '@/app/components/plugins/types'
|
||||
import { createAccountProfileQueryWrapper } from '@/test/account-profile-query'
|
||||
import DetailHeader from '../index'
|
||||
|
||||
const mockSetTargetVersion = vi.fn()
|
||||
@ -10,6 +12,11 @@ const mockHandleUpdate = vi.fn()
|
||||
const mockHandleUpdatedFromMarketplace = vi.fn()
|
||||
const mockHandleDelete = vi.fn()
|
||||
|
||||
const render = (ui: ReactElement) => {
|
||||
const Wrapper = createAccountProfileQueryWrapper({ timezone: 'UTC' })
|
||||
return rtlRender(ui, { wrapper: Wrapper })
|
||||
}
|
||||
|
||||
vi.mock('@/context/app-context', () => ({
|
||||
useAppContext: () => ({
|
||||
userProfile: { timezone: 'UTC' },
|
||||
|
||||
@ -4,6 +4,7 @@ import type { PluginDetail } from '../../types'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
@ -12,8 +13,8 @@ import { AuthCategory, PluginAuth } from '@/app/components/plugins/plugin-auth'
|
||||
import OperationDropdown from '@/app/components/plugins/plugin-detail-panel/operation-dropdown'
|
||||
import PluginVersionPicker from '@/app/components/plugins/update-plugin/plugin-version-picker'
|
||||
import { API_PREFIX } from '@/config'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useGetLanguage, useLocale } from '@/context/i18n'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
import { useAllToolProviders } from '@/service/use-tools'
|
||||
import { getMarketplaceUrl } from '@/utils/var'
|
||||
@ -72,7 +73,10 @@ const DetailHeader = ({
|
||||
onUpdate,
|
||||
}: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
const { data: timezone } = useQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: data => data.profile.timezone ?? undefined,
|
||||
})
|
||||
const { theme } = useTheme()
|
||||
const locale = useGetLanguage()
|
||||
const currentLocale = useLocale()
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import type { AutoUpdateConfig } from '../types'
|
||||
import type { PluginDeclaration, PluginDetail } from '@/app/components/plugins/types'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { QueryClientProvider } from '@tanstack/react-query'
|
||||
import { fireEvent, render as rtlRender, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import dayjs from 'dayjs'
|
||||
import timezone from 'dayjs/plugin/timezone'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
import * as React from 'react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { createAccountProfileQueryClient } from '@/test/account-profile-query'
|
||||
import { PluginCategoryEnum, PluginSource } from '../../../types'
|
||||
import { defaultValue } from '../config'
|
||||
import AutoUpdateSetting from '../index'
|
||||
@ -291,21 +292,22 @@ const createMockAutoUpdateConfig = (overrides: Partial<AutoUpdateConfig> = {}):
|
||||
// Helper Functions
|
||||
// ================================
|
||||
|
||||
const createQueryClient = () => new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
const createQueryClient = () => createAccountProfileQueryClient({ timezone: mockTimezone })
|
||||
|
||||
const render = (ui: React.ReactElement) => {
|
||||
const queryClient = createQueryClient()
|
||||
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
)
|
||||
return rtlRender(ui, { wrapper: Wrapper })
|
||||
}
|
||||
|
||||
const renderWithQueryClient = (ui: React.ReactElement) => {
|
||||
const queryClient = createQueryClient()
|
||||
return render(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{ui}
|
||||
</QueryClientProvider>,
|
||||
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
)
|
||||
return rtlRender(ui, { wrapper: Wrapper })
|
||||
}
|
||||
|
||||
// ================================
|
||||
|
||||
@ -4,6 +4,7 @@ import type { AutoUpdateConfig } from './types'
|
||||
import type { TriggerParams } from '@/app/components/base/date-and-time-picker/types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { RiTimeLine } from '@remixicon/react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
@ -11,8 +12,8 @@ import TimePicker from '@/app/components/base/date-and-time-picker/time-picker'
|
||||
import { convertTimezoneToOffsetStr } from '@/app/components/base/date-and-time-picker/utils/dayjs'
|
||||
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
|
||||
import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useModalContextSelector } from '@/context/modal-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import Label from '../label'
|
||||
import PluginsPicker from './plugins-picker'
|
||||
import StrategyPicker from './strategy-picker'
|
||||
@ -47,7 +48,10 @@ const AutoUpdateSetting: FC<Props> = ({
|
||||
onChange,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
const { data: timezone } = useQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: data => data.profile.timezone ?? undefined,
|
||||
})
|
||||
|
||||
const {
|
||||
strategy_setting,
|
||||
|
||||
@ -12,6 +12,7 @@ import {
|
||||
DatasetPermission,
|
||||
DataSourceType,
|
||||
} from '@/models/datasets'
|
||||
import { AccountProfileQueryProvider, createAccountProfileQueryClient } from '@/test/account-profile-query'
|
||||
import { RETRIEVE_METHOD, RETRIEVE_TYPE } from '@/types/app'
|
||||
import { DatasetsDetailContext } from '../../../datasets-detail-store/provider'
|
||||
import { createDatasetsDetailStore } from '../../../datasets-detail-store/store'
|
||||
@ -583,25 +584,28 @@ describe('knowledge-retrieval path', () => {
|
||||
const onDateChange = vi.fn()
|
||||
const onRemoveCondition = vi.fn()
|
||||
const onUpdateCondition = vi.fn()
|
||||
const queryClient = createAccountProfileQueryClient({ timezone: 'UTC' })
|
||||
|
||||
const { container } = render(
|
||||
<div>
|
||||
<ConditionOperator
|
||||
variableType={MetadataFilteringVariableType.string}
|
||||
value={MetadataComparisonOperator.contains}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
<ConditionDate
|
||||
value={1710000000}
|
||||
onChange={onDateChange}
|
||||
/>
|
||||
<ConditionItem
|
||||
metadataList={[createMetadata()]}
|
||||
condition={createCondition()}
|
||||
onRemoveCondition={onRemoveCondition}
|
||||
onUpdateCondition={onUpdateCondition}
|
||||
/>
|
||||
</div>,
|
||||
<AccountProfileQueryProvider queryClient={queryClient}>
|
||||
<div>
|
||||
<ConditionOperator
|
||||
variableType={MetadataFilteringVariableType.string}
|
||||
value={MetadataComparisonOperator.contains}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
<ConditionDate
|
||||
value={1710000000}
|
||||
onChange={onDateChange}
|
||||
/>
|
||||
<ConditionItem
|
||||
metadataList={[createMetadata()]}
|
||||
condition={createCondition()}
|
||||
onRemoveCondition={onRemoveCondition}
|
||||
onUpdateCondition={onUpdateCondition}
|
||||
/>
|
||||
</div>
|
||||
</AccountProfileQueryProvider>,
|
||||
)
|
||||
|
||||
await user.click(screen.getAllByRole('button', { name: /contains/i })[0]!)
|
||||
|
||||
@ -4,11 +4,12 @@ import {
|
||||
RiCalendarLine,
|
||||
RiCloseCircleFill,
|
||||
} from '@remixicon/react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import DatePicker from '@/app/components/base/date-and-time-picker/date-picker'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
|
||||
type ConditionDateProps = {
|
||||
value?: number
|
||||
@ -19,7 +20,10 @@ const ConditionDate = ({
|
||||
onChange,
|
||||
}: ConditionDateProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
const { data: timezone } = useQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: data => data.profile.timezone ?? undefined,
|
||||
})
|
||||
|
||||
const handleDateChange = useCallback((date?: dayjs.Dayjs) => {
|
||||
if (date)
|
||||
|
||||
@ -3,6 +3,7 @@ import { renderHook } from '@testing-library/react'
|
||||
import { useNodesReadOnly } from '@/app/components/workflow/hooks'
|
||||
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { createAccountProfileQueryWrapper } from '@/test/account-profile-query'
|
||||
import { BlockEnum } from '../../../types'
|
||||
import useConfig from '../use-config'
|
||||
|
||||
@ -60,7 +61,7 @@ describe('trigger-schedule/use-config', () => {
|
||||
frequency: undefined,
|
||||
timezone: undefined,
|
||||
visual_config: undefined,
|
||||
})))
|
||||
})), { wrapper: createAccountProfileQueryWrapper() })
|
||||
|
||||
expect(mockUseNodeCrud).toHaveBeenCalledWith('schedule-node', expect.objectContaining({
|
||||
mode: 'visual',
|
||||
@ -78,7 +79,7 @@ describe('trigger-schedule/use-config', () => {
|
||||
it('updates visual mode configuration and clears cron expression when needed', () => {
|
||||
const { result } = renderHook(() => useConfig('schedule-node', createData({
|
||||
cron_expression: '0 0 * * *',
|
||||
})))
|
||||
})), { wrapper: createAccountProfileQueryWrapper() })
|
||||
|
||||
result.current.handleModeChange('cron')
|
||||
result.current.handleFrequencyChange('hourly')
|
||||
@ -107,7 +108,7 @@ describe('trigger-schedule/use-config', () => {
|
||||
})
|
||||
|
||||
it('switches to raw cron mode and clears visual schedule fields', () => {
|
||||
const { result } = renderHook(() => useConfig('schedule-node', createData()))
|
||||
const { result } = renderHook(() => useConfig('schedule-node', createData()), { wrapper: createAccountProfileQueryWrapper() })
|
||||
|
||||
result.current.handleCronExpressionChange('*/15 * * * *')
|
||||
|
||||
|
||||
@ -1,27 +1,31 @@
|
||||
import type { ScheduleFrequency, ScheduleMode, ScheduleTriggerNodeType } from './types'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useNodesReadOnly } from '@/app/components/workflow/hooks'
|
||||
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { getDefaultVisualConfig } from './constants'
|
||||
|
||||
const useConfig = (id: string, payload: ScheduleTriggerNodeType) => {
|
||||
const { nodesReadOnly: readOnly } = useNodesReadOnly()
|
||||
|
||||
const { userProfile } = useAppContext()
|
||||
const { data: timezone } = useQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: data => data.profile.timezone ?? undefined,
|
||||
})
|
||||
|
||||
const frontendPayload = useMemo(() => {
|
||||
return {
|
||||
...payload,
|
||||
mode: payload.mode || 'visual',
|
||||
frequency: payload.frequency || 'daily',
|
||||
timezone: payload.timezone || userProfile.timezone || 'UTC',
|
||||
timezone: payload.timezone || timezone || 'UTC',
|
||||
visual_config: {
|
||||
...getDefaultVisualConfig(),
|
||||
...payload.visual_config,
|
||||
},
|
||||
}
|
||||
}, [payload, userProfile.timezone])
|
||||
}, [payload, timezone])
|
||||
|
||||
const { inputs, setInputs } = useNodeCrud<ScheduleTriggerNodeType>(id, frontendPayload)
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type { SearchParams } from './types'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useDebounceFn } from 'ahooks'
|
||||
import dayjs from 'dayjs'
|
||||
import timezone from 'dayjs/plugin/timezone'
|
||||
@ -9,9 +10,9 @@ import {
|
||||
useState,
|
||||
} from 'react'
|
||||
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useModalContextSelector } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { useLocalStorage } from '@/hooks/use-local-storage'
|
||||
import { useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { useEducationAutocomplete, useEducationVerify } from '@/service/use-education'
|
||||
@ -81,7 +82,10 @@ const isExpired = (expireAt?: number, timezone?: string) => {
|
||||
const useEducationReverifyNotice = ({
|
||||
onNotice,
|
||||
}: useEducationReverifyNoticeParams) => {
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
const { data: timezone } = useQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: data => data.profile.timezone ?? undefined,
|
||||
})
|
||||
// const [educationInfo, setEducationInfo] = useState<{ is_student: boolean, allow_refresh: boolean, expire_at: number | null } | null>(null)
|
||||
// const isLoading = !educationInfo
|
||||
const { educationAccountExpireAt, allowRefreshEducationVerify, isLoadingEducationAccountInfo: isLoading } = useProviderContext()
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
'use client'
|
||||
|
||||
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
||||
import type { PostWorkspacesCurrentResponse } from '@dify/contracts/api/console/workspaces/types.gen'
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
|
||||
import type { ICurrentWorkspace, LangGeniusVersionResponse } from '@/models/common'
|
||||
import { useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import { setUserId, setUserProperties } from '@/app/components/base/amplitude'
|
||||
@ -72,7 +73,7 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
||||
!systemFeatures.branding.enabled,
|
||||
)
|
||||
|
||||
const userProfile = useMemo<UserProfileResponse>(() => userProfileResp?.profile || userProfilePlaceholder, [userProfileResp?.profile])
|
||||
const userProfile = useMemo<GetAccountProfileResponse>(() => userProfileResp?.profile || userProfilePlaceholder, [userProfileResp?.profile])
|
||||
const currentWorkspace = useMemo<ICurrentWorkspace>(() => normalizeCurrentWorkspace(currentWorkspaceResp), [currentWorkspaceResp])
|
||||
const langGeniusVersionInfo = useMemo<LangGeniusVersionResponse>(() => {
|
||||
if (!userProfileResp?.meta?.currentVersion || !langGeniusVersionQuery.data)
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
'use client'
|
||||
|
||||
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
|
||||
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
||||
import type { ICurrentWorkspace, LangGeniusVersionResponse } from '@/models/common'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { createContext, useContext, useContextSelector } from 'use-context-selector'
|
||||
|
||||
export type AppContextValue = {
|
||||
userProfile: UserProfileResponse
|
||||
userProfile: GetAccountProfileResponse
|
||||
mutateUserProfile: VoidFunction
|
||||
currentWorkspace: ICurrentWorkspace
|
||||
isCurrentWorkspaceManager: boolean
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
import { type } from '@orpc/contract'
|
||||
import { base } from '../base'
|
||||
|
||||
export type AccountProfileResponse = {
|
||||
id: string
|
||||
name: string
|
||||
email: string
|
||||
avatar: string
|
||||
avatar_url: string | null
|
||||
is_password_set: boolean
|
||||
interface_language?: string
|
||||
interface_theme?: string
|
||||
timezone?: string
|
||||
last_login_at?: string
|
||||
last_active_at?: string
|
||||
last_login_ip?: string
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
export const accountProfileContract = base
|
||||
.route({
|
||||
path: '/account/profile',
|
||||
method: 'GET',
|
||||
})
|
||||
.output(type<AccountProfileResponse>())
|
||||
|
||||
export const accountAvatarContract = base
|
||||
.route({
|
||||
path: '/account/avatar',
|
||||
method: 'GET',
|
||||
})
|
||||
.input(type<{
|
||||
query: {
|
||||
avatar: string
|
||||
}
|
||||
}>())
|
||||
.output(type<{ avatar_url: string }>())
|
||||
@ -1,7 +1,6 @@
|
||||
import type { InferContractRouterInputs } from '@orpc/contract'
|
||||
import { contract as communityContract } from '@dify/contracts/api/console/orpc.gen'
|
||||
import { contract as enterpriseContract } from '@dify/contracts/enterprise/orpc.gen'
|
||||
import { accountAvatarContract, accountProfileContract } from './console/account'
|
||||
import { appDeleteContract, appListContract, workflowOnlineUsersContract } from './console/apps'
|
||||
import { bindPartnerStackContract, invoicesContract } from './console/billing'
|
||||
import {
|
||||
@ -71,14 +70,6 @@ export type MarketPlaceInputs = InferContractRouterInputs<typeof marketplaceRout
|
||||
export const consoleRouterContract = {
|
||||
enterprise: enterpriseContract,
|
||||
...communityContract,
|
||||
account: {
|
||||
...communityContract.account,
|
||||
avatar: accountAvatarContract,
|
||||
profile: {
|
||||
...communityContract.account.profile,
|
||||
get: accountProfileContract,
|
||||
},
|
||||
},
|
||||
apps: {
|
||||
...communityContract.apps,
|
||||
list: appListContract,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { AccountProfileResponse } from '@/contract/console/account'
|
||||
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
||||
import { QueryClient } from '@tanstack/react-query'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { resolveServerConsoleApiUrl } from '@/service/server'
|
||||
@ -18,7 +18,7 @@ vi.mock('@/next/headers', () => ({
|
||||
cookies: () => cookiesMock(),
|
||||
}))
|
||||
|
||||
const createProfile = (overrides: Partial<AccountProfileResponse> = {}): AccountProfileResponse => ({
|
||||
const createProfile = (overrides: Partial<GetAccountProfileResponse> = {}): GetAccountProfileResponse => ({
|
||||
id: 'account-id',
|
||||
name: 'Dify User',
|
||||
email: 'user@example.com',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { AccountProfileResponse } from '@/contract/console/account'
|
||||
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
||||
import { queryOptions } from '@tanstack/react-query'
|
||||
import { IS_DEV } from '@/config'
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
@ -6,7 +6,7 @@ import { get } from '@/service/base'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
|
||||
export type UserProfileWithMeta = {
|
||||
profile: AccountProfileResponse
|
||||
profile: GetAccountProfileResponse
|
||||
meta: {
|
||||
currentVersion: string | null
|
||||
currentEnv: string | null
|
||||
@ -24,7 +24,7 @@ export const userProfileQueryOptions = () =>
|
||||
needAllResponseContent: true,
|
||||
silent: true,
|
||||
})
|
||||
const profile: AccountProfileResponse = await response.clone().json()
|
||||
const profile: GetAccountProfileResponse = await response.clone().json()
|
||||
return {
|
||||
profile,
|
||||
meta: {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
||||
import type { UserProfileWithMeta } from './client'
|
||||
import type { AccountProfileResponse } from '@/contract/console/account'
|
||||
import { queryOptions } from '@tanstack/react-query'
|
||||
import { getServerConsoleRequestHeaders, resolveServerConsoleApiUrl, serverConsoleQuery } from '@/service/server'
|
||||
|
||||
@ -22,7 +22,7 @@ export const serverUserProfileQueryOptions = () =>
|
||||
if (!response.ok)
|
||||
throw response
|
||||
|
||||
const profile: AccountProfileResponse = await response.clone().json()
|
||||
const profile: GetAccountProfileResponse = await response.clone().json()
|
||||
return {
|
||||
profile,
|
||||
meta: {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { renderHook } from '@testing-library/react'
|
||||
import { createAccountProfileQueryWrapper } from '@/test/account-profile-query'
|
||||
import useTimestamp from './use-timestamp'
|
||||
|
||||
vi.mock('@/context/app-context', () => ({
|
||||
@ -23,7 +24,7 @@ vi.mock('@/context/app-context', () => ({
|
||||
describe('useTimestamp', () => {
|
||||
describe('formatTime', () => {
|
||||
it('should format unix timestamp correctly', () => {
|
||||
const { result } = renderHook(() => useTimestamp())
|
||||
const { result } = renderHook(() => useTimestamp(), { wrapper: createAccountProfileQueryWrapper() })
|
||||
const timestamp = 1704132000
|
||||
|
||||
expect(result.current.formatTime(timestamp, 'YYYY-MM-DD HH:mm:ss'))
|
||||
@ -31,7 +32,7 @@ describe('useTimestamp', () => {
|
||||
})
|
||||
|
||||
it('should format with different patterns', () => {
|
||||
const { result } = renderHook(() => useTimestamp())
|
||||
const { result } = renderHook(() => useTimestamp(), { wrapper: createAccountProfileQueryWrapper() })
|
||||
const timestamp = 1704132000
|
||||
|
||||
expect(result.current.formatTime(timestamp, 'MM/DD/YYYY'))
|
||||
@ -44,7 +45,7 @@ describe('useTimestamp', () => {
|
||||
|
||||
describe('formatDate', () => {
|
||||
it('should format date string correctly', () => {
|
||||
const { result } = renderHook(() => useTimestamp())
|
||||
const { result } = renderHook(() => useTimestamp(), { wrapper: createAccountProfileQueryWrapper() })
|
||||
const dateString = '2024-01-01T12:00:00Z'
|
||||
|
||||
expect(result.current.formatDate(dateString, 'YYYY-MM-DD HH:mm:ss'))
|
||||
@ -52,7 +53,7 @@ describe('useTimestamp', () => {
|
||||
})
|
||||
|
||||
it('should format with different patterns', () => {
|
||||
const { result } = renderHook(() => useTimestamp())
|
||||
const { result } = renderHook(() => useTimestamp(), { wrapper: createAccountProfileQueryWrapper() })
|
||||
const dateString = '2024-01-01T12:00:00Z'
|
||||
|
||||
expect(result.current.formatDate(dateString, 'MM/DD/YYYY'))
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
'use client'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import dayjs from 'dayjs'
|
||||
import timezone from 'dayjs/plugin/timezone'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
import { useCallback } from 'react'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
|
||||
const useTimestamp = () => {
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
const { data: timezone } = useQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: data => data.profile.timezone ?? undefined,
|
||||
})
|
||||
|
||||
const formatTime = useCallback((value: number, format: string) => {
|
||||
return dayjs.unix(value).tz(timezone).format(format)
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
||||
import type { I18nText } from '@/i18n-config/language'
|
||||
import type { Model } from '@/types/app'
|
||||
|
||||
@ -18,24 +19,8 @@ export type InitValidateStatusResponse = {
|
||||
status: 'finished' | 'not_started'
|
||||
}
|
||||
|
||||
export type UserProfileResponse = {
|
||||
id: string
|
||||
name: string
|
||||
email: string
|
||||
avatar: string
|
||||
avatar_url: string | null
|
||||
is_password_set: boolean
|
||||
interface_language?: string
|
||||
interface_theme?: string
|
||||
timezone?: string
|
||||
last_login_at?: string
|
||||
last_active_at?: string
|
||||
last_login_ip?: string
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
export type UserProfileOriginResponse = {
|
||||
json: () => Promise<UserProfileResponse>
|
||||
json: () => Promise<GetAccountProfileResponse>
|
||||
bodyUsed: boolean
|
||||
headers: any
|
||||
}
|
||||
@ -50,8 +35,11 @@ export type LangGeniusVersionResponse = {
|
||||
current_env: string
|
||||
}
|
||||
|
||||
export type Member = Pick<UserProfileResponse, 'id' | 'name' | 'email' | 'last_login_at' | 'last_active_at' | 'created_at' | 'avatar_url'> & {
|
||||
export type Member = Pick<GetAccountProfileResponse, 'id' | 'name' | 'email' | 'avatar_url'> & {
|
||||
avatar: string
|
||||
last_login_at?: string
|
||||
last_active_at?: string
|
||||
created_at?: string
|
||||
status: 'pending' | 'active' | 'banned' | 'closed'
|
||||
role: 'owner' | 'admin' | 'editor' | 'normal' | 'dataset_operator'
|
||||
}
|
||||
|
||||
@ -371,5 +371,5 @@ export const checkEmailExisted = (body: { email: string }): Promise<CommonRespon
|
||||
|
||||
export const getAvatar = async ({ avatar }: { avatar: string }): Promise<{ avatar_url: string }> => {
|
||||
const { consoleClient } = await import('./client')
|
||||
return consoleClient.account.avatar({ query: { avatar } })
|
||||
return consoleClient.account.avatar.get({ query: { avatar } })
|
||||
}
|
||||
|
||||
70
web/test/account-profile-query.ts
Normal file
70
web/test/account-profile-query.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
|
||||
import type { QueryClient } from '@tanstack/react-query'
|
||||
import type { ReactNode } from 'react'
|
||||
import type { UserProfileWithMeta } from '@/features/account-profile/client'
|
||||
import { QueryClientProvider, QueryClient as TanStackQueryClient } from '@tanstack/react-query'
|
||||
import { createElement } from 'react'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
|
||||
const createMockAccountProfile = (
|
||||
overrides: Partial<GetAccountProfileResponse> = {},
|
||||
): GetAccountProfileResponse => ({
|
||||
id: 'user-1',
|
||||
name: 'Test User',
|
||||
email: 'test@dify.ai',
|
||||
avatar: '',
|
||||
avatar_url: null,
|
||||
is_password_set: false,
|
||||
timezone: 'Asia/Shanghai',
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const createMockUserProfileResponse = (
|
||||
profile: Partial<GetAccountProfileResponse> = {},
|
||||
): UserProfileWithMeta => ({
|
||||
profile: createMockAccountProfile(profile),
|
||||
meta: {
|
||||
currentVersion: null,
|
||||
currentEnv: null,
|
||||
},
|
||||
})
|
||||
|
||||
export const createAccountProfileQueryClient = (
|
||||
profile: Partial<GetAccountProfileResponse> = {},
|
||||
) => {
|
||||
const queryClient = new TanStackQueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: false,
|
||||
staleTime: Number.POSITIVE_INFINITY,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
queryClient.setQueryData(
|
||||
userProfileQueryOptions().queryKey,
|
||||
createMockUserProfileResponse(profile),
|
||||
)
|
||||
|
||||
return queryClient
|
||||
}
|
||||
|
||||
export const createAccountProfileQueryWrapper = (
|
||||
profile: Partial<GetAccountProfileResponse> = {},
|
||||
) => {
|
||||
const queryClient = createAccountProfileQueryClient(profile)
|
||||
|
||||
return function AccountProfileQueryWrapper({ children }: { children: ReactNode }) {
|
||||
return createElement(QueryClientProvider, { client: queryClient }, children)
|
||||
}
|
||||
}
|
||||
|
||||
export function AccountProfileQueryProvider({
|
||||
children,
|
||||
queryClient,
|
||||
}: {
|
||||
children: ReactNode
|
||||
queryClient: QueryClient
|
||||
}) {
|
||||
return createElement(QueryClientProvider, { client: queryClient }, children)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user