diff --git a/src/components/Pipelines/VariableForm/VariableForm.js b/src/components/Pipelines/VariableForm/VariableForm.js
index 1b3365e54..77074912c 100644
--- a/src/components/Pipelines/VariableForm/VariableForm.js
+++ b/src/components/Pipelines/VariableForm/VariableForm.js
@@ -11,7 +11,7 @@ import Button, { TheButtonGroup } from '../../widgets/TheButton';
import Callout from '../../widgets/Callout';
import SubmitButton from '../../forms/SubmitButton';
import { CloseIcon, SaveIcon, RefreshIcon } from '../../../components/icons';
-import { isArrayType } from '../../../helpers/pipelines';
+import { KNOWN_DATA_TYPES, isArrayType } from '../../../helpers/pipelines';
export const newVariableInitialData = {
name: '',
@@ -21,10 +21,7 @@ export const newVariableInitialData = {
external: false,
};
-const variableTypeOptions = ['file', 'remote-file', 'string']
- .reduce((acc, type) => [...acc, type, type + '[]'], [])
- .sort()
- .map(type => ({ key: type, name: type }));
+const variableTypeOptions = KNOWN_DATA_TYPES.map(type => ({ key: type, name: type }));
class VariableForm extends Component {
render() {
diff --git a/src/containers/PipelineEditContainer/PipelineEditContainer.js b/src/containers/PipelineEditContainer/PipelineEditContainer.js
index 57ecd5bf6..b2a043b51 100644
--- a/src/containers/PipelineEditContainer/PipelineEditContainer.js
+++ b/src/containers/PipelineEditContainer/PipelineEditContainer.js
@@ -11,10 +11,9 @@ import VariablesTable from '../../components/Pipelines/VariablesTable';
import VariableForm, { newVariableInitialData } from '../../components/Pipelines/VariableForm';
import BoxForm, { newBoxInitialData } from '../../components/Pipelines/BoxForm';
import Button, { TheButtonGroup } from '../../components/widgets/TheButton';
+import Callout from '../../components/widgets/Callout';
import Icon, { RefreshIcon, SaveIcon, UndoIcon, RedoIcon } from '../../components/icons';
-import { fetchSupplementaryFilesForPipeline } from '../../redux/modules/pipelineFiles';
-
import {
getVariablesUtilization,
isArrayType,
@@ -23,12 +22,18 @@ import {
getReferenceIdentifier,
makeExternalReference,
getVariablesTypes,
+ validatePipeline,
} from '../../helpers/pipelines';
import { getBoxTypes } from '../../redux/selectors/boxes';
import { objectMap, arrayToObject, encodeId, deepCompare, identity } from '../../helpers/common';
import styles from '../../components/Pipelines/styles.less';
+const getFormattedErrorAsKey = element => {
+ const values = element.props.values ? { ...element.props.values } : {};
+ delete values.code;
+ return `${element.props.id}-${Object.values(values).join('_')}`;
+};
// TODO
/*
@@ -90,6 +95,8 @@ class PipelineEditContainer extends Component {
version: null,
boxes: null,
variables: null,
+ boxTypes: null,
+ errors: [],
history: [],
future: [],
...STATE_DEFAULTS,
@@ -97,17 +104,32 @@ class PipelineEditContainer extends Component {
static getDerivedStateFromProps(nextProps, prevState) {
if (prevState.pipelineId !== nextProps.pipeline.id) {
+ // pipeline was changed whilst component was kept mounted => complete reload
return {
pipelineId: nextProps.pipeline.id,
version: nextProps.pipeline.version,
boxes: nextProps.pipeline.pipeline.boxes,
variables: nextProps.pipeline.pipeline.variables,
+ boxTypes: nextProps.boxTypes,
+ errors: validatePipeline(
+ nextProps.pipeline.pipeline.boxes,
+ nextProps.pipeline.pipeline.variables,
+ nextProps.boxTypes
+ ),
history: [],
future: [],
...STATE_DEFAULTS,
};
}
+ if (prevState.boxTypes !== nextProps.boxTypes) {
+ // boxTypes changed (probably get loaded) -> revalidate
+ return {
+ boxTypes: nextProps.boxTypes,
+ errors: validatePipeline(prevState.boxes, prevState.variables, nextProps.boxTypes),
+ };
+ }
+
if (prevState.version < nextProps.pipeline.version) {
// TODO -- deal with mergin issues
return { version: nextProps.pipeline.version };
@@ -126,6 +148,11 @@ class PipelineEditContainer extends Component {
this.setState({
...restore,
+ errors: validatePipeline(
+ restore.boxes || this.state.boxes,
+ restore.variables || this.state.variables,
+ this.props.boxTypes
+ ),
history,
future: [snapshot, ...this.state.future],
selectedBoxVariables: _getSelectedBoxVariables(this.state.selectedBox, restore.boxes || this.state.boxes),
@@ -143,6 +170,11 @@ class PipelineEditContainer extends Component {
this.setState({
...restore,
+ errors: validatePipeline(
+ restore.boxes || this.state.boxes,
+ restore.variables || this.state.variables,
+ this.props.boxTypes
+ ),
history: [snapshot, ...this.state.history],
future,
selectedBoxVariables: _getSelectedBoxVariables(this.state.selectedBox, restore.boxes || this.state.boxes),
@@ -163,6 +195,11 @@ class PipelineEditContainer extends Component {
version: this.props.pipeline.version,
boxes: this.props.pipeline.pipeline.boxes,
variables: this.props.pipeline.pipeline.variables,
+ errors: validatePipeline(
+ this.props.pipeline.pipeline.boxes,
+ this.props.pipeline.pipeline.variables,
+ this.props.boxTypes
+ ),
history: [],
future,
...STATE_DEFAULTS,
@@ -284,6 +321,11 @@ class PipelineEditContainer extends Component {
if (pipelineChanged) {
stateUpdate.history = [snapshot, ...this.state.history];
stateUpdate.future = [];
+ stateUpdate.errors = validatePipeline(
+ stateUpdate.boxes || this.state.boxes,
+ stateUpdate.variables || this.state.variables,
+ this.props.boxTypes
+ );
}
// update (recompute) selections if necessary
@@ -461,6 +503,7 @@ class PipelineEditContainer extends Component {
}
unlimitedHeight
+ type={this.state.errors && this.state.errors.length > 0 ? 'danger' : 'light'}
footer={
@@ -490,7 +533,7 @@ class PipelineEditContainer extends Component {
-