mirror of
https://github.com/langgenius/dify.git
synced 2026-06-26 14:51:13 +08:00
fix: use timestamp hook
This commit is contained in:
parent
a656e514aa
commit
5bb8658b0d
@ -57,6 +57,9 @@ const ChatWrapper = () => {
|
||||
} = useChatWithHistoryContext()
|
||||
|
||||
const appSourceType = isInstalledApp ? AppSourceType.installedApp : AppSourceType.webApp
|
||||
const timezone = appSourceType === AppSourceType.webApp
|
||||
? Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
: undefined
|
||||
|
||||
// Semantic variable for better code readability
|
||||
const isHistoryConversation = !!currentConversationId
|
||||
@ -91,6 +94,8 @@ const ChatWrapper = () => {
|
||||
taskId => stopChatMessageResponding('', taskId, appSourceType, appId),
|
||||
clearChatList,
|
||||
setClearChatList,
|
||||
undefined,
|
||||
{ timezone },
|
||||
)
|
||||
const inputsFormValue = currentConversationId ? currentConversationInputs : newConversationInputsRef?.current
|
||||
const inputDisabled = useMemo(() => {
|
||||
|
||||
@ -6,6 +6,10 @@ import { useParams, usePathname } from '@/next/navigation'
|
||||
import { sseGet, ssePost } from '@/service/base'
|
||||
import { useChat } from '../hooks'
|
||||
|
||||
const useTimestampMock = vi.hoisted(() =>
|
||||
vi.fn(() => ({ formatTime: vi.fn().mockReturnValue('10:00 AM') })),
|
||||
)
|
||||
|
||||
vi.mock('@/service/base', () => ({
|
||||
sseGet: vi.fn(),
|
||||
ssePost: vi.fn(),
|
||||
@ -31,7 +35,7 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/use-timestamp', () => ({
|
||||
default: () => ({ formatTime: vi.fn().mockReturnValue('10:00 AM') }),
|
||||
default: useTimestampMock,
|
||||
}))
|
||||
|
||||
vi.mock('@/next/navigation', () => ({
|
||||
@ -91,6 +95,21 @@ describe('useChat', () => {
|
||||
expect(result.current.suggestedQuestions).toEqual([])
|
||||
})
|
||||
|
||||
it('should pass timestamp options to timestamp formatter', () => {
|
||||
renderHook(() => useChat(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{ timezone: 'UTC' },
|
||||
))
|
||||
|
||||
expect(useTimestampMock).toHaveBeenCalledWith({ timezone: 'UTC' })
|
||||
})
|
||||
|
||||
it('should initialize with opening statement and suggested questions', () => {
|
||||
const config = {
|
||||
opening_statement: 'Hello {{name}}',
|
||||
|
||||
@ -55,6 +55,10 @@ type SendCallback = {
|
||||
isPublicAPI?: boolean
|
||||
}
|
||||
|
||||
type UseChatOptions = {
|
||||
timezone?: string
|
||||
}
|
||||
|
||||
export const useChat = (
|
||||
config?: ChatConfig,
|
||||
formSettings?: {
|
||||
@ -66,9 +70,10 @@ export const useChat = (
|
||||
clearChatList?: boolean,
|
||||
clearChatListCallback?: (state: boolean) => void,
|
||||
initialConversationId?: string,
|
||||
options: UseChatOptions = {},
|
||||
) => {
|
||||
const { t } = useTranslation()
|
||||
const { formatTime } = useTimestamp()
|
||||
const { formatTime } = useTimestamp({ timezone: options.timezone })
|
||||
const conversationIdRef = useRef(initialConversationId ?? '')
|
||||
const initialConversationIdRef = useRef(initialConversationId ?? '')
|
||||
const hasStopRespondedRef = useRef(false)
|
||||
|
||||
@ -81,6 +81,9 @@ const ChatWrapper = () => {
|
||||
opening_statement: currentConversationItem?.introduction || (config as any).opening_statement,
|
||||
} as ChatConfig
|
||||
}, [appParams, currentConversationItem?.introduction])
|
||||
const timezone = appSourceType === AppSourceType.webApp
|
||||
? Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
: undefined
|
||||
const {
|
||||
chatList,
|
||||
handleSend,
|
||||
@ -98,6 +101,8 @@ const ChatWrapper = () => {
|
||||
taskId => stopChatMessageResponding('', taskId, appSourceType, appId),
|
||||
clearChatList,
|
||||
setClearChatList,
|
||||
undefined,
|
||||
{ timezone },
|
||||
)
|
||||
const inputsFormValue = currentConversationId ? currentConversationInputs : newConversationInputsRef?.current
|
||||
const inputDisabled = useMemo(() => {
|
||||
|
||||
@ -6,14 +6,6 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { createAccountProfileQueryWrapper } from '@/test/account-profile-query'
|
||||
import useTimestamp from './use-timestamp'
|
||||
|
||||
const navigationMocks = vi.hoisted(() => ({
|
||||
pathname: '/apps',
|
||||
}))
|
||||
|
||||
vi.mock('@/next/navigation', () => ({
|
||||
usePathname: () => navigationMocks.pathname,
|
||||
}))
|
||||
|
||||
vi.mock('@/context/app-context', () => ({
|
||||
useAppContext: vi.fn(() => ({
|
||||
userProfile: {
|
||||
@ -50,10 +42,6 @@ const createEmptyQueryWrapper = () => {
|
||||
}
|
||||
|
||||
describe('useTimestamp', () => {
|
||||
beforeEach(() => {
|
||||
navigationMocks.pathname = '/apps'
|
||||
})
|
||||
|
||||
describe('formatTime', () => {
|
||||
it('should format unix timestamp correctly', () => {
|
||||
const { result } = renderHook(() => useTimestamp(), { wrapper: createAccountProfileQueryWrapper() })
|
||||
@ -96,13 +84,12 @@ describe('useTimestamp', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('should not request account profile on public webapp routes', () => {
|
||||
navigationMocks.pathname = '/chatbot/share-token'
|
||||
it('should not request account profile when timezone is provided', () => {
|
||||
const { queryClient, wrapper } = createEmptyQueryWrapper()
|
||||
|
||||
const { result } = renderHook(() => useTimestamp(), { wrapper })
|
||||
const { result } = renderHook(() => useTimestamp({ timezone: 'UTC' }), { wrapper })
|
||||
|
||||
expect(result.current.formatTime(1704132000, 'YYYY')).toBe('2024')
|
||||
expect(result.current.formatTime(1704132000, 'YYYY-MM-DD HH:mm')).toBe('2024-01-01 18:00')
|
||||
expect(queryClient.isFetching({ queryKey: userProfileQueryOptions().queryKey })).toBe(0)
|
||||
expect(queryClient.getQueryState(userProfileQueryOptions().queryKey)?.fetchStatus).toBe('idle')
|
||||
})
|
||||
|
||||
@ -5,31 +5,25 @@ import timezone from 'dayjs/plugin/timezone'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
import { useCallback } from 'react'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { usePathname } from '@/next/navigation'
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
|
||||
const PUBLIC_WEBAPP_ROUTE_SEGMENTS = new Set(['agent', 'chat', 'chatbot', 'completion', 'workflow'])
|
||||
|
||||
const isPublicWebAppPath = (pathname: string | null) => {
|
||||
const segment = pathname?.split('/').find(Boolean)
|
||||
return segment ? PUBLIC_WEBAPP_ROUTE_SEGMENTS.has(segment) : false
|
||||
type UseTimestampOptions = {
|
||||
timezone?: string
|
||||
}
|
||||
|
||||
const getBrowserTimezone = () => {
|
||||
return Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
}
|
||||
|
||||
const useTimestamp = () => {
|
||||
const pathname = usePathname()
|
||||
const shouldUseAccountTimezone = !isPublicWebAppPath(pathname)
|
||||
const useTimestamp = ({ timezone: timezoneOverride }: UseTimestampOptions = {}) => {
|
||||
const { data: accountTimezone } = useQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: data => data.profile.timezone ?? undefined,
|
||||
enabled: shouldUseAccountTimezone,
|
||||
enabled: timezoneOverride === undefined,
|
||||
})
|
||||
const resolvedTimezone = accountTimezone ?? getBrowserTimezone()
|
||||
const resolvedTimezone = timezoneOverride ?? accountTimezone ?? getBrowserTimezone()
|
||||
|
||||
const formatTime = useCallback((value: number, format: string) => {
|
||||
return dayjs.unix(value).tz(resolvedTimezone).format(format)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user