+42
![autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>](/assets/img/avatar_default.png)








Saumya Talwani
GitHub
Poojan
sahil-infocusp
非法操作
Pandaaaa906
Asuka Minato
heyszt
autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Ijas
gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
木之本澪
KinomotoMio
不做了睡大觉
User
Copilot
edvatar
-LAN-
Leilei
HaKu
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
wangxiaolei
Varun Chawla
Stephen Zhou
yyh
yyh
tda
root
Sisyphus
Niels Kaspers
hj24
Tyson Cung
Stephen Zhou
FFXN
slegarraga
99
Br1an
L1nSn0w
Yunlu Wen
akkoaya
盐粒 Yanli
lif
weiguang li
Copilot
crazywoola
HanWenbo
Coding On Star
CodingOnStar
Stable Genius
Stable Genius
ふるい
Xiyuan Chen
f50e44b24a
Signed-off-by: edvatar <[email protected]> Signed-off-by: -LAN- <[email protected]> Signed-off-by: dependabot[bot] <[email protected]> Signed-off-by: majiayu000 <[email protected]> Co-authored-by: Poojan <[email protected]> Co-authored-by: sahil-infocusp <[email protected]> Co-authored-by: 非法操作 <[email protected]> Co-authored-by: Pandaaaa906 <[email protected]> Co-authored-by: Asuka Minato <[email protected]> Co-authored-by: heyszt <[email protected]> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Ijas <[email protected]> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: 木之本澪 <[email protected]> Co-authored-by: KinomotoMio <[email protected]> Co-authored-by: 不做了睡大觉 <[email protected]> Co-authored-by: User <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: edvatar <[email protected]> Co-authored-by: -LAN- <[email protected]> Co-authored-by: Leilei <[email protected]> Co-authored-by: HaKu <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: wangxiaolei <[email protected]> Co-authored-by: Varun Chawla <[email protected]> Co-authored-by: Stephen Zhou <[email protected]> Co-authored-by: yyh <[email protected]> Co-authored-by: yyh <[email protected]> Co-authored-by: tda <[email protected]> Co-authored-by: root <root@DESKTOP-KQLO90N> Co-authored-by: Sisyphus <[email protected]> Co-authored-by: Niels Kaspers <[email protected]> Co-authored-by: hj24 <[email protected]> Co-authored-by: Tyson Cung <[email protected]> Co-authored-by: Stephen Zhou <[email protected]> Co-authored-by: FFXN <[email protected]> Co-authored-by: slegarraga <[email protected]> Co-authored-by: 99 <[email protected]> Co-authored-by: Br1an <[email protected]> Co-authored-by: L1nSn0w <[email protected]> Co-authored-by: Yunlu Wen <[email protected]> Co-authored-by: akkoaya <[email protected]> Co-authored-by: 盐粒 Yanli <[email protected]> Co-authored-by: lif <[email protected]> Co-authored-by: weiguang li <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: crazywoola <[email protected]> Co-authored-by: HanWenbo <[email protected]> Co-authored-by: Coding On Star <[email protected]> Co-authored-by: CodingOnStar <[email protected]> Co-authored-by: Stable Genius <[email protected]> Co-authored-by: Stable Genius <[email protected]> Co-authored-by: ふるい <[email protected]> Co-authored-by: Xiyuan Chen <[email protected]>
277 lines
9.1 KiB
TypeScript
277 lines
9.1 KiB
TypeScript
import * as React from 'react'
|
|
import { useEffect, useState } from 'react'
|
|
import Button from '@/app/components/base/button'
|
|
import { useChatContext } from '@/app/components/base/chat/chat/context'
|
|
import Checkbox from '@/app/components/base/checkbox'
|
|
import DatePicker from '@/app/components/base/date-and-time-picker/date-picker'
|
|
import TimePicker from '@/app/components/base/date-and-time-picker/time-picker'
|
|
import { formatDateForOutput } from '@/app/components/base/date-and-time-picker/utils/dayjs'
|
|
import Input from '@/app/components/base/input'
|
|
import Select from '@/app/components/base/select'
|
|
import Textarea from '@/app/components/base/textarea'
|
|
|
|
enum DATA_FORMAT {
|
|
TEXT = 'text',
|
|
JSON = 'json',
|
|
}
|
|
enum SUPPORTED_TAGS {
|
|
LABEL = 'label',
|
|
INPUT = 'input',
|
|
TEXTAREA = 'textarea',
|
|
BUTTON = 'button',
|
|
}
|
|
enum SUPPORTED_TYPES {
|
|
TEXT = 'text',
|
|
PASSWORD = 'password',
|
|
EMAIL = 'email',
|
|
NUMBER = 'number',
|
|
DATE = 'date',
|
|
TIME = 'time',
|
|
DATETIME = 'datetime',
|
|
CHECKBOX = 'checkbox',
|
|
SELECT = 'select',
|
|
HIDDEN = 'hidden',
|
|
}
|
|
const MarkdownForm = ({ node }: any) => {
|
|
const { onSend } = useChatContext()
|
|
|
|
const [formValues, setFormValues] = useState<{ [key: string]: any }>({})
|
|
|
|
useEffect(() => {
|
|
const initialValues: { [key: string]: any } = {}
|
|
node.children.forEach((child: any) => {
|
|
if ([SUPPORTED_TAGS.INPUT, SUPPORTED_TAGS.TEXTAREA].includes(child.tagName)) {
|
|
initialValues[child.properties.name]
|
|
= (child.tagName === SUPPORTED_TAGS.INPUT && child.properties.type === SUPPORTED_TYPES.HIDDEN)
|
|
? (child.properties.value || '')
|
|
: child.properties.value
|
|
}
|
|
})
|
|
setFormValues(initialValues)
|
|
}, [node.children])
|
|
|
|
const getFormValues = (children: any) => {
|
|
const values: { [key: string]: any } = {}
|
|
children.forEach((child: any) => {
|
|
if ([SUPPORTED_TAGS.INPUT, SUPPORTED_TAGS.TEXTAREA].includes(child.tagName)) {
|
|
let value = formValues[child.properties.name]
|
|
|
|
if (child.tagName === SUPPORTED_TAGS.INPUT
|
|
&& (child.properties.type === SUPPORTED_TYPES.DATE || child.properties.type === SUPPORTED_TYPES.DATETIME)) {
|
|
if (value && typeof value.format === 'function') {
|
|
// Format date output consistently
|
|
const includeTime = child.properties.type === SUPPORTED_TYPES.DATETIME
|
|
value = formatDateForOutput(value, includeTime)
|
|
}
|
|
}
|
|
|
|
values[child.properties.name] = value
|
|
}
|
|
})
|
|
return values
|
|
}
|
|
|
|
const onSubmit = (e: any) => {
|
|
e.preventDefault()
|
|
const format = node.properties.dataFormat || DATA_FORMAT.TEXT
|
|
const result = getFormValues(node.children)
|
|
|
|
if (format === DATA_FORMAT.JSON) {
|
|
onSend?.(JSON.stringify(result))
|
|
}
|
|
else {
|
|
const textResult = Object.entries(result)
|
|
.map(([key, value]) => `${key}: ${value}`)
|
|
.join('\n')
|
|
onSend?.(textResult)
|
|
}
|
|
}
|
|
return (
|
|
<form
|
|
autoComplete="off"
|
|
className="flex flex-col self-stretch"
|
|
data-testid="markdown-form"
|
|
onSubmit={(e: any) => {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
}}
|
|
>
|
|
{node.children.filter((i: any) => i.type === 'element').map((child: any, index: number) => {
|
|
if (child.tagName === SUPPORTED_TAGS.LABEL) {
|
|
return (
|
|
<label
|
|
key={index}
|
|
htmlFor={child.properties.htmlFor || child.properties.name}
|
|
className="my-2 text-text-secondary system-md-semibold"
|
|
data-testid="label-field"
|
|
>
|
|
{child.children[0]?.value || ''}
|
|
</label>
|
|
)
|
|
}
|
|
if (child.tagName === SUPPORTED_TAGS.INPUT && Object.values(SUPPORTED_TYPES).includes(child.properties.type)) {
|
|
if (child.properties.type === SUPPORTED_TYPES.DATE || child.properties.type === SUPPORTED_TYPES.DATETIME) {
|
|
return (
|
|
<DatePicker
|
|
key={index}
|
|
value={formValues[child.properties.name]}
|
|
needTimePicker={child.properties.type === SUPPORTED_TYPES.DATETIME}
|
|
onChange={(date) => {
|
|
setFormValues(prevValues => ({
|
|
...prevValues,
|
|
[child.properties.name]: date,
|
|
}))
|
|
}}
|
|
onClear={() => {
|
|
setFormValues(prevValues => ({
|
|
...prevValues,
|
|
[child.properties.name]: undefined,
|
|
}))
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
if (child.properties.type === SUPPORTED_TYPES.TIME) {
|
|
return (
|
|
<TimePicker
|
|
key={index}
|
|
value={formValues[child.properties.name]}
|
|
onChange={(time) => {
|
|
setFormValues(prevValues => ({
|
|
...prevValues,
|
|
[child.properties.name]: time,
|
|
}))
|
|
}}
|
|
onClear={() => {
|
|
setFormValues(prevValues => ({
|
|
...prevValues,
|
|
[child.properties.name]: undefined,
|
|
}))
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
if (child.properties.type === SUPPORTED_TYPES.CHECKBOX) {
|
|
return (
|
|
<div className="mt-2 flex h-6 items-center space-x-2" key={index}>
|
|
<Checkbox
|
|
key={index}
|
|
checked={formValues[child.properties.name]}
|
|
onCheck={() => {
|
|
setFormValues(prevValues => ({
|
|
...prevValues,
|
|
[child.properties.name]: !prevValues[child.properties.name],
|
|
}))
|
|
}}
|
|
id={child.properties.name}
|
|
/>
|
|
<span>{child.properties.dataTip || child.properties['data-tip'] || ''}</span>
|
|
</div>
|
|
)
|
|
}
|
|
if (child.properties.type === SUPPORTED_TYPES.SELECT) {
|
|
return (
|
|
<Select
|
|
key={index}
|
|
allowSearch={false}
|
|
className="w-full"
|
|
items={(() => {
|
|
let options = child.properties.dataOptions || child.properties['data-options'] || []
|
|
if (typeof options === 'string') {
|
|
try {
|
|
options = JSON.parse(options)
|
|
}
|
|
catch (e) {
|
|
console.error('Failed to parse options:', e)
|
|
options = []
|
|
}
|
|
}
|
|
return options.map((option: string) => ({
|
|
name: option,
|
|
value: option,
|
|
}))
|
|
})()}
|
|
defaultValue={formValues[child.properties.name]}
|
|
onSelect={(item) => {
|
|
setFormValues(prevValues => ({
|
|
...prevValues,
|
|
[child.properties.name]: item.value,
|
|
}))
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
|
|
if (child.properties.type === SUPPORTED_TYPES.HIDDEN) {
|
|
return (
|
|
<input
|
|
key={index}
|
|
type="hidden"
|
|
name={child.properties.name}
|
|
value={formValues[child.properties.name] || child.properties.value || ''}
|
|
/>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<Input
|
|
key={index}
|
|
type={child.properties.type}
|
|
name={child.properties.name}
|
|
placeholder={child.properties.placeholder}
|
|
value={formValues[child.properties.name]}
|
|
onChange={(e) => {
|
|
setFormValues(prevValues => ({
|
|
...prevValues,
|
|
[child.properties.name]: e.target.value,
|
|
}))
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
if (child.tagName === SUPPORTED_TAGS.TEXTAREA) {
|
|
return (
|
|
<Textarea
|
|
key={index}
|
|
name={child.properties.name}
|
|
placeholder={child.properties.placeholder}
|
|
value={formValues[child.properties.name]}
|
|
onChange={(e) => {
|
|
setFormValues(prevValues => ({
|
|
...prevValues,
|
|
[child.properties.name]: e.target.value,
|
|
}))
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
if (child.tagName === SUPPORTED_TAGS.BUTTON) {
|
|
const variant = child.properties.dataVariant
|
|
const size = child.properties.dataSize
|
|
|
|
return (
|
|
<Button
|
|
variant={variant}
|
|
size={size}
|
|
className="mt-4"
|
|
key={index}
|
|
onClick={onSubmit}
|
|
>
|
|
<span className="text-[13px]">{child.children[0]?.value || ''}</span>
|
|
</Button>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<p key={index}>
|
|
Unsupported tag:
|
|
{child.tagName}
|
|
</p>
|
|
)
|
|
})}
|
|
</form>
|
|
)
|
|
}
|
|
MarkdownForm.displayName = 'MarkdownForm'
|
|
export default MarkdownForm
|