diff --git a/src/js/components/containerImages/ContainerImagePrepareParameterForm.js b/src/js/components/containerImages/ContainerImagePrepareParameterForm.js
new file mode 100644
index 00000000..718252dd
--- /dev/null
+++ b/src/js/components/containerImages/ContainerImagePrepareParameterForm.js
@@ -0,0 +1,111 @@
+/**
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import PropTypes from 'prop-types';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import { injectIntl, defineMessages } from 'react-intl';
+import { reduxForm, Field, SubmissionError } from 'redux-form';
+import { Form, Wizard } from 'patternfly-react';
+import yaml from 'js-yaml';
+
+import { OverlayLoader } from '../ui/Loader';
+import ModalFormErrorList from '../ui/forms/ModalFormErrorList';
+import AceEditorInput from '../ui/reduxForm/AceEditorInput';
+import { updateParameters } from '../../actions/ParametersActions';
+
+const messages = defineMessages({
+ updatingConfiguration: {
+ id: 'ContainerImagePrepareParameterForm.updatingConfiguration',
+ defaultMessage: 'Updating configuration...'
+ },
+ yamlSyntaxError: {
+ id: 'ContainerImagePrepareParameterForm.yamlSyntaxError',
+ defaultMessage: 'Invalid Yaml Syntax:'
+ }
+});
+
+const ContainerImagePrepareParameterForm = ({
+ currentPlanName,
+ error,
+ handleSubmit,
+ intl: { formatMessage },
+ parameter,
+ submitting
+}) => (
+
+);
+ContainerImagePrepareParameterForm.propTypes = {
+ currentPlanName: PropTypes.string.isRequired,
+ error: PropTypes.object,
+ handleSubmit: PropTypes.func.isRequired,
+ intl: PropTypes.object.isRequired,
+ parameter: ImmutablePropTypes.record.isRequired,
+ submitting: PropTypes.bool.isRequired
+};
+
+const form = reduxForm({
+ form: 'parametersForm',
+ onSubmit: (
+ { ContainerImagePrepare },
+ dispatch,
+ { currentPlanName, intl: { formatMessage } }
+ ) => {
+ try {
+ ContainerImagePrepare = yaml.safeLoad(ContainerImagePrepare, {
+ json: true
+ });
+ dispatch(updateParameters(currentPlanName, { ContainerImagePrepare }));
+ } catch (e) {
+ return Promise.reject(
+ new SubmissionError({
+ _error: {
+ title: formatMessage(messages.yamlSyntaxError),
+ message: e.message
+ }
+ })
+ );
+ }
+ },
+ validate: ({ ContainerImagePrepare }) => {
+ try {
+ yaml.safeLoad(ContainerImagePrepare, { json: true });
+ return {};
+ } catch (e) {
+ return { ContainerImagePrepare: e.message };
+ }
+ }
+});
+
+export default injectIntl(form(ContainerImagePrepareParameterForm));
diff --git a/src/js/components/containerImages/ContainerImagePrepareParameterFormActions.js b/src/js/components/containerImages/ContainerImagePrepareParameterFormActions.js
new file mode 100644
index 00000000..d17d6aab
--- /dev/null
+++ b/src/js/components/containerImages/ContainerImagePrepareParameterFormActions.js
@@ -0,0 +1,88 @@
+/**
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { Fragment } from 'react';
+import { connect } from 'react-redux';
+import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
+import PropTypes from 'prop-types';
+import { Icon, Button } from 'patternfly-react';
+import { submit, isSubmitting, isPristine, isInvalid } from 'redux-form';
+
+import { CloseModalButton } from '../ui/Modals';
+
+const messages = defineMessages({
+ back: {
+ id: 'ContainerImagePrepareParameterFormActions.back',
+ defaultMessage: 'Back'
+ },
+ save: {
+ id: 'ContainerImagePrepareParameterFormActions.save',
+ defaultMessage: 'Save Changes'
+ },
+ close: {
+ id: 'ContainerImagePrepareParameterFormActions.close',
+ defaultMessage: 'Close'
+ }
+});
+
+const ContainerImagePrepareParameterFormActions = ({
+ goBack,
+ isSubmitting,
+ isInvalid,
+ isPristine,
+ submitForm
+}) => (
+
+
+
+
+
+
+
+);
+ContainerImagePrepareParameterFormActions.propTypes = {
+ goBack: PropTypes.func.isRequired,
+ intl: PropTypes.object.isRequired,
+ isInvalid: PropTypes.bool.isRequired,
+ isPristine: PropTypes.bool.isRequired,
+ isSubmitting: PropTypes.bool.isRequired,
+ submitForm: PropTypes.func.isRequired
+};
+
+const mapStateToProps = state => ({
+ isSubmitting: isSubmitting('parametersForm')(state),
+ isPristine: isPristine('parametersForm')(state),
+ isInvalid: isInvalid('parametersForm')(state)
+});
+
+const mapDispatchToProps = dispatch => ({
+ submitForm: () => dispatch(submit('parametersForm'))
+});
+
+export default injectIntl(
+ connect(mapStateToProps, mapDispatchToProps)(
+ ContainerImagePrepareParameterFormActions
+ )
+);
diff --git a/src/js/components/containerImages/ContainerImagesPrepareFormActions.js b/src/js/components/containerImages/ContainerImagesPrepareFormActions.js
index ab25d7da..8a8ecbd1 100644
--- a/src/js/components/containerImages/ContainerImagesPrepareFormActions.js
+++ b/src/js/components/containerImages/ContainerImagesPrepareFormActions.js
@@ -21,11 +21,20 @@ import PropTypes from 'prop-types';
import { Icon, Button } from 'patternfly-react';
import { submit, isSubmitting, isPristine, isInvalid } from 'redux-form';
+import { CloseModalButton } from '../ui/Modals';
import { startContainerImagesPrepare } from '../../actions/ContainerImagesActions';
const messages = defineMessages({
+ cancel: {
+ id: 'ContainerImagesWizard.cancel',
+ defaultMessage: 'Cancel'
+ },
+ save: {
+ id: 'ContainerImagesPrepareFormActions.save',
+ defaultMessage: 'Save Changes'
+ },
next: {
- id: 'ContainerImagesWizard.next',
+ id: 'ContainerImagesPrepareFormActions.next',
defaultMessage: 'Next'
},
reset: {
@@ -35,38 +44,44 @@ const messages = defineMessages({
});
const ContainerImagesPrepareFormActions = ({
+ goForward,
isSubmitting,
isInvalid,
isPristine,
resetToDefaults,
- submitImagesPrepareForm
+ submitForm
}) => (
+
+
+
+
);
ContainerImagesPrepareFormActions.propTypes = {
+ goForward: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
- isFetchingParameters: PropTypes.bool.isRequired,
isInvalid: PropTypes.bool.isRequired,
isPristine: PropTypes.bool.isRequired,
isSubmitting: PropTypes.bool.isRequired,
resetToDefaults: PropTypes.func.isRequired,
- submitImagesPrepareForm: PropTypes.func.isRequired
+ submitForm: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
- isFetchingParameters: state.parameters.isFetching,
isSubmitting: isSubmitting('containerImagesPrepareForm')(state),
isPristine: isPristine('containerImagesPrepareForm')(state),
isInvalid: isInvalid('containerImagesPrepareForm')(state)
@@ -74,7 +89,7 @@ const mapStateToProps = state => ({
const mapDispatchToProps = dispatch => ({
resetToDefaults: () => dispatch(startContainerImagesPrepare({})),
- submitImagesPrepareForm: () => dispatch(submit('containerImagesPrepareForm'))
+ submitForm: () => dispatch(submit('containerImagesPrepareForm'))
});
export default injectIntl(
diff --git a/src/js/components/containerImages/ContainerImagesWizard.js b/src/js/components/containerImages/ContainerImagesWizard.js
index efcab469..ac98fa38 100644
--- a/src/js/components/containerImages/ContainerImagesWizard.js
+++ b/src/js/components/containerImages/ContainerImagesWizard.js
@@ -14,43 +14,30 @@
* under the License.
*/
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
import { connect } from 'react-redux';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import PropTypes from 'prop-types';
-import { Wizard, Modal, Icon, Button } from 'patternfly-react';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import { Wizard, Modal } from 'patternfly-react';
+import yaml from 'js-yaml';
import { checkRunningDeployment } from '../utils/checkRunningDeploymentHOC';
import { getCurrentPlanName } from '../../selectors/plans';
import { Loader } from '../ui/Loader';
import { fetchParameters } from '../../actions/ParametersActions';
import { startContainerImagesPrepare } from '../../actions/ContainerImagesActions';
-import {
- RoutedWizard,
- CloseModalXButton,
- CloseModalButton
-} from '../ui/Modals';
+import { RoutedWizard, CloseModalXButton } from '../ui/Modals';
import ContainerImagesPrepareForm from './ContainerImagesPrepareForm';
-import { getContainerImagePrepareParameterSeed } from '../../selectors/parameters';
+import {
+ getContainerImagePrepareParameterSeed,
+ getContainerImagePrepareParameter
+} from '../../selectors/parameters';
import ContainerImagesPrepareFormActions from './ContainerImagesPrepareFormActions';
+import ContainerImagePrepareParameterForm from './ContainerImagePrepareParameterForm';
+import ContainerImagePrepareParameterFormActions from './ContainerImagePrepareParameterFormActions';
const messages = defineMessages({
- close: {
- id: 'ContainerImagesWizard.close',
- defaultMessage: 'Close'
- },
- cancel: {
- id: 'ContainerImagesWizard.cancel',
- defaultMessage: 'Cancel'
- },
- back: {
- id: 'ContainerImagesWizard.back',
- defaultMessage: 'Back'
- },
- save: {
- id: 'ContainerImagesWizard.save',
- defaultMessage: 'Save Changes'
- },
title: {
id: 'ContainerImagesWizard.title',
defaultMessage: 'Prepare Container Images'
@@ -93,6 +80,7 @@ class ContainerImagesWizard extends Component {
intl: { formatMessage },
isFetchingParameters,
containerImagePrepareParameterSeed,
+ containerImagePrepareParameter,
resetToDefaults
} = this.props;
@@ -152,31 +140,28 @@ class ContainerImagesWizard extends Component {
resetToDefaults={resetToDefaults}
/>
) : (
-
parameter form here
+
)}
-
-
-
- {activeStepIndex === 0 && }
+ {activeStepIndex === 0 && (
+ this.setActiveStepIndex(1)}
+ />
+ )}
{activeStepIndex === 1 && (
-
-
-
-
-
-
-
+ this.setActiveStepIndex(0)}
+ />
)}
@@ -184,6 +169,7 @@ class ContainerImagesWizard extends Component {
}
}
ContainerImagesWizard.propTypes = {
+ containerImagePrepareParameter: ImmutablePropTypes.record.isRequired,
containerImagePrepareParameterSeed: PropTypes.object.isRequired,
currentPlanName: PropTypes.string.isRequired,
fetchParameters: PropTypes.func.isRequired,
@@ -196,6 +182,7 @@ const mapStateToProps = state => ({
containerImagePrepareParameterSeed: getContainerImagePrepareParameterSeed(
state
),
+ containerImagePrepareParameter: getContainerImagePrepareParameter(state),
currentPlanName: getCurrentPlanName(state),
isFetchingParameters: state.parameters.isFetching
});
diff --git a/src/js/components/ui/reduxForm/AceEditorInput.js b/src/js/components/ui/reduxForm/AceEditorInput.js
new file mode 100644
index 00000000..627bca21
--- /dev/null
+++ b/src/js/components/ui/reduxForm/AceEditorInput.js
@@ -0,0 +1,51 @@
+/**
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { Fragment } from 'react';
+import PropTypes from 'prop-types';
+import AceEditor from 'react-ace';
+import 'brace/theme/textmate';
+import 'brace/mode/yaml';
+
+import AceEditorInputToolbar from './AceEditorInputToolbar';
+
+const aceOnBlur = onBlur => (_event, editor) => {
+ const value = editor && editor.getValue();
+ onBlur(value);
+};
+
+const AceEditorInput = ({ input, meta, description, ...rest }) => (
+
+
+
+
+);
+AceEditorInput.propTypes = {
+ description: PropTypes.string.isRequired,
+ input: PropTypes.object.isRequired,
+ meta: PropTypes.object.isRequired,
+ mode: PropTypes.string.isRequired,
+ theme: PropTypes.string.isRequired
+};
+AceEditorInput.defaultProps = {
+ theme: 'textmate',
+ mode: 'yaml',
+ tabSize: 2,
+ enableBasicAutocompletion: false,
+ editorProps: { $blockScrolling: true }
+};
+
+export default AceEditorInput;
diff --git a/src/js/components/ui/reduxForm/AceEditorInputToolbar.js b/src/js/components/ui/reduxForm/AceEditorInputToolbar.js
new file mode 100644
index 00000000..7c4cd6f6
--- /dev/null
+++ b/src/js/components/ui/reduxForm/AceEditorInputToolbar.js
@@ -0,0 +1,56 @@
+/**
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { Fragment } from 'react';
+import PropTypes from 'prop-types';
+import { Icon } from 'patternfly-react';
+
+const AceEditorInputToolbar = ({
+ valid,
+ invalid,
+ warning,
+ error,
+ description
+}) => (
+
+);
+AceEditorInputToolbar.propTypes = {
+ description: PropTypes.string,
+ error: PropTypes.string,
+ invalid: PropTypes.bool.isRequired,
+ valid: PropTypes.bool.isRequired,
+ warning: PropTypes.string
+};
+
+export default AceEditorInputToolbar;
diff --git a/src/less/base.less b/src/less/base.less
index 754d1a3b..19a14cf3 100644
--- a/src/less/base.less
+++ b/src/less/base.less
@@ -163,6 +163,7 @@
@import "ui/Sidebar";
@import "ui/Toolbar";
@import "ui/Tooltips";
+@import "ui/AceEditorToolbar";
@import "components/Breadcrumbs";
@import "components/MainContent";
@import "components/EnvironmentConfiguration";
diff --git a/src/less/components/Loader.less b/src/less/components/Loader.less
index 8c986c57..89d25926 100644
--- a/src/less/components/Loader.less
+++ b/src/less/components/Loader.less
@@ -25,6 +25,7 @@
display: flex;
flex-direction: column;
justify-content: center;
+ z-index: 100;
&.card-loader {
box-sizing: content-box;
diff --git a/src/less/ui/AceEditorToolbar.less b/src/less/ui/AceEditorToolbar.less
new file mode 100644
index 00000000..3e773e48
--- /dev/null
+++ b/src/less/ui/AceEditorToolbar.less
@@ -0,0 +1,23 @@
+/**
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+.ace-editor-toolbar {
+ background: #f0f0f0;
+ color: #333;
+ border-top: 1px solid #e8e8e8;
+ padding: 3px 5px;
+ min-height: 24px;
+}
\ No newline at end of file