8
8
EuiButton ,
9
9
EuiButtonEmpty ,
10
10
EuiCallOut ,
11
+ EuiCheckableCard ,
11
12
EuiComboBox ,
12
13
EuiEmptyPrompt ,
13
14
EuiFieldText ,
@@ -42,6 +43,7 @@ export interface IntegrationSetupInputs {
42
43
connectionLocation : string ;
43
44
checkpointLocation : string ;
44
45
connectionTableName : string ;
46
+ enabledWorkflows : string [ ] ;
45
47
}
46
48
47
49
type SetupCallout = { show : true ; title : string ; color ?: Color ; text ?: string } | { show : false } ;
@@ -182,6 +184,38 @@ const runQuery = async (
182
184
}
183
185
} ;
184
186
187
+ export function SetupWorkflowSelector ( {
188
+ integration,
189
+ useWorkflows,
190
+ toggleWorkflow,
191
+ } : {
192
+ integration : IntegrationConfig ;
193
+ useWorkflows : Map < string , boolean > ;
194
+ toggleWorkflow : ( name : string ) => void ;
195
+ } ) {
196
+ if ( ! integration . workflows ) {
197
+ return null ;
198
+ }
199
+
200
+ const cards = integration . workflows . map ( ( workflow ) => {
201
+ return (
202
+ < EuiCheckableCard
203
+ id = { `workflow-checkbox-${ workflow . name } ` }
204
+ key = { workflow . name }
205
+ label = { workflow . label }
206
+ checkableType = "checkbox"
207
+ value = { workflow . name }
208
+ checked = { useWorkflows . get ( workflow . name ) }
209
+ onChange = { ( ) => toggleWorkflow ( workflow . name ) }
210
+ >
211
+ { workflow . description }
212
+ </ EuiCheckableCard >
213
+ ) ;
214
+ } ) ;
215
+
216
+ return cards ;
217
+ }
218
+
185
219
export function SetupIntegrationForm ( {
186
220
config,
187
221
updateConfig,
@@ -197,6 +231,25 @@ export function SetupIntegrationForm({
197
231
const [ isBucketBlurred , setIsBucketBlurred ] = useState ( false ) ;
198
232
const [ isCheckpointBlurred , setIsCheckpointBlurred ] = useState ( false ) ;
199
233
234
+ const [ useWorkflows , setUseWorkflows ] = useState ( new Map < string , boolean > ( ) ) ;
235
+ const toggleWorkflow = ( name : string ) => {
236
+ setUseWorkflows ( new Map ( useWorkflows . set ( name , ! useWorkflows . get ( name ) ) ) ) ;
237
+ } ;
238
+
239
+ useEffect ( ( ) => {
240
+ if ( integration . workflows ) {
241
+ setUseWorkflows ( new Map ( integration . workflows . map ( ( w ) => [ w . name , w . enabled_by_default ] ) ) ) ;
242
+ }
243
+ } , [ integration . workflows ] ) ;
244
+
245
+ useEffect ( ( ) => {
246
+ updateConfig ( {
247
+ enabledWorkflows : [ ...useWorkflows . entries ( ) ] . filter ( ( w ) => w [ 1 ] ) . map ( ( w ) => w [ 0 ] ) ,
248
+ } ) ;
249
+ // If we add the updateConfig dep here, rendering crashes with "Maximum update depth exceeded"
250
+ // eslint-disable-next-line react-hooks/exhaustive-deps
251
+ } , [ useWorkflows ] ) ;
252
+
200
253
useEffect ( ( ) => {
201
254
const updateDataSources = async ( ) => {
202
255
const data = await suggestDataSources ( config . connectionType ) ;
@@ -339,12 +392,47 @@ export function SetupIntegrationForm({
339
392
} }
340
393
/>
341
394
</ EuiFormRow >
395
+ { integration . workflows ? (
396
+ < >
397
+ < EuiSpacer />
398
+ < EuiText >
399
+ < h3 > Installation Flows</ h3 >
400
+ </ EuiText >
401
+ < EuiSpacer />
402
+ < EuiFormRow
403
+ label = { 'Flows' }
404
+ helpText = {
405
+ 'Select from the available asset types based on your use case. Choose at least one.'
406
+ }
407
+ isInvalid = { ! [ ...useWorkflows . values ( ) ] . includes ( true ) }
408
+ error = { [ 'Must select at least one workflow.' ] }
409
+ >
410
+ < SetupWorkflowSelector
411
+ integration = { integration }
412
+ useWorkflows = { useWorkflows }
413
+ toggleWorkflow = { toggleWorkflow }
414
+ />
415
+ </ EuiFormRow >
416
+ </ >
417
+ ) : null }
342
418
</ >
343
419
) : null }
344
420
</ EuiForm >
345
421
) ;
346
422
}
347
423
424
+ const prepareQuery = ( query : string , config : IntegrationSetupInputs ) : string => {
425
+ let queryStr = query . replaceAll (
426
+ '{table_name}' ,
427
+ `${ config . connectionDataSource } .default.${ config . connectionTableName } `
428
+ ) ;
429
+ queryStr = queryStr . replaceAll ( '{s3_bucket_location}' , config . connectionLocation ) ;
430
+ queryStr = queryStr . replaceAll ( '{s3_checkpoint_location}' , config . checkpointLocation ) ;
431
+ queryStr = queryStr . replaceAll ( '{object_name}' , config . connectionTableName ) ;
432
+ queryStr = queryStr . replaceAll ( / \s + / g, ' ' ) ;
433
+ return queryStr ;
434
+ } ;
435
+
348
436
const addIntegration = async ( {
349
437
config,
350
438
integration,
@@ -375,22 +463,20 @@ const addIntegration = async ({
375
463
} else if ( config . connectionType === 's3' ) {
376
464
const http = coreRefs . http ! ;
377
465
378
- const assets = await http . get ( `${ INTEGRATIONS_BASE } /repository/${ integration . name } /assets` ) ;
466
+ const assets : { data : ParsedIntegrationAsset [ ] } = await http . get (
467
+ `${ INTEGRATIONS_BASE } /repository/${ integration . name } /assets`
468
+ ) ;
379
469
380
- // Queries must exist because we disable s3 if they're not present
381
470
for ( const query of assets . data . filter (
382
- ( a : ParsedIntegrationAsset ) : a is { type : 'query' ; query : string ; language : string } =>
471
+ ( a : ParsedIntegrationAsset ) : a is ParsedIntegrationAsset & { type : 'query' } =>
383
472
a . type === 'query'
384
473
) ) {
385
- let queryStr = ( query . query as string ) . replaceAll (
386
- '{table_name}' ,
387
- ` ${ config . connectionDataSource } .default. ${ config . connectionTableName } `
388
- ) ;
474
+ // Skip any queries that have conditional workflows but aren't enabled
475
+ if ( query . workflows && ! query . workflows . some ( ( w ) => config . enabledWorkflows . includes ( w ) ) ) {
476
+ continue ;
477
+ }
389
478
390
- queryStr = queryStr . replaceAll ( '{s3_bucket_location}' , config . connectionLocation ) ;
391
- queryStr = queryStr . replaceAll ( '{s3_checkpoint_location}' , config . checkpointLocation ) ;
392
- queryStr = queryStr . replaceAll ( '{object_name}' , config . connectionTableName ) ;
393
- queryStr = queryStr . replaceAll ( / \s + / g, ' ' ) ;
479
+ const queryStr = prepareQuery ( query . query , config ) ;
394
480
const result = await runQuery ( queryStr , config . connectionDataSource , sessionId ) ;
395
481
if ( ! result . ok ) {
396
482
setLoading ( false ) ;
@@ -400,15 +486,15 @@ const addIntegration = async ({
400
486
sessionId = result . value . sessionId ?? sessionId ;
401
487
}
402
488
// Once everything is ready, add the integration to the new datasource as usual
403
- // TODO determine actual values here after more about queries is known
404
489
const res = await addIntegrationRequest (
405
490
false ,
406
491
integration . name ,
407
492
config . displayName ,
408
493
integration ,
409
494
setCalloutLikeToast ,
410
495
config . displayName ,
411
- `flint_${ config . connectionDataSource } _default_${ config . connectionTableName } _mview`
496
+ `flint_${ config . connectionDataSource } _default_${ config . connectionTableName } _mview` ,
497
+ config . enabledWorkflows
412
498
) ;
413
499
if ( ! res ) {
414
500
setLoading ( false ) ;
@@ -418,11 +504,14 @@ const addIntegration = async ({
418
504
}
419
505
} ;
420
506
421
- const isConfigValid = ( config : IntegrationSetupInputs ) : boolean => {
507
+ const isConfigValid = ( config : IntegrationSetupInputs , integration : IntegrationConfig ) : boolean => {
422
508
if ( config . displayName . length < 1 || config . connectionDataSource . length < 1 ) {
423
509
return false ;
424
510
}
425
511
if ( config . connectionType === 's3' ) {
512
+ if ( integration . workflows && config . enabledWorkflows . length < 1 ) {
513
+ return false ;
514
+ }
426
515
return (
427
516
config . connectionLocation . startsWith ( 's3://' ) && config . checkpointLocation . startsWith ( 's3://' )
428
517
) ;
@@ -477,7 +566,7 @@ export function SetupBottomBar({
477
566
iconType = "arrowRight"
478
567
iconSide = "right"
479
568
isLoading = { loading }
480
- disabled = { ! isConfigValid ( config ) }
569
+ disabled = { ! isConfigValid ( config , integration ) }
481
570
onClick = { async ( ) =>
482
571
addIntegration ( { integration, config, setLoading, setCalloutLikeToast } )
483
572
}
@@ -511,6 +600,7 @@ export function SetupIntegrationPage({ integration }: { integration: string }) {
511
600
connectionLocation : '' ,
512
601
checkpointLocation : '' ,
513
602
connectionTableName : integration ,
603
+ enabledWorkflows : [ ] ,
514
604
} ) ;
515
605
516
606
const [ template , setTemplate ] = useState ( {
0 commit comments