diff --git a/web/app/(humanInputLayout)/form/[token]/form.tsx b/web/app/(humanInputLayout)/form/[token]/form.tsx new file mode 100644 index 0000000000..55292af07f --- /dev/null +++ b/web/app/(humanInputLayout)/form/[token]/form.tsx @@ -0,0 +1,166 @@ +'use client' +import React from 'react' +import { useTranslation } from 'react-i18next' +import useDocumentTitle from '@/hooks/use-document-title' +import { useParams } from 'next/navigation' +import { + RiCheckboxCircleFill, + RiInformation2Fill, +} from '@remixicon/react' +import AppIcon from '@/app/components/base/app-icon' +import { Markdown } from '@/app/components/base/markdown' +import Button, { } from '@/app/components/base/button' +import DifyLogo from '@/app/components/base/logo/dify-logo' +import { UserActionButtonType } from '@/app/components/workflow/nodes/human-input/types' + +import cn from '@/utils/classnames' + +import { MOCK_DATA } from './mock' + +const success = true + +const expired = true + +const submitted = true + +const FormContent = () => { + const { t } = useTranslation() + + const { token } = useParams() + useDocumentTitle('') + + const { site } = MOCK_DATA.site + const { form_content, user_actions, timeout, timeout_unit } = MOCK_DATA + + const getButtonStyle = (style: UserActionButtonType) => { + if (style === UserActionButtonType.Primary) + return 'primary' + if (style === UserActionButtonType.Default) + return 'secondary' + if (style === UserActionButtonType.Accent) + return 'secondary-accent' + if (style === UserActionButtonType.Ghost) + return 'ghost' + } + + if (success) { + return ( +
+
+
+
+ +
+
+
{t('share.humanInput.thanks')}
+
{t('share.humanInput.recorded')}
+
+
{t('share.humanInput.submissionID', { id: token })}
+
+
+
+
{t('share.chat.poweredBy')}
+ +
+
+
+
+ ) + } + + if (expired) { + return ( +
+
+
+
+ +
+
+
{t('share.humanInput.sorry')}
+
{t('share.humanInput.expired')}
+
+
{t('share.humanInput.submissionID', { id: token })}
+
+
+
+
{t('share.chat.poweredBy')}
+ +
+
+
+
+ ) + } + + if (submitted) { + return ( +
+
+
+
+ +
+
+
{t('share.humanInput.sorry')}
+
{t('share.humanInput.completed')}
+
+
{t('share.humanInput.submissionID', { id: token })}
+
+
+
+
{t('share.chat.poweredBy')}
+ +
+
+
+
+ ) + } + + return ( +
+
+ +
{site.title}
+
+
+
+ +
+ {user_actions.map((action: any) => ( + + ))} +
+
+ {timeout_unit === 'day' ? t('share.humanInput.timeoutDay', { count: timeout }) : t('share.humanInput.timeoutHour', { count: timeout })} +
+
+
+
+
{t('share.chat.poweredBy')}
+ +
+
+
+
+ ) +} + +export default React.memo(FormContent) diff --git a/web/app/(humanInputLayout)/form/[token]/mock.ts b/web/app/(humanInputLayout)/form/[token]/mock.ts new file mode 100644 index 0000000000..e1fb770d3e --- /dev/null +++ b/web/app/(humanInputLayout)/form/[token]/mock.ts @@ -0,0 +1,81 @@ +import { UserActionButtonType } from '@/app/components/workflow/nodes/human-input/types' + +export const MOCK_DATA = { + site: { + app_id: 'e9823576-d836-4f2b-b46f-bd4df1d82230', + end_user_id: 'b7aa295d-1560-4d87-a828-77b3f39b30d0', + enable_site: true, + site: { + title: 'wf', + chat_color_theme: null, + chat_color_theme_inverted: false, + icon_type: 'emoji', + icon: '\uD83E\uDD16', + icon_background: '#FFEAD5', + icon_url: null, + description: null, + copyright: null, + privacy_policy: null, + custom_disclaimer: '', + default_language: 'en-US', + prompt_public: false, + show_workflow_steps: true, + use_icon_as_answer_icon: false, + }, + model_config: null, + plan: 'basic', + can_replace_logo: false, + custom_config: null, + }, + // 采用与上方 form editor 相同的数据结构,唯一不同的就是 + // 对于 Text 类型,其文本已完成了变量替换(即,所有使用 + // {{#node_name.var_name#}} 格式引用其他变量的位置,都 + // 被替换成了对应的变量的值) + // + // 参考 FormContent + form_content: ` + # Experiencing the Four Seasons + ![Four seasons landscape]({{#nodename.image#}}) + + ## My Seasonal Guide + Name: {{#noddename.name#}} + Location: {{#nodename.location#}} + Favorite Season: {{#nodename.season#}} + + The four seasons throughout the year: + - Spring: Cherry blossoms, returning birds + - Summer: Long sunny days, thunderstorms, beach adventures + - Autumn: Red and gold foliage, harvest festivals, apple picking + - Winter: Snowfall, frozen lakes, holiday celebrations + ## Notes + + {{#$output.content#}} + `, + // 对每一个字段的描述,参考上方 FormInput 的定义。 + inputs: [''], + // 用户对这个表单可采取的操作,参考上方 UserAction 的定义。 + user_actions: [ + { + id: 'approve-action', + title: 'Post to X', + button_style: UserActionButtonType.Primary, + }, + { + id: 'regenerate-action', + title: 'regenerate', + button_style: UserActionButtonType.Default, + }, + { + id: 'thinking-action', + title: 'thinking', + button_style: UserActionButtonType.Accent, + }, + { + id: 'cancel-action', + title: 'cancel', + button_style: UserActionButtonType.Ghost, + }, + ], + timeout: 3, + timeout_unit: 'day', +} diff --git a/web/app/(humanInputLayout)/form/[token]/page.tsx b/web/app/(humanInputLayout)/form/[token]/page.tsx new file mode 100644 index 0000000000..8f736df638 --- /dev/null +++ b/web/app/(humanInputLayout)/form/[token]/page.tsx @@ -0,0 +1,13 @@ +'use client' +import React from 'react' +import FormContent from './form' + +const FormPage = () => { + return ( +
+ +
+ ) +} + +export default React.memo(FormPage) diff --git a/web/i18n/en-US/share.ts b/web/i18n/en-US/share.ts index ab589ffb76..4934e1a481 100644 --- a/web/i18n/en-US/share.ts +++ b/web/i18n/en-US/share.ts @@ -80,6 +80,16 @@ const translation = { login: { backToHome: 'Back to Home', }, + humanInput: { + timeoutDay: 'This action will expire in {{count}} days.', + timeoutHour: 'This action will expire in {{count}} hours.', + 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. ', + }, } export default translation diff --git a/web/i18n/zh-Hans/share.ts b/web/i18n/zh-Hans/share.ts index ce1270dae8..4df2bde11b 100644 --- a/web/i18n/zh-Hans/share.ts +++ b/web/i18n/zh-Hans/share.ts @@ -76,6 +76,15 @@ const translation = { login: { backToHome: '返回首页', }, + humanInput: { + timeoutDay: '此操作将在 {{count}} 天后过期。', + timeoutHour: '此操作将在 {{count}} 小时后过期。', + thanks: '谢谢!', + sorry: '抱歉!', + recorded: '您的输入已被记录。', + expired: '此请求似乎已过期。', + completed: '此请求似乎在其他地方得到了处理。', + }, } export default translation