6
6
import React , { useRef , useState , useEffect } from 'react' ;
7
7
import { useSelector } from 'react-redux' ;
8
8
import { useHistory } from 'react-router-dom' ;
9
- import { useReactFlow } from 'reactflow' ;
10
9
import { Form , Formik , FormikProps } from 'formik' ;
11
10
import * as yup from 'yup' ;
12
- import { EuiFlexGroup , EuiFlexItem , EuiResizableContainer } from '@elastic/eui' ;
11
+ import {
12
+ EuiFlexGroup ,
13
+ EuiFlexItem ,
14
+ EuiPanel ,
15
+ EuiResizableContainer ,
16
+ EuiTitle ,
17
+ } from '@elastic/eui' ;
13
18
import { getCore } from '../../services' ;
14
19
15
20
import {
16
21
Workflow ,
17
- ReactFlowComponent ,
18
22
WORKFLOW_STATE ,
19
- ReactFlowEdge ,
20
23
WorkflowFormValues ,
21
24
WorkflowSchema ,
22
25
WorkflowConfig ,
@@ -35,20 +38,22 @@ import {
35
38
updateWorkflow ,
36
39
useAppDispatch ,
37
40
} from '../../store' ;
41
+ import { WorkflowInputs } from './workflow_inputs' ;
42
+ import { configToTemplateFlows } from './utils' ;
38
43
import { Workspace } from './workspace' ;
39
44
40
45
// styling
41
46
import './workspace/workspace-styles.scss' ;
42
47
import '../../global-styles.scss' ;
43
- import { WorkflowInputs } from './workflow_inputs' ;
44
- import { configToTemplateFlows } from './utils' ;
48
+ import { Tools } from './tools' ;
45
49
46
50
interface ResizableWorkspaceProps {
47
51
isNewWorkflow : boolean ;
48
52
workflow ?: Workflow ;
49
53
}
50
54
51
55
const WORKFLOW_INPUTS_PANEL_ID = 'workflow_inputs_panel_id' ;
56
+ const TOOLS_PANEL_ID = 'tools_panel_id' ;
52
57
53
58
/**
54
59
* The overall workspace component that maintains state related to the 2 resizable
@@ -75,21 +80,29 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
75
80
// Validation states
76
81
const [ formValidOnSubmit , setFormValidOnSubmit ] = useState < boolean > ( true ) ;
77
82
78
- // Component details side panel state
79
- const [ isDetailsPanelOpen , setisDetailsPanelOpen ] = useState < boolean > ( true ) ;
80
- const collapseFn = useRef (
83
+ // Workflow inputs side panel state
84
+ const [ isWorkflowInputsPanelOpen , setIsWorkflowInputsPanelOpen ] = useState <
85
+ boolean
86
+ > ( true ) ;
87
+ const collapseFnHorizontal = useRef (
81
88
( id : string , options : { direction : 'left' | 'right' } ) => { }
82
89
) ;
83
- const onToggleChange = ( ) => {
84
- collapseFn . current ( WORKFLOW_INPUTS_PANEL_ID , { direction : 'left' } ) ;
85
- setisDetailsPanelOpen ( ! isDetailsPanelOpen ) ;
90
+ const onToggleWorkflowInputsChange = ( ) => {
91
+ collapseFnHorizontal . current ( WORKFLOW_INPUTS_PANEL_ID , {
92
+ direction : 'left' ,
93
+ } ) ;
94
+ setIsWorkflowInputsPanelOpen ( ! isWorkflowInputsPanelOpen ) ;
86
95
} ;
87
96
88
- // Selected component state
89
- const reactFlowInstance = useReactFlow ( ) ;
90
- const [ selectedComponent , setSelectedComponent ] = useState <
91
- ReactFlowComponent
92
- > ( ) ;
97
+ // Tools side panel state
98
+ const [ isToolsPanelOpen , setIsToolsPanelOpen ] = useState < boolean > ( true ) ;
99
+ const collapseFnVertical = useRef (
100
+ ( id : string , options : { direction : 'top' | 'bottom' } ) => { }
101
+ ) ;
102
+ const onToggleToolsChange = ( ) => {
103
+ collapseFnVertical . current ( TOOLS_PANEL_ID , { direction : 'bottom' } ) ;
104
+ setIsToolsPanelOpen ( ! isToolsPanelOpen ) ;
105
+ } ;
93
106
94
107
// Save/provision/deprovision button state
95
108
const isSaveable =
@@ -116,31 +129,6 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
116
129
const isLoadingGlobal =
117
130
loading || isProvisioning || isDeprovisioning || isSaving || isCreating ;
118
131
119
- /**
120
- * Custom listener on when nodes are selected / de-selected. Passed to
121
- * downstream ReactFlow components you can listen using
122
- * the out-of-the-box useOnSelectionChange hook.
123
- * - populate panel content appropriately
124
- * - open the panel if a node is selected and the panel is closed
125
- * - it is assumed that only one node can be selected at once
126
- */
127
- function onSelectionChange ( {
128
- nodes,
129
- edges,
130
- } : {
131
- nodes : ReactFlowComponent [ ] ;
132
- edges : ReactFlowEdge [ ] ;
133
- } ) {
134
- if ( nodes && nodes . length > 0 ) {
135
- setSelectedComponent ( nodes [ 0 ] ) ;
136
- if ( ! isDetailsPanelOpen ) {
137
- onToggleChange ( ) ;
138
- }
139
- } else {
140
- setSelectedComponent ( undefined ) ;
141
- }
142
- }
143
-
144
132
// Hook to update some default values for the workflow, if applicable.
145
133
// We need to handle different scenarios:
146
134
// 1. Rendering backend-only-created workflow / an already-created workflow with no ui_metadata.
@@ -171,19 +159,6 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
171
159
}
172
160
} , [ props . workflow ] ) ;
173
161
174
- // Hook to updated the selected ReactFlow component
175
- useEffect ( ( ) => {
176
- reactFlowInstance ?. setNodes ( ( nodes : ReactFlowComponent [ ] ) =>
177
- nodes . map ( ( node ) => {
178
- node . data = {
179
- ...node . data ,
180
- selected : node . id === selectedComponent ?. id ? true : false ,
181
- } ;
182
- return node ;
183
- } )
184
- ) ;
185
- } , [ selectedComponent ] ) ;
186
-
187
162
// Initialize the form state to an existing workflow, if applicable.
188
163
useEffect ( ( ) => {
189
164
if ( workflow ?. ui_metadata ?. config ) {
@@ -194,10 +169,6 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
194
169
}
195
170
} , [ workflow ] ) ;
196
171
197
- // TODO: leave as a placeholder for now. Current functionality is the workflow
198
- // is readonly and only reacts/changes when the underlying form is updated.
199
- function onNodesChange ( nodes : ReactFlowComponent [ ] ) : void { }
200
-
201
172
/**
202
173
* Function to pass down to the Formik <Form> components as a listener to propagate
203
174
* form changes to this parent component to re-enable save button, etc.
@@ -275,41 +246,20 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
275
246
>
276
247
{ ( formikProps ) => (
277
248
< Form >
278
- { /*
279
- TODO: finalize where/how to show invalidations
280
- */ }
281
- { /* {!formValidOnSubmit && (
282
- <EuiCallOut
283
- title="There are empty or invalid fields"
284
- color="danger"
285
- iconType="alert"
286
- style={{ marginBottom: '16px' }}
287
- >
288
- Please address the highlighted fields and try saving again.
289
- </EuiCallOut>
290
- )}
291
- {isDeprovisionable && isDirty && (
292
- <EuiCallOut
293
- title="The configured flow has been provisioned"
294
- color="warning"
295
- iconType="alert"
296
- style={{ marginBottom: '16px' }}
297
- >
298
- Changes cannot be saved until the workflow has first been
299
- deprovisioned.
300
- </EuiCallOut>
301
- )} */ }
302
249
< EuiResizableContainer
303
250
direction = "horizontal"
304
251
className = "stretch-absolute"
305
252
style = { {
306
- marginLeft : '-8px' ,
253
+ marginLeft : isWorkflowInputsPanelOpen ? '-8px' : '0px' ,
254
+ marginTop : '-8px' ,
307
255
} }
308
256
>
309
257
{ ( EuiResizablePanel , EuiResizableButton , { togglePanel } ) => {
310
258
if ( togglePanel ) {
311
- collapseFn . current = ( panelId : string , { direction } ) =>
312
- togglePanel ( panelId , { direction } ) ;
259
+ collapseFnHorizontal . current = (
260
+ panelId : string ,
261
+ { direction }
262
+ ) => togglePanel ( panelId , { direction } ) ;
313
263
}
314
264
315
265
return (
@@ -320,46 +270,106 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
320
270
initialSize = { 50 }
321
271
minSize = "25%"
322
272
paddingSize = "s"
323
- onToggleCollapsedInternal = { ( ) => onToggleChange ( ) }
273
+ onToggleCollapsedInternal = { ( ) =>
274
+ onToggleWorkflowInputsChange ( )
275
+ }
324
276
>
325
- < EuiFlexGroup
326
- direction = "column"
327
- gutterSize = "s"
328
- className = "workspace-panel"
329
- >
330
- < EuiFlexItem >
331
- < WorkflowInputs
332
- workflow = { props . workflow }
333
- formikProps = { formikProps }
334
- onFormChange = { onFormChange }
335
- validateAndSubmit = { validateAndSubmit }
336
- />
337
- </ EuiFlexItem >
338
- </ EuiFlexGroup >
277
+ < WorkflowInputs
278
+ workflow = { props . workflow }
279
+ formikProps = { formikProps }
280
+ onFormChange = { onFormChange }
281
+ validateAndSubmit = { validateAndSubmit }
282
+ />
339
283
</ EuiResizablePanel >
340
284
< EuiResizableButton />
341
285
< EuiResizablePanel
342
- style = { { marginRight : '-16px' } }
286
+ style = { {
287
+ marginRight : '-32px' ,
288
+ marginBottom : isToolsPanelOpen ? '0px' : '24px' ,
289
+ } }
343
290
mode = "main"
344
291
initialSize = { 60 }
345
292
minSize = "25%"
346
293
paddingSize = "s"
347
294
>
348
- < EuiFlexGroup
349
- direction = "column"
350
- gutterSize = "s"
295
+ < EuiResizableContainer
351
296
className = "workspace-panel"
297
+ direction = "vertical"
298
+ style = { {
299
+ marginLeft : '-8px' ,
300
+ marginTop : '-8px' ,
301
+ padding : 'none' ,
302
+ } }
352
303
>
353
- < EuiFlexItem >
354
- < Workspace
355
- id = "ingest"
356
- workflow = { workflow }
357
- readonly = { false }
358
- onNodesChange = { onNodesChange }
359
- onSelectionChange = { onSelectionChange }
360
- />
361
- </ EuiFlexItem >
362
- </ EuiFlexGroup >
304
+ { (
305
+ EuiResizablePanel ,
306
+ EuiResizableButton ,
307
+ { togglePanel }
308
+ ) => {
309
+ if ( togglePanel ) {
310
+ collapseFnVertical . current = (
311
+ panelId : string ,
312
+ { direction }
313
+ ) =>
314
+ // ignore is added since docs are incorrectly missing "top" and "bottom"
315
+ // as valid direction options for vertically-configured resizable panels.
316
+ // @ts -ignore
317
+ togglePanel ( panelId , { direction } ) ;
318
+ }
319
+
320
+ return (
321
+ < >
322
+ < EuiResizablePanel
323
+ mode = "main"
324
+ initialSize = { 60 }
325
+ minSize = "25%"
326
+ paddingSize = "s"
327
+ style = { { marginBottom : '-8px' } }
328
+ >
329
+ < EuiFlexGroup
330
+ direction = "column"
331
+ gutterSize = "s"
332
+ style = { { height : '100%' } }
333
+ >
334
+ < EuiFlexItem >
335
+ < Workspace
336
+ id = "ingest"
337
+ workflow = { workflow }
338
+ readonly = { false }
339
+ />
340
+ </ EuiFlexItem >
341
+ </ EuiFlexGroup >
342
+ </ EuiResizablePanel >
343
+ < EuiResizableButton />
344
+ < EuiResizablePanel
345
+ id = { TOOLS_PANEL_ID }
346
+ mode = "collapsible"
347
+ initialSize = { 50 }
348
+ minSize = "25%"
349
+ paddingSize = "s"
350
+ onToggleCollapsedInternal = { ( ) =>
351
+ onToggleToolsChange ( )
352
+ }
353
+ style = { { marginBottom : '-24px' } }
354
+ >
355
+ < EuiFlexGroup
356
+ direction = "column"
357
+ gutterSize = "s"
358
+ style = { {
359
+ height : '100%' ,
360
+ } }
361
+ >
362
+ < EuiFlexItem >
363
+ < EuiPanel paddingSize = "m" >
364
+ < Tools workflow = { workflow } />
365
+ </ EuiPanel >
366
+ </ EuiFlexItem >
367
+ </ EuiFlexGroup >
368
+ </ EuiResizablePanel >
369
+ </ >
370
+ ) ;
371
+ } }
372
+ </ EuiResizableContainer >
363
373
</ EuiResizablePanel >
364
374
</ >
365
375
) ;
0 commit comments