feat: preveiw wrap

This commit is contained in:
Joel 2025-08-29 16:21:39 +08:00
parent 4d4c8b21ac
commit ec07636ce9
2 changed files with 74 additions and 2 deletions

View File

@ -0,0 +1,57 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import type { FormInputItem, UserAction } from '../types'
import { useStore } from '@/app/components/workflow/store'
import { Markdown } from '@/app/components/base/markdown'
import { getButtonStyle } from '@/app/components/base/chat/chat/answer/human-input-content/utils'
import Button from '@/app/components/base/button'
import Badge from '@/app/components/base/badge'
import { useTranslation } from 'react-i18next'
import ActionButton from '@/app/components/base/action-button'
import { RiCloseLine } from '@remixicon/react'
const i18nPrefix = 'workflow.nodes.humanInput'
type Props = {
content: string
formInputs: FormInputItem[]
userActions: UserAction[]
onClose: () => void
}
const FormContentPreview: FC<Props> = ({
content,
formInputs,
userActions,
onClose,
}) => {
const { t } = useTranslation()
const panelWidth = useStore(state => state.panelWidth)
return (
<div className='fixed top-[112px] z-10 max-h-[calc(100vh-116px)] w-[600px] rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg py-3 shadow-xl' style={{
right: panelWidth + 8,
}}>
<div className='flex h-[26px] items-center justify-between px-4'>
<Badge uppercase className='border-text-accent-secondary text-text-accent-secondary'>{t(`${i18nPrefix}.formContent.preview`)}</Badge>
<ActionButton onClick={onClose}><RiCloseLine className='w-5 text-text-tertiary' /></ActionButton>
</div>
<div className='max-h-[calc(100vh-167px)] overflow-y-auto px-4'>
<Markdown content={content} />
<div className='mt-3 flex flex-wrap gap-1 py-1'>
{userActions.map((action: any) => (
<Button
key={action.id}
variant={getButtonStyle(action.button_style) as any}
>
{action.title}
</Button>
))}
</div>
<div className='system-xs-regular mt-1 px-4 text-text-tertiary'>In preview mode, action buttons are not functional.</div>
</div>
</div>
)
}
export default React.memo(FormContentPreview)

View File

@ -29,6 +29,7 @@ import copy from 'copy-to-clipboard'
import { useBoolean } from 'ahooks'
import cn from '@/utils/classnames'
import { useStore } from '@/app/components/workflow/store'
import FormContentPreview from './components/form-content-preview'
const i18nPrefix = 'workflow.nodes.humanInput'
@ -63,6 +64,11 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
}] = useBoolean(false)
const panelWidth = useStore(state => state.panelWidth)
const [isPreview, {
toggle: togglePreview,
setFalse: hidePreview,
}] = useBoolean(false)
return (
<div className='py-2'>
{/* delivery methods */}
@ -76,7 +82,7 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
<Divider className='!my-0 !h-px !bg-divider-subtle' />
</div>
{/* form content */}
<div className={cn('px-4 py-2', isExpandFormContent && 'fixed bottom-[8px] right-[4px] top-[189px] z-10 flex flex-col bg-components-panel-bg')} style={{ width: panelWidth }}>
<div className={cn('px-4 py-2', isExpandFormContent && 'fixed bottom-[8px] right-[4px] top-[189px] z-10 flex flex-col bg-components-panel-bg')} style={{ width: isExpandFormContent ? panelWidth : '100%' }}>
<div className='mb-1 flex shrink-0 items-center justify-between'>
<div className='flex h-6 items-center gap-0.5'>
<div className='system-sm-semibold-uppercase text-text-secondary'>{t(`${i18nPrefix}.formContent.title`)}</div>
@ -85,7 +91,7 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
/>
</div>
<div className='flex items-center '>
<Button variant='ghost' className='flex items-center space-x-1 px-2 text-components-button-ghost-text'>
<Button variant='ghost' className='flex items-center space-x-1 px-2 text-components-button-ghost-text' onClick={togglePreview}>
<RiEyeLine className='size-3.5' />
<div className='system-xs-medium'>{t(`${i18nPrefix}.formContent.preview`)}</div>
</Button>
@ -167,6 +173,15 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
onChange={handleTimeoutChange}
/>
</div>
{isPreview && (
<FormContentPreview
content={inputs.form_content}
formInputs={inputs.inputs}
userActions={inputs.user_actions}
onClose={hidePreview}
/>
)}
</div>
)
}