Skip to content

Commit cef60e8

Browse files
committed
feat: update prompt dialog, condition
1 parent acfce79 commit cef60e8

File tree

13 files changed

+204
-86
lines changed

13 files changed

+204
-86
lines changed

client/src/components/forms/condition.tsx

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import {
33
TCompareValue,
44
useCompareValueSchema,
55
} from '@/lib/schema/compare-value'
6+
import { isStringBoolean } from '@/utils'
67
import { zodResolver } from '@hookform/resolvers/zod'
8+
import { useEffect } from 'react'
79
import { useForm } from 'react-hook-form'
810
import { useTranslation } from 'react-i18next'
911
import {
@@ -16,6 +18,7 @@ import {
1618
Input,
1719
Select,
1820
SelectContent,
21+
SelectGroup,
1922
SelectItem,
2023
SelectTrigger,
2124
SelectValue,
@@ -34,15 +37,31 @@ const ConditionForm = ({
3437
}: Props) => {
3538
const schema = useCompareValueSchema()
3639
const form = useForm<TCompareValue>({
37-
defaultValues,
40+
defaultValues: {
41+
operator: defaultValues?.operator || '',
42+
value: defaultValues?.value
43+
? JSON.stringify(defaultValues.value).replace(/"/g, '')
44+
: '',
45+
},
3846
resolver: zodResolver(schema),
3947
})
4048
const { t } = useTranslation(['forms', 'flowDetail'])
4149

50+
const watchOperator = form.watch('operator')
51+
4252
const handleSubmit = form.handleSubmit((data) => {
43-
onSubmit?.(data)
53+
onSubmit?.({
54+
...data,
55+
value: isStringBoolean(data.value) ? JSON.parse(data.value) : data.value,
56+
})
4457
})
4558

59+
useEffect(() => {
60+
if (watchOperator === 'exist' && !form.getValues('value')) {
61+
form.reset({ value: 'true' })
62+
}
63+
}, [watchOperator, form])
64+
4665
return (
4766
<Form {...form}>
4867
<form className='space-y-3' onSubmit={handleSubmit} id={id}>
@@ -56,44 +75,79 @@ const ConditionForm = ({
5675
<Select
5776
onValueChange={field.onChange}
5877
defaultValue={field.value}
78+
value={field.value}
5979
>
6080
<FormControl>
6181
<SelectTrigger>
6282
<SelectValue placeholder={t('operator.placeholder')} />
6383
</SelectTrigger>
6484
</FormControl>
65-
<SelectContent>
66-
{CONDITIONAL_OPERATOR.map((c) => {
67-
return (
68-
<SelectItem key={c} value={c}>
69-
{
70-
// @ts-ignore
71-
t(`flowDetail:compare_types.${c}`)
72-
}
73-
</SelectItem>
74-
)
75-
})}
85+
<SelectContent className='max-h-72'>
86+
<SelectGroup>
87+
{CONDITIONAL_OPERATOR.map((c) => {
88+
return (
89+
<SelectItem key={c} value={c}>
90+
{
91+
// @ts-ignore
92+
t(`flowDetail:compare_types.${c}`)
93+
}
94+
</SelectItem>
95+
)
96+
})}
97+
</SelectGroup>
7698
</SelectContent>
7799
</Select>
78100
<FormMessage />
79101
</FormItem>
80102
)}
81103
/>
82-
<FormField
83-
name='value'
84-
control={form.control}
85-
render={({ field }) => {
86-
return (
104+
{watchOperator === 'exist' ? (
105+
<FormField
106+
name='value'
107+
control={form.control}
108+
render={({ field }) => (
87109
<FormItem className='w-full'>
88110
<FormLabel>{t('value.label')}</FormLabel>
89-
<FormControl>
90-
<Input {...field} placeholder={t('value.placeholder')} />
91-
</FormControl>
111+
<Select
112+
onValueChange={field.onChange}
113+
defaultValue={field.value}
114+
>
115+
<FormControl>
116+
<SelectTrigger className='capitalize'>
117+
<SelectValue placeholder={t('value.placeholder')} />
118+
</SelectTrigger>
119+
</FormControl>
120+
<SelectContent>
121+
{['true', 'false'].map((c) => {
122+
return (
123+
<SelectItem key={c} value={c} className='capitalize'>
124+
{c}
125+
</SelectItem>
126+
)
127+
})}
128+
</SelectContent>
129+
</Select>
92130
<FormMessage />
93131
</FormItem>
94-
)
95-
}}
96-
/>
132+
)}
133+
/>
134+
) : (
135+
<FormField
136+
name='value'
137+
control={form.control}
138+
render={({ field }) => {
139+
return (
140+
<FormItem className='w-full'>
141+
<FormLabel>{t('value.label')}</FormLabel>
142+
<FormControl>
143+
<Input {...field} placeholder={t('value.placeholder')} />
144+
</FormControl>
145+
<FormMessage />
146+
</FormItem>
147+
)
148+
}}
149+
/>
150+
)}
97151
</div>
98152
</form>
99153
</Form>

client/src/components/pages/flow-detail/flow-provider.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,8 @@ export const FlowProvider = ({ children, flow }: Props) => {
503503
(edge) => edge.target === connection.target,
504504
).length
505505

506+
const targetNode = nodes.find((node) => node.id === connection.target)
507+
506508
if (connection.source === connection.target) return false
507509

508510
if (
@@ -530,6 +532,14 @@ export const FlowProvider = ({ children, flow }: Props) => {
530532
})
531533
}
532534

535+
if (
536+
(targetNode?.data.action === EActionTypes.CHECK_VARIABLES ||
537+
targetNode?.data.action === EActionTypes.PROMPT_AND_COLLECT) &&
538+
sourcesFromHandleInState < 1
539+
) {
540+
return true
541+
}
542+
533543
if (targetFromHandleInState === 1) return false
534544
if (sourcesFromHandleInState < 1) return true
535545

client/src/components/pages/flow-detail/node-dialog/message.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export const MessageDialogContent = () => {
8080
return (
8181
<div className='space-y-3'>
8282
<div className='space-y-2'>
83-
<Label>{t('message_dialog.responses')}</Label>
83+
<Label required>{t('message_dialog.responses')}</Label>
8484
<Select value={messageType} onValueChange={handleSelectChange}>
8585
<SelectTrigger>
8686
<SelectValue placeholder='Select a fruit' />
@@ -98,7 +98,7 @@ export const MessageDialogContent = () => {
9898
</div>
9999
{messageType !== EMessageTypes.LIST_BUTTON && (
100100
<div className='space-y-2'>
101-
<Label>{t('message_dialog.forms.bot_response.label')}</Label>
101+
<Label required>{t('message_dialog.forms.bot_response.label')}</Label>
102102
{messageType === EMessageTypes.TEXT && (
103103
<Input
104104
placeholder={t('message_dialog.forms.bot_response.placeholder')}

client/src/components/pages/flow-detail/node-dialog/node-dialog.tsx

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
} from '@/components/ui'
1616
import { LANGS } from '@/constants'
1717
import { useDidUpdate } from '@/hooks/use-did-update'
18+
import { cn } from '@/lib/utils'
1819
import { EActionTypes } from '@/types/flow'
1920
import { useEffect, useState } from 'react'
2021
import { useTranslation } from 'react-i18next'
@@ -67,48 +68,63 @@ export const NodeDialog = () => {
6768
<DialogTrigger asChild>
6869
<div className='!hidden'></div>
6970
</DialogTrigger>
70-
<DialogContent className='max-w-xl'>
71+
<DialogContent
72+
className={cn('max-w-xl', {
73+
'max-w-5xl':
74+
selectedNode?.data.action === EActionTypes.PROMPT_AND_COLLECT,
75+
})}
76+
>
7177
<DialogHeader>
7278
<DialogTitle>{selectedNode?.data.label}</DialogTitle>
7379
<DialogDescription>{t('node_dialog.desc')}</DialogDescription>
7480
</DialogHeader>
7581
<div className='space-y-3'>
76-
<div className='space-y-2'>
77-
<Label>{t('forms:name.label')}</Label>
78-
<Input
79-
value={name}
80-
onChange={(e) => {
81-
setName(e.target.value)
82-
}}
83-
placeholder={t('forms:name.placeholder')}
84-
/>
85-
</div>
86-
{ACTIONS_TO_RENDER_LANG.includes(
87-
selectedNode.data.action as unknown as EActionTypes,
88-
) && (
82+
<div
83+
className={cn('grid grid-cols-2 gap-3', {
84+
'grid-cols-1': !ACTIONS_TO_RENDER_LANG.includes(
85+
selectedNode.data.action as unknown as EActionTypes,
86+
),
87+
})}
88+
>
8989
<div className='space-y-2'>
90-
<Label>{t('forms:bot_lang.label')}</Label>
91-
<Select
92-
onValueChange={(value) => {
93-
handleChangeLang(value)
90+
<Label>{t('forms:name.label')}</Label>
91+
<Input
92+
value={name}
93+
onChange={(e) => {
94+
setName(e.target.value)
9495
}}
95-
value={currentLang}
96-
>
97-
<SelectTrigger>
98-
<SelectValue placeholder={t('forms:bot_lang.placeholder')} />
99-
</SelectTrigger>
100-
<SelectContent>
101-
{Object.keys(LANGS).map((lang) => {
102-
return (
103-
<SelectItem key={lang} value={lang}>
104-
{LANGS[lang]}
105-
</SelectItem>
106-
)
107-
})}
108-
</SelectContent>
109-
</Select>
96+
placeholder={t('forms:name.placeholder')}
97+
/>
11098
</div>
111-
)}
99+
{ACTIONS_TO_RENDER_LANG.includes(
100+
selectedNode.data.action as unknown as EActionTypes,
101+
) && (
102+
<div className='space-y-2'>
103+
<Label>{t('forms:bot_lang.label')}</Label>
104+
<Select
105+
onValueChange={(value) => {
106+
handleChangeLang(value)
107+
}}
108+
value={currentLang}
109+
>
110+
<SelectTrigger>
111+
<SelectValue
112+
placeholder={t('forms:bot_lang.placeholder')}
113+
/>
114+
</SelectTrigger>
115+
<SelectContent>
116+
{Object.keys(LANGS).map((lang) => {
117+
return (
118+
<SelectItem key={lang} value={lang}>
119+
{LANGS[lang]}
120+
</SelectItem>
121+
)
122+
})}
123+
</SelectContent>
124+
</Select>
125+
</div>
126+
)}
127+
</div>
112128
{selectedNode &&
113129
MAP_ACTION[
114130
selectedNode.data.action as unknown as EActionTypes

client/src/components/pages/flow-detail/node-dialog/prompt-and-collect.tsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
Input,
23
Label,
34
Select,
45
SelectContent,
@@ -15,12 +16,13 @@ import { MAP_GRAMMAR_TYPE } from '../constant'
1516

1617
export const PromptAndCollectDialogContent = () => {
1718
const { t } = useTranslation('forms')
18-
const { flow, selectedNode, handleChangeSelectedNode } = useFlowCtx()
19+
const { flow, selectedNode, handleChangeSelectedNode, currentLang } =
20+
useFlowCtx()
1921

2022
return (
2123
<>
2224
<div className='space-y-3'>
23-
<div className='flex gap-3'>
25+
<div className='grid-cols-4 grid gap-3'>
2426
<div className='space-y-2 w-full'>
2527
<Label>{t('grammar_type.label')}</Label>
2628
<Select
@@ -82,8 +84,6 @@ export const PromptAndCollectDialogContent = () => {
8284
</SelectContent>
8385
</Select>
8486
</div>
85-
</div>
86-
<div className='flex gap-3'>
8787
<div className='space-y-2 w-full'>
8888
<Label>{t('trained_data.label')}</Label>
8989
<Select
@@ -141,6 +141,29 @@ export const PromptAndCollectDialogContent = () => {
141141
</Select>
142142
</div>
143143
</div>
144+
{selectedNode?.data?.repeat > 0 && (
145+
<div className='space-y-2'>
146+
<Label required>{t('repeat_message.label')}</Label>
147+
<Input
148+
placeholder={t('repeat_message.placeholder')}
149+
value={
150+
selectedNode?.data?.contents?.[currentLang]?.repeatMessage || ''
151+
}
152+
onChange={(e) => {
153+
if (!selectedNode) return
154+
155+
const clonedNode = _.cloneDeep(selectedNode)
156+
157+
clonedNode.data.contents[currentLang] = {
158+
...clonedNode.data.contents[currentLang],
159+
repeatMessage: e.target.value,
160+
}
161+
162+
handleChangeSelectedNode(clonedNode)
163+
}}
164+
/>
165+
</div>
166+
)}
144167
<MessageDialogContent />
145168
</div>
146169
</>

0 commit comments

Comments
 (0)