@@ -26,6 +26,9 @@ import { Link } from '@stackstorm/module-router';
2626import ActionReporter from '@stackstorm/module-action-reporter' ;
2727import AutoForm from '@stackstorm/module-auto-form' ;
2828import StringField from '@stackstorm/module-auto-form/fields/string' ;
29+ import EnumField from '@stackstorm/module-auto-form/fields/enum' ;
30+ import get from 'lodash/fp/get' ;
31+
2932import {
3033 FlexTable ,
3134 FlexTableRow ,
@@ -48,7 +51,6 @@ import {
4851} from '@stackstorm/module-panel' ;
4952import Time from '@stackstorm/module-time' ;
5053
51-
5254@connect ( ( state ) => {
5355 const { action, executions, entrypoint } = state ;
5456 return { action, executions, entrypoint } ;
@@ -64,14 +66,28 @@ export default class ActionsDetails extends React.Component {
6466 action : PropTypes . object ,
6567 executions : PropTypes . array ,
6668 entrypoint : PropTypes . string ,
69+ groups : PropTypes . array ,
70+ filter : PropTypes . string ,
71+ match : PropTypes . shape ( {
72+ params : PropTypes . shape ( {
73+ ref : PropTypes . string ,
74+ section : PropTypes . string ,
75+ } ) ,
76+ } ) ,
6777 }
6878
6979 state = {
7080 runPreview : false ,
7181 runValue : null ,
7282 runTrace : null ,
7383 executionsVisible : { } ,
74- isChecked :false ,
84+ openModel : false ,
85+ isChecked : false ,
86+ destinationPack :'' ,
87+ destinationAction :'' ,
88+ packs :[ ] ,
89+ isRemoveFiles : false ,
90+
7591 }
7692
7793 componentDidMount ( ) {
@@ -129,11 +145,29 @@ export default class ActionsDetails extends React.Component {
129145 }
130146 }
131147
132- componentDidUpdate ( prevProps ) {
133- const { id } = this . props ;
148+ UNSAFE_componentWillReceiveProps ( nextProps ) {
149+ const { groups, filter} = nextProps ;
150+ const packs = [ ] ;
151+ if ( ! filter ) {
152+ groups && groups . map ( data => {
153+ packs . push ( data . pack ) ;
154+ } ) ;
155+
156+ this . setState ( { packs : packs } ) ;
157+ }
158+ }
159+
160+ componentDidUpdate ( prevProps , prevState ) {
161+ const { id , filter} = this . props ;
162+
163+
134164 if ( id && id !== prevProps . id ) {
135165 this . fetchAction ( id ) ;
136166 }
167+
168+ if ( filter && filter !== prevProps . filter ) {
169+ this . setState ( { packs : prevState . packs } ) ;
170+ }
137171 }
138172
139173 componentWillUnmount ( ) {
@@ -254,6 +288,101 @@ export default class ActionsDetails extends React.Component {
254288 return this . props . handleRun ( ...args ) ;
255289 }
256290
291+ handleClone ( e , srcPack , srcAction , destAction , destPack , overwrite ) {
292+ e . preventDefault ( ) ;
293+ return store . dispatch ( {
294+ type : 'CLONE_ACTION' ,
295+ promise : api . request ( {
296+ method : 'post' ,
297+ path : `/actions/${ srcPack } .${ srcAction } /clone` ,
298+ } , {
299+ 'dest_pack' : destPack ,
300+ 'dest_action' : destAction ,
301+ 'overwrite' : overwrite ,
302+
303+ } )
304+ . then ( ( execution ) => {
305+ document . getElementById ( 'overlay' ) . style . display = 'none' ;
306+ notification . success ( `Action "${ srcAction } " has been cloned successfully.` ) ;
307+ this . getActions ( ) ;
308+ return execution ;
309+ } )
310+ . catch ( ( err ) => {
311+ if ( err . response ) {
312+ const error = document . getElementById ( 'error' ) ;
313+ error . textContent = err . response . data . faultstring ;
314+ error . style . color = 'red' ;
315+ }
316+ } ) ,
317+ } ) ;
318+ }
319+
320+ getActions ( ) {
321+ return store . dispatch ( {
322+ type : 'FETCH_GROUPS' ,
323+ promise : api . request ( {
324+ path : '/actions' ,
325+ query : {
326+ include_attributes : [
327+ 'ref' ,
328+ 'pack' ,
329+ 'name' ,
330+ 'description' ,
331+ 'runner_type' ,
332+ ] ,
333+ } ,
334+ } )
335+ . catch ( ( err ) => {
336+ notification . error ( 'Unable to retrieve actions.' , { err } ) ;
337+ throw err ;
338+ } ) ,
339+ } )
340+ . then ( ( ) => {
341+ const { id } = this . urlParams ;
342+ const { groups } = this . props ;
343+
344+ if ( id && groups && ! groups . some ( ( { actions } ) => actions . some ( ( { ref } ) => ref === id ) ) ) {
345+ this . navigate ( { id : false } ) ;
346+ }
347+ } )
348+ ;
349+ }
350+
351+ get urlParams ( ) {
352+ const {
353+ ref = get ( 'groups[0].actions[0].ref' , this . props ) ,
354+ section = 'general' ,
355+ } = this . props . match . params ;
356+
357+ return {
358+ id : ref ,
359+ section,
360+ } ;
361+ }
362+
363+ openModel ( e ) {
364+ const { action} = this . props ;
365+ const el = document . getElementById ( 'overlay' ) ;
366+ el . style . display = 'block' ;
367+ this . setState ( { destinationPack :action . pack , destinationAction :'' , isChecked : false } ) ;
368+ }
369+
370+ closeModel ( ) {
371+ document . getElementById ( 'overlay' ) . style . display = 'none' ;
372+ }
373+
374+ handleDropdown ( e ) {
375+ const error = document . getElementById ( 'error' ) ;
376+ error . textContent = '' ;
377+ this . setState ( { destinationPack :e } ) ;
378+ }
379+
380+ handleInput ( e ) {
381+ const error = document . getElementById ( 'error' ) ;
382+ error . textContent = '' ;
383+ this . setState ( { destinationAction :e } ) ;
384+ }
385+
257386 handleChange ( e ) {
258387 const isChecked = document . getElementById ( 'checkbox' ) . checked ;
259388 if ( isChecked ) {
@@ -264,28 +393,37 @@ export default class ActionsDetails extends React.Component {
264393 }
265394 }
266395
267- openModel ( e ) {
268- this . setState ( { isChecked : false } ) ;
269- const el = document . getElementById ( 'overlay' ) ;
396+ handleDeleteChange ( e ) {
397+ const isChecked = document . getElementById ( 'deletecheckbox' ) . checked ;
398+ if ( isChecked ) {
399+ this . setState ( { isRemoveFiles :true } ) ;
400+ }
401+ else {
402+ this . setState ( { isRemoveFiles :false } ) ;
403+ }
404+ }
405+
406+ openDeleteModel ( e ) {
407+ this . setState ( { isRemoveFiles : false } ) ;
408+ const el = document . getElementById ( 'delete' ) ;
270409 el . style . display = 'block' ;
271410 }
272411
273412 handleDelete ( e ) {
274413 e . preventDefault ( ) ;
275414 const { id } = this . props ;
276- const { isChecked } = this . state ;
277- document . getElementById ( 'overlay ' ) . style . display = 'none' ;
278- return this . props . handleDelete ( id , isChecked ) ;
415+ const { isRemoveFiles } = this . state ;
416+ document . getElementById ( 'delete ' ) . style . display = 'none' ;
417+ return this . props . handleDelete ( id , isRemoveFiles ) ;
279418 }
280419
281- closeModel ( ) {
282-
283- document . getElementById ( 'overlay' ) . style . display = 'none' ;
420+ closeDeleteModel ( ) {
421+ document . getElementById ( 'delete' ) . style . display = 'none' ;
284422 }
285-
286423
287424 render ( ) {
288- const { section, action, executions, entrypoint } = this . props ;
425+ const { section, action, executions, entrypoint} = this . props ;
426+
289427 if ( ! action ) {
290428 return null ;
291429 }
@@ -325,7 +463,8 @@ export default class ActionsDetails extends React.Component {
325463 />
326464 < Button flat value = "Preview" onClick = { ( ) => this . handleToggleRunPreview ( ) } />
327465 < DetailsToolbarSeparator />
328- < Button className = "st2-forms__button st2-details__toolbar-button" value = "Delete" onClick = { ( e ) => this . openModel ( e ) } />
466+ < Button disabled = { this . props . id !== action . ref } className = "st2-forms__button st2-details__toolbar-button" value = "Clone" onClick = { ( e ) => this . openModel ( e ) } />
467+ < Button className = "st2-forms__button st2-details__toolbar-button" value = "Delete" onClick = { ( e ) => this . openDeleteModel ( e ) } />
329468
330469 { action . runner_type === 'mistral-v2' || action . runner_type === 'orquesta' ? (
331470 < Link
@@ -425,15 +564,29 @@ export default class ActionsDetails extends React.Component {
425564 </ DetailsPanel >
426565 </ DetailsBody >
427566 ) : null }
567+
568+ { /* Written pop-up box code here */ }
569+ < div id = "overlay" className = "web_dialog_overlay" style = { { display : 'none' , position : 'fixed' , zIndex : '10' , left : '0' , top : '0' , width : '100%' , minHeight : '-webkit-fill-available' , overflow : 'auto' , backgroundColor : 'rgba(0,0,0,0.4)' } } >
570+ < div id = "dialog" className = "web_dialog" style = { { backgroundColor : '#fefefe' , margin : '15% auto' , padding : '20px' , border : '1px solid #888' , width : '28%' , height :'50%' } } >
571+ < EnumField name = "Destination Pack Name *" value = { this . state . destinationPack ? this . state . destinationPack : action . pack } spec = { { enum : this . state . packs } } onChange = { ( e ) => this . handleDropdown ( e ) } /> < br /> < br />
572+ < StringField style = { { height :'30%' } } name = "Destination Action Name *" value = { this . state . destinationAction } onChange = { ( e ) => this . handleInput ( e ) } required /> < br /> < br />
428573
574+ < input id = "checkbox" name = "checkbox" type = "checkbox" checked = { this . state . isChecked } value = { this . state . isChecked } onChange = { ( e ) => this . handleChange ( e ) } /> Overwrite < br /> < br /> < br />
575+ < span id = "error" /> < br /> < br />
576+ < div style = { { width :'100%' , display :'inline-block' } } >
577+ < button onClick = { ( e ) => this . handleClone ( e , action . pack , action . name , this . state . destinationAction , this . state . destinationPack , this . state . isChecked ) } type = "submit" className = "btn" style = { { backgroundColor : '#04AA6D' , color : 'white' , padding : '16px 20px' , border : 'none' , cursor : 'pointer' , width : '45%' , marginBottom :'10px' , opacity : '0.8' , float :'left' } } > Submit</ button >
578+ < button onClick = { ( e ) => this . closeModel ( e ) } type = "close" className = "btn cancel" style = { { backgroundColor : 'red' , color : 'white' , padding : '16px 20px' , border : 'none' , cursor : 'pointer' , width : '45%' , marginBottom :'10px' , opacity : '0.8' , float :'right' } } > Close</ button >
579+ </ div >
580+ </ div >
581+ </ div >
429582
430- < div id = "overlay " className = "web_dialog_overlay" style = { { display : 'none' , position : 'fixed' , zIndex : '10' , left : '0' , top : '0' , width : '100%' , minHeight : '-webkit-fill-available' , overflow : 'auto' , backgroundColor : 'rgba(0,0,0,0.4)' } } >
583+ < div id = "delete " className = "web_dialog_overlay" style = { { display : 'none' , position : 'fixed' , zIndex : '10' , left : '0' , top : '0' , width : '100%' , minHeight : '-webkit-fill-available' , overflow : 'auto' , backgroundColor : 'rgba(0,0,0,0.4)' } } >
431584 < div id = "dialog" className = "web_dialog" style = { { backgroundColor : '#fefefe' , margin : '15% auto' , padding : '20px' , border : '1px solid #888' , width : '24%' , height :'20%' } } >
432585 < p > You are about to delete the action. Are you sure? </ p >
433- < input id = "checkbox " name = "checkbox" type = "checkbox" checked = { this . state . isChecked } value = { this . state . isChecked } onChange = { ( e ) => this . handleChange ( e ) } /> Remove Files (This operation is irreversible.) < br /> < br /> < br />
586+ < input id = "deletecheckbox " name = "checkbox" type = "checkbox" checked = { this . state . isRemoveFiles } value = { this . state . isRemoveFiles } onChange = { ( e ) => this . handleDeleteChange ( e ) } /> Remove Files (This operation is irreversible.) < br /> < br /> < br />
434587 < div style = { { width :'100%' , display :'inline-block' } } >
435588 < button onClick = { ( e ) => this . handleDelete ( e ) } type = "submit" className = "btn" style = { { backgroundColor : '#04AA6D' , color : 'white' , padding : '16px 20px' , border : 'none' , cursor : 'pointer' , width : '45%' , marginBottom :'10px' , opacity : '0.8' , float :'left' } } > Submit</ button >
436- < button onClick = { ( e ) => this . closeModel ( e ) } type = "close" className = "btn cancel" style = { { backgroundColor : 'red' , color : 'white' , padding : '16px 20px' , border : 'none' , cursor : 'pointer' , width : '45%' , marginBottom :'10px' , opacity : '0.8' , float :'right' } } > Close</ button >
589+ < button onClick = { ( e ) => this . closeDeleteModel ( e ) } type = "close" className = "btn cancel" style = { { backgroundColor : 'red' , color : 'white' , padding : '16px 20px' , border : 'none' , cursor : 'pointer' , width : '45%' , marginBottom :'10px' , opacity : '0.8' , float :'right' } } > Close</ button >
437590 </ div >
438591 </ div >
439592 </ div >
0 commit comments