33 useFrappeUpdateDoc ,
44 useFrappeDeleteDoc ,
55} from 'frappe-react-sdk' ;
6- import { Label } from '@/components/ui/label' ;
7- import { Input } from '@/components/ui/input' ;
86import { Button } from '@/components/ui/button' ;
97import { ScrollArea } from '@/components/ui/scroll-area' ;
108import SetTriggerDialog from '@/components/workflows/set-trigger-dialog' ;
@@ -13,21 +11,10 @@ import { useNavigate } from '@tanstack/react-router';
1311import { useConfirm } from '@/hooks/confirm' ;
1412import { toast } from 'sonner' ;
1513import { useEditorStore } from '@/stores/editor' ;
16- import { DocTypeAutoComplete } from '../common/doctype-autocomplete' ;
1714import { nodesToHazelNodes , edgesToHazelConnections } from '@/utils/editor' ;
15+ import { ParamForm } from '@/components/common/param-field' ;
1816
19- import {
20- Select ,
21- SelectContent ,
22- SelectItem ,
23- SelectTrigger ,
24- SelectValue ,
25- } from "@/components/ui/select"
26-
27-
28- interface TriggerConfig {
29- [ index : string ] : string ;
30- }
17+ type FormState = Record < string , string > ;
3118
3219export function WorkflowConfigPanel ( {
3320 hazelWorkflow,
@@ -56,30 +43,55 @@ export function WorkflowConfigPanel({
5643 }
5744 ) ;
5845
59-
6046 const { updateDoc } = useFrappeUpdateDoc < HazelWorkflow > ( ) ;
6147 const { deleteDoc } = useFrappeDeleteDoc ( ) ;
6248
6349 const navigate = useNavigate ( ) ;
6450 const confirm = useConfirm ( ) ;
6551
66- const [ triggerFormState , setTriggerFormState ] = useState < TriggerConfig > ( { } ) ;
52+ const [ triggerFormState , setTriggerFormState ] = useState < FormState > ( { } ) ;
53+ const [ actionFormState , setActionFormState ] = useState < FormState > ( { } ) ;
6754 const [ updateTriggerDialogOpen , setUpdateTriggerDialogOpen ] = useState ( false ) ;
6855
56+ // Initialize trigger form state
6957 useEffect ( ( ) => {
70- const initTriggerFormState : TriggerConfig = { } ;
71- const initConfig = hazelWorkflow . trigger_config
58+ const initState : FormState = { } ;
59+ const savedConfig = hazelWorkflow . trigger_config
7260 ? JSON . parse ( hazelWorkflow . trigger_config )
7361 : { } ;
7462
7563 if ( triggerDoc ) {
7664 for ( const param of triggerDoc . params || [ ] ) {
77- initTriggerFormState [ param . fieldname ] = initConfig [ param . fieldname ] ;
65+ initState [ param . fieldname ] = savedConfig [ param . fieldname ] || '' ;
7866 }
7967 }
80- setTriggerFormState ( initTriggerFormState ) ;
68+ setTriggerFormState ( initState ) ;
8169 } , [ triggerDoc , hazelWorkflow ] ) ;
8270
71+ // Initialize action form state when selected node changes
72+ useEffect ( ( ) => {
73+ const initState : FormState = { } ;
74+ const savedParams = editorStore . selectedNode ?. data ?. parameters ;
75+
76+ if ( actionDoc && savedParams ) {
77+ for ( const param of actionDoc . params || [ ] ) {
78+ const savedParam = Array . isArray ( savedParams )
79+ ? savedParams . find ( ( p : { fieldname : string } ) => p . fieldname === param . fieldname )
80+ : null ;
81+ initState [ param . fieldname ] = savedParam ?. value || '' ;
82+ }
83+ }
84+ setActionFormState ( initState ) ;
85+ } , [ actionDoc , editorStore . selectedNode ] ) ;
86+
87+ const handleTriggerFieldChange = ( fieldname : string , value : string ) => {
88+ setTriggerFormState ( ( prev ) => ( { ...prev , [ fieldname ] : value } ) ) ;
89+ } ;
90+
91+ const handleActionFieldChange = ( fieldname : string , value : string ) => {
92+ setActionFormState ( ( prev ) => ( { ...prev , [ fieldname ] : value } ) ) ;
93+ } ;
94+
8395 async function handleDeleteWorkflow ( ) {
8496 const deleteConfirmed = await confirm ( {
8597 title : 'Delete Workflow' ,
@@ -117,135 +129,70 @@ export function WorkflowConfigPanel({
117129 }
118130 }
119131
120-
121132 return (
122- < ScrollArea className = "h-full p-3" >
123- < strong > { hazelWorkflow . title } </ strong >
124- < ul >
125- { hazelWorkflow . trigger_type && (
126- < li >
127- Trigger: { hazelWorkflow . trigger_type }
133+ < ScrollArea className = "h-full p-3" >
134+ < h2 className = "text-lg font-semibold mb-3" > { hazelWorkflow . title } </ h2 >
135+
136+ { /* Trigger Section */ }
137+ { hazelWorkflow . trigger_type && (
138+ < section className = "mb-4" >
139+ < div className = "flex items-center justify-between mb-2" >
140+ < span className = "text-sm text-gray-600" >
141+ Trigger: < strong > { hazelWorkflow . trigger_type } </ strong >
142+ </ span >
128143 < Button
129144 onClick = { ( ) => setUpdateTriggerDialogOpen ( true ) }
130145 outline = { true }
146+ className = "text-xs"
131147 >
132148 Change
133149 </ Button >
134- </ li >
135- ) }
136- </ ul >
137- { ( triggerDoc ?. params || [ ] ) . map ( ( param ) => {
138- return (
139- < div key = { param . name } >
140- < Label htmlFor = { param . fieldname } > { param . label } </ Label >
141-
142- { param . fieldtype === "Link" && < DocTypeAutoComplete
143- onChange = { ( v ) =>
144- setTriggerFormState ( {
145- ...triggerFormState ,
146- [ param . fieldname ] : v ,
147- } ) }
148- doctype = 'DocType' /> }
149-
150- { param . fieldtype === "Select" &&
151- < Select
152- value = { triggerFormState [ param . fieldname ] }
153- onValueChange = { ( v ) =>
154- setTriggerFormState ( {
155- ...triggerFormState ,
156- [ param . fieldname ] : v ,
157- } )
158- }
159- >
160- < SelectTrigger className = "w-[180px]" >
161- < SelectValue placeholder = "Event" />
162- </ SelectTrigger >
163- < SelectContent >
164- { param . options ?. split ( "\n" ) . map ( ( option ) => {
165- return < SelectItem value = { option } > { option } </ SelectItem >
166- } ) }
167-
168-
169- </ SelectContent >
170- </ Select >
171- }
172- { param . fieldtype === "Data" &&
173- < Input
174- value = { triggerFormState [ param . fieldname ] }
175- onChange = { ( v ) =>
176- setTriggerFormState ( {
177- ...triggerFormState ,
178- [ param . fieldname ] : v . target . value ,
179- } )
180- }
181- type = "text"
182- name = { param . fieldname }
183- />
184- }
185150 </ div >
186- ) ;
187- } ) }
151+
152+ { triggerDoc ?. params && triggerDoc . params . length > 0 && (
153+ < ParamForm
154+ params = { triggerDoc . params }
155+ values = { triggerFormState }
156+ onChange = { handleTriggerFieldChange }
157+ />
158+ ) }
159+ </ section >
160+ ) }
188161
189162 < SetTriggerDialog
190163 open = { updateTriggerDialogOpen }
191164 onClose = { setUpdateTriggerDialogOpen }
192165 />
193- < Button color = "white" onClick = { handleSaveWorkflow } >
194- Save
195- </ Button >
196- < br />
197- < Button color = "rose" onClick = { handleDeleteWorkflow } >
198- Delete Workflow
199- </ Button >
200- < h2 className = " mt-4 text-xl font-bold text-gray-900" > Action Settings</ h2 >
201- { editorStore . selectedNode ?. data . type }
202-
203- { actionDoc ?. params ?. map ( param => {
204- return (
205- < div key = { param . name } >
206- < Label htmlFor = { param . fieldname } > { param . label } </ Label >
207-
208- { param . fieldtype === "Link" && < DocTypeAutoComplete
209- onChange = { ( v ) =>
210- setTriggerFormState ( {
211- ...triggerFormState ,
212- [ param . fieldname ] : v ,
213- } ) }
214- doctype = 'DocType' /> }
215-
216- { param . fieldtype === "Select" &&
217- < Select
218- value = { triggerFormState [ param . fieldname ] }
219- onValueChange = { ( v ) =>
220- setTriggerFormState ( {
221- ...triggerFormState ,
222- [ param . fieldname ] : v ,
223- } )
224- }
225- >
226- < SelectTrigger className = "w-[180px]" >
227- < SelectValue placeholder = "Event" />
228- </ SelectTrigger >
229- < SelectContent >
230- { param . options ?. split ( "\n" ) . map ( ( option ) => {
231- return < SelectItem value = { option } > { option } </ SelectItem >
232- } ) }
233-
234-
235- </ SelectContent >
236- </ Select >
237- }
238- { param . fieldtype === "Data" &&
239- < Input
240- value = { triggerFormState [ param . fieldname ] }
241- onChange = { ( ) => { /* TODO: set this in backend */ } }
242- type = "text"
243- name = { param . fieldname }
166+
167+ { /* Action Buttons */ }
168+ < div className = "flex gap-2 mb-4" >
169+ < Button color = "white" onClick = { handleSaveWorkflow } >
170+ Save
171+ </ Button >
172+ < Button color = "rose" onClick = { handleDeleteWorkflow } >
173+ Delete
174+ </ Button >
175+ </ div >
176+
177+ { /* Action Settings Section */ }
178+ { editorStore . selectedNode && (
179+ < section className = "border-t pt-4" >
180+ < h3 className = "text-md font-semibold text-gray-900 mb-2" >
181+ Action Settings
182+ </ h3 >
183+ < p className = "text-sm text-gray-600 mb-3" >
184+ { editorStore . selectedNode . data . type }
185+ </ p >
186+
187+ { actionDoc ?. params && actionDoc . params . length > 0 && (
188+ < ParamForm
189+ params = { actionDoc . params }
190+ values = { actionFormState }
191+ onChange = { handleActionFieldChange }
244192 />
245- }
246- </ div >
247- ) ;
248- } ) }
193+ ) }
194+ </ section >
195+ ) }
249196 </ ScrollArea >
250197 ) ;
251198}
0 commit comments