@@ -11,10 +11,9 @@ import VariablesTable from '../../components/Pipelines/VariablesTable';
1111import VariableForm , { newVariableInitialData } from '../../components/Pipelines/VariableForm' ;
1212import BoxForm , { newBoxInitialData } from '../../components/Pipelines/BoxForm' ;
1313import Button , { TheButtonGroup } from '../../components/widgets/TheButton' ;
14+ import Callout from '../../components/widgets/Callout' ;
1415import Icon , { RefreshIcon , SaveIcon , UndoIcon , RedoIcon } from '../../components/icons' ;
1516
16- import { fetchSupplementaryFilesForPipeline } from '../../redux/modules/pipelineFiles' ;
17-
1817import {
1918 getVariablesUtilization ,
2019 isArrayType ,
@@ -23,12 +22,18 @@ import {
2322 getReferenceIdentifier ,
2423 makeExternalReference ,
2524 getVariablesTypes ,
25+ validatePipeline ,
2626} from '../../helpers/pipelines' ;
2727import { getBoxTypes } from '../../redux/selectors/boxes' ;
2828import { objectMap , arrayToObject , encodeId , deepCompare , identity } from '../../helpers/common' ;
2929
3030import styles from '../../components/Pipelines/styles.less' ;
3131
32+ const getFormattedErrorAsKey = element => {
33+ const values = element . props . values ? { ...element . props . values } : { } ;
34+ delete values . code ;
35+ return `${ element . props . id } -${ Object . values ( values ) . join ( '_' ) } ` ;
36+ } ;
3237// TODO
3338
3439/*
@@ -90,24 +95,41 @@ class PipelineEditContainer extends Component {
9095 version : null ,
9196 boxes : null ,
9297 variables : null ,
98+ boxTypes : null ,
99+ errors : [ ] ,
93100 history : [ ] ,
94101 future : [ ] ,
95102 ...STATE_DEFAULTS ,
96103 } ;
97104
98105 static getDerivedStateFromProps ( nextProps , prevState ) {
99106 if ( prevState . pipelineId !== nextProps . pipeline . id ) {
107+ // pipeline was changed whilst component was kept mounted => complete reload
100108 return {
101109 pipelineId : nextProps . pipeline . id ,
102110 version : nextProps . pipeline . version ,
103111 boxes : nextProps . pipeline . pipeline . boxes ,
104112 variables : nextProps . pipeline . pipeline . variables ,
113+ boxTypes : nextProps . boxTypes ,
114+ errors : validatePipeline (
115+ nextProps . pipeline . pipeline . boxes ,
116+ nextProps . pipeline . pipeline . variables ,
117+ nextProps . boxTypes
118+ ) ,
105119 history : [ ] ,
106120 future : [ ] ,
107121 ...STATE_DEFAULTS ,
108122 } ;
109123 }
110124
125+ if ( prevState . boxTypes !== nextProps . boxTypes ) {
126+ // boxTypes changed (probably get loaded) -> revalidate
127+ return {
128+ boxTypes : nextProps . boxTypes ,
129+ errors : validatePipeline ( prevState . boxes , prevState . variables , nextProps . boxTypes ) ,
130+ } ;
131+ }
132+
111133 if ( prevState . version < nextProps . pipeline . version ) {
112134 // TODO -- deal with mergin issues
113135 return { version : nextProps . pipeline . version } ;
@@ -126,6 +148,11 @@ class PipelineEditContainer extends Component {
126148
127149 this . setState ( {
128150 ...restore ,
151+ errors : validatePipeline (
152+ restore . boxes || this . state . boxes ,
153+ restore . variables || this . state . variables ,
154+ this . props . boxTypes
155+ ) ,
129156 history,
130157 future : [ snapshot , ...this . state . future ] ,
131158 selectedBoxVariables : _getSelectedBoxVariables ( this . state . selectedBox , restore . boxes || this . state . boxes ) ,
@@ -143,6 +170,11 @@ class PipelineEditContainer extends Component {
143170
144171 this . setState ( {
145172 ...restore ,
173+ errors : validatePipeline (
174+ restore . boxes || this . state . boxes ,
175+ restore . variables || this . state . variables ,
176+ this . props . boxTypes
177+ ) ,
146178 history : [ snapshot , ...this . state . history ] ,
147179 future,
148180 selectedBoxVariables : _getSelectedBoxVariables ( this . state . selectedBox , restore . boxes || this . state . boxes ) ,
@@ -163,6 +195,11 @@ class PipelineEditContainer extends Component {
163195 version : this . props . pipeline . version ,
164196 boxes : this . props . pipeline . pipeline . boxes ,
165197 variables : this . props . pipeline . pipeline . variables ,
198+ errors : validatePipeline (
199+ this . props . pipeline . pipeline . boxes ,
200+ this . props . pipeline . pipeline . variables ,
201+ this . props . boxTypes
202+ ) ,
166203 history : [ ] ,
167204 future,
168205 ...STATE_DEFAULTS ,
@@ -284,6 +321,11 @@ class PipelineEditContainer extends Component {
284321 if ( pipelineChanged ) {
285322 stateUpdate . history = [ snapshot , ...this . state . history ] ;
286323 stateUpdate . future = [ ] ;
324+ stateUpdate . errors = validatePipeline (
325+ stateUpdate . boxes || this . state . boxes ,
326+ stateUpdate . variables || this . state . variables ,
327+ this . props . boxTypes
328+ ) ;
287329 }
288330
289331 // update (recompute) selections if necessary
@@ -461,6 +503,7 @@ class PipelineEditContainer extends Component {
461503 < Box
462504 title = { < FormattedMessage id = "app.pipelineEditContainer.title" defaultMessage = "Edit Pipeline Structure" /> }
463505 unlimitedHeight
506+ type = { this . state . errors && this . state . errors . length > 0 ? 'danger' : 'light' }
464507 footer = {
465508 < div className = "text-center" style = { { marginBottom : '-0.75rem' } } >
466509 < TheButtonGroup className = { styles . mainButtonGroup } >
@@ -490,7 +533,7 @@ class PipelineEditContainer extends Component {
490533 </ TheButtonGroup >
491534
492535 < TheButtonGroup className = { styles . mainButtonGroup } >
493- < Button variant = "success" >
536+ < Button variant = "success" disabled = { this . state . errors && this . state . errors . length > 0 } >
494537 < SaveIcon gapRight />
495538 < FormattedMessage id = "generic.save" defaultMessage = "Save" />
496539 </ Button >
@@ -537,6 +580,27 @@ class PipelineEditContainer extends Component {
537580 ) }
538581 </ Col >
539582 </ Row >
583+
584+ { this . state . errors && this . state . errors . length > 0 && (
585+ < Row >
586+ < Col xl = { 12 } >
587+ < Callout variant = "danger" >
588+ < h5 >
589+ < FormattedMessage
590+ id = "app.pipelineEditContainer.errorsCalloutTitle"
591+ defaultMessage = "The following errors were found in the pipeline"
592+ />
593+ :
594+ </ h5 >
595+ < ul >
596+ { this . state . errors . map ( error => (
597+ < li key = { getFormattedErrorAsKey ( error ) } > { error } </ li >
598+ ) ) }
599+ </ ul >
600+ </ Callout >
601+ </ Col >
602+ </ Row >
603+ ) }
540604 </ Container >
541605
542606 < BoxForm
@@ -579,12 +643,12 @@ PipelineEditContainer.propTypes = {
579643} ;
580644
581645export default connect (
582- ( state , { pipeline } ) => {
646+ state => {
583647 return {
584648 boxTypes : getBoxTypes ( state ) ,
585649 } ;
586650 } ,
587651 ( dispatch , { pipeline } ) => ( {
588- loadFiles : ( ) => dispatch ( fetchSupplementaryFilesForPipeline ( pipeline . id ) ) ,
652+ //
589653 } )
590654) ( PipelineEditContainer ) ;
0 commit comments