mirror of https://github.com/langgenius/dify.git
feat: replace timeout handling with expiration time in HumanInput form and add ExpirationTime component
This commit is contained in:
parent
be0f493e61
commit
e744d4de80
|
|
@ -11,6 +11,7 @@ import { useTranslation } from 'react-i18next'
|
|||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import Button from '@/app/components/base/button'
|
||||
import ContentItem from '@/app/components/base/chat/chat/answer/human-input-content/content-item'
|
||||
import ExpirationTime from '@/app/components/base/chat/chat/answer/human-input-content/expiration-time'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import { UserActionButtonType } from '@/app/components/workflow/nodes/human-input/types'
|
||||
|
|
@ -24,8 +25,7 @@ export type FormData = {
|
|||
form_content: string
|
||||
inputs: FormInputItem[]
|
||||
user_actions: UserAction[]
|
||||
timeout: number
|
||||
timeout_unit: 'hour' | 'day'
|
||||
expiration_time: number
|
||||
}
|
||||
|
||||
const FormContent = () => {
|
||||
|
|
@ -249,9 +249,7 @@ const FormContent = () => {
|
|||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div className="system-xs-regular mt-1 text-text-tertiary">
|
||||
{formData.timeout_unit === 'day' ? t('share.humanInput.timeoutDay', { count: formData.timeout }) : t('share.humanInput.timeoutHour', { count: formData.timeout })}
|
||||
</div>
|
||||
<ExpirationTime expirationTime={formData.expiration_time} />
|
||||
</div>
|
||||
<div className="flex flex-row-reverse px-2 py-3">
|
||||
<div className={cn(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
'use client'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useI18N } from '@/context/i18n'
|
||||
import { formatRelativeTimeInZone } from './utils'
|
||||
|
||||
type ExpirationTimeProps = {
|
||||
expirationTime: number
|
||||
}
|
||||
|
||||
const ExpirationTime = ({
|
||||
expirationTime,
|
||||
}: ExpirationTimeProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { locale } = useI18N()
|
||||
const relativeTime = formatRelativeTimeInZone(expirationTime, locale)
|
||||
|
||||
return (
|
||||
<div className="system-xs-regular mt-1 text-text-tertiary">
|
||||
{t('share.humanInput.expirationTime', { relativeTime })}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ExpirationTime
|
||||
|
|
@ -2,20 +2,17 @@
|
|||
import type { HumanInputFormProps } from './type'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import ContentItem from './content-item'
|
||||
import ExpirationTime from './expiration-time'
|
||||
import { getButtonStyle, initializeInputs, splitByOutputVar } from './utils'
|
||||
|
||||
const HumanInputForm = ({
|
||||
formData,
|
||||
showTimeout,
|
||||
timeout,
|
||||
timeoutUnit,
|
||||
onSubmit,
|
||||
expirationTime,
|
||||
}: HumanInputFormProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const formID = formData.form_id
|
||||
const defaultInputs = initializeInputs(formData.inputs)
|
||||
const contentList = splitByOutputVar(formData.form_content)
|
||||
|
|
@ -59,10 +56,8 @@ const HumanInputForm = ({
|
|||
</Button>
|
||||
))}
|
||||
</div>
|
||||
{showTimeout && (
|
||||
<div className="system-xs-regular mt-1 text-text-tertiary">
|
||||
{timeoutUnit === 'day' ? t('share.humanInput.timeoutDay', { count: timeout }) : t('share.humanInput.timeoutHour', { count: timeout })}
|
||||
</div>
|
||||
{showTimeout && typeof expirationTime === 'number' && (
|
||||
<ExpirationTime expirationTime={expirationTime} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -12,16 +12,14 @@ export type HumanInputContentProps = {
|
|||
showEmailTip?: boolean
|
||||
showDebugModeTip?: boolean
|
||||
showTimeout?: boolean
|
||||
timeout?: number
|
||||
timeoutUnit?: 'hour' | 'day'
|
||||
expirationTime?: number
|
||||
onSubmit?: (formID: string, data: any) => Promise<void>
|
||||
}
|
||||
|
||||
export type HumanInputFormProps = {
|
||||
formData: HumanInputFormData
|
||||
showTimeout?: boolean
|
||||
timeout?: number
|
||||
timeoutUnit?: 'hour' | 'day'
|
||||
expirationTime?: number
|
||||
onSubmit?: (formID: string, data: any) => Promise<void>
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,15 @@
|
|||
import type { FormInputItem } from '@/app/components/workflow/nodes/human-input/types'
|
||||
import type { Locale } from '@/i18n-config'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
import { UserActionButtonType } from '@/app/components/workflow/nodes/human-input/types'
|
||||
import 'dayjs/locale/en'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import 'dayjs/locale/ja'
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
export const getButtonStyle = (style: UserActionButtonType) => {
|
||||
if (style === UserActionButtonType.Primary)
|
||||
|
|
@ -28,3 +38,21 @@ export const initializeInputs = (formInputs: FormInputItem[]) => {
|
|||
})
|
||||
return initialInputs
|
||||
}
|
||||
|
||||
const localeMap: Record<string, string> = {
|
||||
'en-US': 'en',
|
||||
'zh-Hans': 'zh-cn',
|
||||
'ja-JP': 'ja',
|
||||
}
|
||||
|
||||
export const formatRelativeTimeInZone = (
|
||||
utcTimestamp: string | number,
|
||||
locale: Locale = 'en-US',
|
||||
) => {
|
||||
const dayjsLocale = localeMap[locale] ?? 'en'
|
||||
|
||||
return dayjs
|
||||
.utc(utcTimestamp)
|
||||
.locale(dayjsLocale)
|
||||
.fromNow()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,14 +82,13 @@ const translation = {
|
|||
backToHome: 'Back to Home',
|
||||
},
|
||||
humanInput: {
|
||||
timeoutDay: 'This action will expire in {{count}} days.',
|
||||
timeoutHour: 'This action will expire in {{count}} hours.',
|
||||
expirationTime: 'This action will expire {{relativeTime}}.',
|
||||
submissionID: 'submission_id: {{id}}',
|
||||
thanks: 'Thanks!',
|
||||
sorry: 'Sorry!',
|
||||
recorded: 'Your input has been recorded.',
|
||||
expired: 'Seems like this request has expired. ',
|
||||
completed: 'Seems like this request was dealt with elsewhere. ',
|
||||
expired: 'Seems like this request has expired.',
|
||||
completed: 'Seems like this request was dealt with elsewhere.',
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,14 @@ const translation = {
|
|||
login: {
|
||||
backToHome: 'ホームに戻る',
|
||||
},
|
||||
humanInput: {
|
||||
expirationTime: 'この操作は{{relativeTime}}で期限切れになります。',
|
||||
thanks: 'ありがとうございます!',
|
||||
sorry: '申し訳ありません!',
|
||||
recorded: '入力内容は記録されました。',
|
||||
expired: 'このリクエストは期限切れのようです。',
|
||||
completed: 'このリクエストは他の場所で処理されたようです。',
|
||||
},
|
||||
}
|
||||
|
||||
export default translation
|
||||
|
|
|
|||
|
|
@ -78,8 +78,7 @@ const translation = {
|
|||
backToHome: '返回首页',
|
||||
},
|
||||
humanInput: {
|
||||
timeoutDay: '此操作将在 {{count}} 天后过期。',
|
||||
timeoutHour: '此操作将在 {{count}} 小时后过期。',
|
||||
expirationTime: '此操作将在{{relativeTime}}过期。',
|
||||
thanks: '谢谢!',
|
||||
sorry: '抱歉!',
|
||||
recorded: '您的输入已被记录。',
|
||||
|
|
|
|||
|
|
@ -333,8 +333,7 @@ export const getHumanInputForm = (token: string) => {
|
|||
form_content: string
|
||||
inputs: FormInputItem[]
|
||||
user_actions: UserAction[]
|
||||
timeout: number
|
||||
timeout_unit: 'hour' | 'day'
|
||||
expiration_time: number
|
||||
}>(`/api/form/human_input/${token}`)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue