Skip to content

Commit bf4636c

Browse files
committed
feat: add select var in subflow, fix conversation have another channel type
1 parent d64eaad commit bf4636c

File tree

15 files changed

+209
-50
lines changed

15 files changed

+209
-50
lines changed

client/package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/src/apis/channel.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import http_client from '@/lib/http-client'
33
import { TChannelInput } from '@/lib/schema/channel'
44
import {
55
TChannelQuery,
6+
TChannelQueryForSelect,
67
TChannelType,
78
TChannelWithChannelType,
89
} from '@/types/channel'
@@ -47,10 +48,10 @@ class ChannelApi {
4748
}
4849

4950
getChannelsForSelect(
50-
flowId?: string,
51+
query: TChannelQueryForSelect,
5152
): Promise<TBaseResponse<TSelectResponse<string, string>[]>> {
5253
return http_client.get(`${ENDPOINTS.CHANNEL.INDEX}/for-select`, {
53-
params: { flowId },
54+
params: query,
5455
})
5556
}
5657

client/src/components/layouts/live-chat/sidebar.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,18 @@ const Sidebar = () => {
4141
initTotalItems: data.totalItems || 0,
4242
})
4343

44-
const { data: channels } = useSuspenseQuery(queryChannelsForSelectOption())
44+
const { data: channels } = useSuspenseQuery(
45+
queryChannelsForSelectOption({
46+
isForConversation: true,
47+
}),
48+
)
4549

4650
return (
4751
<aside className='max-w-80 w-full border-r border-input'>
4852
<div className='h-header flex items-center px-4 border-b border-input'>
4953
<PageTitle>{t('title')}</PageTitle>
5054
</div>
51-
<div className='p-4 pb-0'>
55+
<div className='p-4'>
5256
<Select
5357
value={search.get('channelId') || NOT_CHOOSE}
5458
onValueChange={(value) => {

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

Lines changed: 118 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import {
66
SelectTrigger,
77
SelectValue,
88
} from '@/components/ui'
9-
import { queryFlowsForSelectOption } from '@/lib/query-options/flow'
9+
import { NOT_CHOOSE } from '@/constants'
10+
import {
11+
queryFlowOption,
12+
queryFlowsForSelectOption,
13+
} from '@/lib/query-options/flow'
1014
import { useQuery } from '@tanstack/react-query'
1115
import _ from 'lodash'
1216
import { useTranslation } from 'react-i18next'
@@ -17,38 +21,122 @@ export const SubFlowContent = () => {
1721
const { id } = useParams()
1822
const { data: flows } = useQuery(queryFlowsForSelectOption())
1923
const { t } = useTranslation('forms')
20-
const { handleChangeSelectedNode, selectedNode } = useFlowCtx()
24+
const { handleChangeSelectedNode, selectedNode, flow } = useFlowCtx()
25+
const { data: subflow } = useQuery({
26+
...queryFlowOption(selectedNode?.data?.subFlowId),
27+
enabled: !!selectedNode?.data?.subFlowId,
28+
})
2129

2230
return (
23-
<div className='space-y-2'>
24-
<Label>{t('sub_flow.label')}</Label>
25-
<Select
26-
value={selectedNode?.data?.subFlowId}
27-
onValueChange={(value) => {
28-
if (!selectedNode) return
29-
30-
const cloneSelectedNode = _.cloneDeep(selectedNode)
31-
32-
cloneSelectedNode.data.subFlowId = value
33-
34-
handleChangeSelectedNode(cloneSelectedNode)
35-
}}
36-
>
37-
<SelectTrigger>
38-
<SelectValue placeholder={t('sub_flow.placeholder')} />
39-
</SelectTrigger>
40-
<SelectContent>
41-
{flows?.map((flow) => {
42-
if (flow.value === id) return null
43-
44-
return (
45-
<SelectItem key={flow.value} value={flow.value}>
46-
{flow.label}
31+
<div className='space-y-3'>
32+
<div className='space-y-2'>
33+
<Label>{t('sub_flow.label')}</Label>
34+
<Select
35+
value={selectedNode?.data?.subFlowId}
36+
onValueChange={(value) => {
37+
if (!selectedNode) return
38+
39+
const cloneSelectedNode = _.cloneDeep(selectedNode)
40+
41+
cloneSelectedNode.data.subFlowId = value
42+
43+
handleChangeSelectedNode(cloneSelectedNode)
44+
}}
45+
>
46+
<SelectTrigger>
47+
<SelectValue placeholder={t('sub_flow.placeholder')} />
48+
</SelectTrigger>
49+
<SelectContent>
50+
{flows?.map((flow) => {
51+
if (flow.value === id) return null
52+
53+
return (
54+
<SelectItem key={flow.value} value={flow.value}>
55+
{flow.label}
56+
</SelectItem>
57+
)
58+
})}
59+
</SelectContent>
60+
</Select>
61+
</div>
62+
<div className='flex gap-3'>
63+
<div className='space-y-2 w-full'>
64+
<Label>{t('assign_var.label')}</Label>
65+
<Select
66+
value={selectedNode?.data?.assignTo || NOT_CHOOSE}
67+
onValueChange={(value) => {
68+
if (!selectedNode) return
69+
70+
const cloneSelectedNode = _.cloneDeep(selectedNode)
71+
72+
if (value === NOT_CHOOSE) {
73+
delete cloneSelectedNode.data.assignTo
74+
} else {
75+
cloneSelectedNode.data.assignTo = value
76+
}
77+
78+
handleChangeSelectedNode(cloneSelectedNode)
79+
}}
80+
>
81+
<SelectTrigger>
82+
<SelectValue placeholder={t('assign_var.placeholder')} />
83+
</SelectTrigger>
84+
<SelectContent>
85+
<SelectItem value={NOT_CHOOSE}>
86+
{t('assign_var.placeholder')}
87+
</SelectItem>
88+
{flow.variables?.map((variable, index) => {
89+
return (
90+
<SelectItem
91+
key={`${variable.name}-${index}`}
92+
value={variable.name}
93+
>
94+
{variable.name}
95+
</SelectItem>
96+
)
97+
})}
98+
</SelectContent>
99+
</Select>
100+
</div>
101+
<div className='space-y-2 w-full'>
102+
<Label>{t('output_var.label')}</Label>
103+
<Select
104+
value={selectedNode?.data?.outputVar || NOT_CHOOSE}
105+
onValueChange={(value) => {
106+
if (!selectedNode) return
107+
108+
const cloneSelectedNode = _.cloneDeep(selectedNode)
109+
110+
if (value === NOT_CHOOSE) {
111+
delete cloneSelectedNode.data.outputVar
112+
} else {
113+
cloneSelectedNode.data.outputVar = value
114+
}
115+
116+
handleChangeSelectedNode(cloneSelectedNode)
117+
}}
118+
>
119+
<SelectTrigger>
120+
<SelectValue placeholder={t('output_var.placeholder')} />
121+
</SelectTrigger>
122+
<SelectContent>
123+
<SelectItem value={NOT_CHOOSE}>
124+
{t('output_var.placeholder')}
47125
</SelectItem>
48-
)
49-
})}
50-
</SelectContent>
51-
</Select>
126+
{subflow?.variables?.map((variable, index) => {
127+
return (
128+
<SelectItem
129+
key={`${variable.name}-${index}`}
130+
value={variable.name}
131+
>
132+
{variable.name}
133+
</SelectItem>
134+
)
135+
})}
136+
</SelectContent>
137+
</Select>
138+
</div>
139+
</div>
52140
</div>
53141
)
54142
}

client/src/lib/loader.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,11 @@ export const flowsLoader = async ({ request }: any) => {
110110

111111
export const flowDetailLoader = async ({ params }: any) => {
112112
await Promise.all([
113-
queryClient.ensureQueryData(queryChannelsForSelectOption(params.id)),
113+
queryClient.ensureQueryData(
114+
queryChannelsForSelectOption({
115+
flowId: params.id,
116+
}),
117+
),
114118
queryClient.ensureQueryData(queryFlowDetailOption(params.id)),
115119
queryClient.ensureQueryData(queryChannelForTestOption(params.id)),
116120
])

client/src/lib/query-options/channel.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { channelApi } from '@/apis/channel'
2-
import { TChannelQuery } from '@/types/channel'
2+
import { TChannelQuery, TChannelQueryForSelect } from '@/types/channel'
33
import { keepPreviousData, queryOptions } from '@tanstack/react-query'
44

55
export const queryChannelTypesOption = queryOptions({
@@ -36,11 +36,17 @@ export const queryChannelsOption = (query?: TChannelQuery) => {
3636
})
3737
}
3838

39-
export const queryChannelsForSelectOption = (flowId?: string) => {
39+
export const queryChannelsForSelectOption = ({
40+
flowId,
41+
isForConversation,
42+
}: TChannelQueryForSelect) => {
4043
return queryOptions({
41-
queryKey: ['channels-for-select', flowId],
44+
queryKey: ['channels-for-select', flowId, isForConversation],
4245
queryFn: async () => {
43-
const res = await channelApi.getChannelsForSelect(flowId)
46+
const res = await channelApi.getChannelsForSelect({
47+
flowId,
48+
isForConversation,
49+
})
4450

4551
return res.data
4652
},

client/src/locales/en/forms.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,20 @@
221221
"required": "Please select variable to assign user response."
222222
}
223223
},
224+
"assign_var": {
225+
"label": "Assign variable",
226+
"placeholder": "Select variable",
227+
"errors": {
228+
"required": "Please select variable to assign."
229+
}
230+
},
231+
"output_var": {
232+
"label": "Output variable",
233+
"placeholder": "Select variable",
234+
"errors": {
235+
"required": "Please select output variable."
236+
}
237+
},
224238
"repeat": {
225239
"label": "Repeat",
226240
"placeholder": "Select repeat",

client/src/locales/vi/forms.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,5 +346,19 @@
346346
"errors": {
347347
"required": "Vui lòng nhập tin nhắn lặp lại."
348348
}
349+
},
350+
"assign_var": {
351+
"label": "Gán biến",
352+
"placeholder": "Chọn biến để gán giá trị",
353+
"errors": {
354+
"required": "Vui lòng chọn biến để gán giá trị."
355+
}
356+
},
357+
"output_var": {
358+
"label": "Biến đầu ra",
359+
"placeholder": "Chọn biến đầu ra",
360+
"errors": {
361+
"required": "Vui lòng chọn biến đầu ra."
362+
}
349363
}
350364
}

client/src/types/channel.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,8 @@ export type TChannelWithChannelType = TChannel & {
3434
export type TChannelQuery = TBaseQuery & {
3535
orderBy: keyof TChannel
3636
}
37+
38+
export type TChannelQueryForSelect = {
39+
flowId?: string
40+
isForConversation?: boolean
41+
}

client/src/utils/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,5 +192,5 @@ export const isEmptyObject = (obj: Record<any, any>) => {
192192
}
193193

194194
export const genScript = (contactId: string) => {
195-
return `<script src="http://localhost:8080/public/script/chatbox.js" channelId="${contactId}"></script>`
195+
return `<script src="http://localhost:8080/public/script/chatbox.js" channelId="${contactId}" id="${contactId}" async type="text/javascript"></script>`
196196
}

0 commit comments

Comments
 (0)