diff --git a/src/PresentationalComponents/CreateImageWizard/WizardStepImageOutput.js b/src/PresentationalComponents/CreateImageWizard/WizardStepImageOutput.js
new file mode 100644
index 00000000..7d43755b
--- /dev/null
+++ b/src/PresentationalComponents/CreateImageWizard/WizardStepImageOutput.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { Form, FormGroup, FormSelect, FormSelectOption, Title } from '@patternfly/react-core';
+
+const WizardStepImageOutput = (props) => {
+ const releaseOptions = [
+ { value: 'rhel-8', label: 'Red Hat Enterprise Linux (RHEL) 8.2' },
+ ];
+ const uploadOptions = [
+ { value: 'aws', label: 'Amazon Web Services' },
+ ];
+ return (
+
+ );
+};
+
+WizardStepImageOutput.propTypes = {
+ setRelease: PropTypes.func,
+ value: PropTypes.string,
+ upload: PropTypes.object,
+ setUpload: PropTypes.func,
+};
+
+export default WizardStepImageOutput;
diff --git a/src/PresentationalComponents/CreateImageWizard/WizardStepRegistration.js b/src/PresentationalComponents/CreateImageWizard/WizardStepRegistration.js
new file mode 100644
index 00000000..90791264
--- /dev/null
+++ b/src/PresentationalComponents/CreateImageWizard/WizardStepRegistration.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { Form, FormGroup, TextInput, Radio, Title } from '@patternfly/react-core';
+
+const WizardStepRegistration = (props) => {
+ return (
+
+ );
+};
+
+WizardStepRegistration.propTypes = {
+ setSubscription: PropTypes.func,
+ setSubscribeNow: PropTypes.func,
+ subscription: PropTypes.object,
+ subscribeNow: PropTypes.bool,
+ errors: PropTypes.object,
+};
+
+export default WizardStepRegistration;
diff --git a/src/PresentationalComponents/CreateImageWizard/WizardStepReview.js b/src/PresentationalComponents/CreateImageWizard/WizardStepReview.js
new file mode 100644
index 00000000..1f2e623f
--- /dev/null
+++ b/src/PresentationalComponents/CreateImageWizard/WizardStepReview.js
@@ -0,0 +1,95 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { Alert, TextContent, Title } from '@patternfly/react-core';
+import { ExclamationCircleIcon } from '@patternfly/react-icons';
+
+import './WizardStepReview.scss';
+
+const WizardStepReview = (props) => {
+ const releaseOptions = {
+ 'rhel-8': 'Red Hat Enterprise Linux (RHEL) 8.2'
+ };
+ const uploadOptions = {
+ aws: 'Amazon Web Services'
+ };
+ return (
+ <>
+ { (Object.keys(props.uploadErrors).length > 0 ||
+ Object.keys(props.subscriptionErrors).length > 0) &&
+ }
+ Create image
+
+
+ Review the information and click Create image
+ to create the image using the following criteria.
+
+ Image output
+
+ -
+ Release
+
+ -
+ { releaseOptions[props.release]}
+
+ -
+ Target environment
+
+ -
+ { props.upload && <>{ uploadOptions[props.upload.type] }> }
+
+
+ { Object.entries(props.uploadErrors).length > 0 && (
+ Upload to AWS
+ )}
+
+ { Object.entries(props.uploadErrors).map(([ key, error ]) => {
+ return (
+ -
+ { error.label }
+
+ -
+ { error.value }
+
+ );
+ })}
+
+ Registration
+
+ -
+ Subscription
+
+ { !props.subscribeNow &&
+ -
+ Register the system later
+
}
+ { props.subscribeNow &&
+ -
+ Register the system on first boot
+
}
+ { Object.entries(props.subscriptionErrors).map(([ key, error ]) => {
+ return (
+ -
+ { error.label }
+
+ -
+ { error.value }
+
+ );
+ })}
+
+
+ >
+ );
+};
+
+WizardStepReview.propTypes = {
+ release: PropTypes.string,
+ upload: PropTypes.object,
+ subscription: PropTypes.object,
+ subscribeNow: PropTypes.bool,
+ uploadErrors: PropTypes.object,
+ subscriptionErrors: PropTypes.object,
+};
+
+export default WizardStepReview;
diff --git a/src/PresentationalComponents/CreateImageWizard/WizardStepReview.scss b/src/PresentationalComponents/CreateImageWizard/WizardStepReview.scss
new file mode 100644
index 00000000..0aa26bb0
--- /dev/null
+++ b/src/PresentationalComponents/CreateImageWizard/WizardStepReview.scss
@@ -0,0 +1,17 @@
+.error {
+ color: var(--pf-global--danger-color--100);
+ }
+// Increasing margins for h3 for better spacing and readability
+.pf-c-content h3 {
+ margin-top: var(--pf-global--spacer--xl);
+ margin-bottom: var(--pf-global--spacer--md);
+}
+// Decreasing gap between dl items for better spacing and readability
+// Also setting a first column width to 25% instead of auto,
+// to guarantee the same width for each section.
+@media screen and (min-width: 576px) {
+ .pf-c-content dl {
+ grid-template: 1fr / 25% 1fr;
+ grid-gap: var(--pf-global--spacer--sm);
+ }
+}
\ No newline at end of file
diff --git a/src/PresentationalComponents/CreateImageWizard/WizardStepUploadAWS.js b/src/PresentationalComponents/CreateImageWizard/WizardStepUploadAWS.js
new file mode 100644
index 00000000..f74efbaf
--- /dev/null
+++ b/src/PresentationalComponents/CreateImageWizard/WizardStepUploadAWS.js
@@ -0,0 +1,63 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { Form, FormGroup, FormSelect, TextInput, FormSelectOption, Title } from '@patternfly/react-core';
+
+const WizardStepUploadAWS = (props) => {
+ const serviceOptions = [
+ { value: 'ec2', label: 'Amazon Elastic Compute Cloud (ec2)' },
+ { value: 's3', label: 'Amazon Simple Storage Service (s3)' },
+ ];
+
+ return (
+
+ );
+};
+
+WizardStepUploadAWS.propTypes = {
+ setUploadOptions: PropTypes.func,
+ upload: PropTypes.object,
+ errors: PropTypes.object,
+};
+
+export default WizardStepUploadAWS;
diff --git a/src/SmartComponents/CreateImageWizard/CreateImageWizard.js b/src/SmartComponents/CreateImageWizard/CreateImageWizard.js
index 581d6667..b524ab3e 100644
--- a/src/SmartComponents/CreateImageWizard/CreateImageWizard.js
+++ b/src/SmartComponents/CreateImageWizard/CreateImageWizard.js
@@ -5,249 +5,15 @@ import { connect } from 'react-redux';
import { actions } from '../redux';
import { PageHeader, PageHeaderTitle } from '@redhat-cloud-services/frontend-components';
-import {
- Alert,
- Flex,
- FlexItem,
- Form,
- FormGroup,
- FormSelect,
- FormSelectOption,
- Radio,
- TextContent,
- TextInput,
- Wizard,
-} from '@patternfly/react-core';
+import { Wizard } from '@patternfly/react-core';
-import { ExclamationCircleIcon } from '@patternfly/react-icons';
+import WizardStepImageOutput from '../../PresentationalComponents/CreateImageWizard/WizardStepImageOutput';
+import WizardStepUploadAWS from '../../PresentationalComponents/CreateImageWizard/WizardStepUploadAWS';
+import WizardStepRegistration from '../../PresentationalComponents/CreateImageWizard/WizardStepRegistration';
+import WizardStepReview from '../../PresentationalComponents/CreateImageWizard/WizardStepReview';
import api from './../../api.js';
-const ReleaseComponent = (props) => {
- const options = [
- { value: 'rhel-8', label: 'Red Hat Enterprise Linux (RHEL) 8.2' },
- ];
- return (
-
- );
-};
-
-ReleaseComponent.propTypes = {
- setRelease: PropTypes.func,
- value: PropTypes.string,
-};
-
-const AmazonUploadComponent = (props) => {
- const serviceOptions = [
- { value: 'ec2', label: 'Amazon Elastic Compute Cloud (ec2)' },
- { value: 's3', label: 'Amazon Simple Storage Service (s3)' },
- ];
-
- return (
- <>
-
- props.setUploadOptions(Object.assign(props.upload.options, { access_key_id: value })) } />
-
-
- props.setUploadOptions(Object.assign(props.upload.options, { secret_access_key: value })) } />
-
-
- props.setUploadOptions(Object.assign(props.upload.options, { service: value })) }>
- { serviceOptions.map(option => ) }
-
-
-
- props.setUploadOptions(Object.assign(props.upload.options, { region: value })) } />
-
- { props.upload.options.service === 's3' &&
-
- props.setUploadOptions(Object.assign(props.upload.options, { bucket: value })) } />
- }
- >
- );
-};
-
-AmazonUploadComponent.propTypes = {
- setUploadOptions: PropTypes.func,
- upload: PropTypes.object,
- errors: PropTypes.object,
-};
-
-const UploadComponent = (props) => {
- const uploadTypes = [
- { value: 'aws', label: 'Amazon Machine Image (.raw)' },
- ];
-
- return (
- <>
-
- >
- );
-};
-
-UploadComponent.propTypes = {
- setUpload: PropTypes.func,
- setUploadOptions: PropTypes.func,
- upload: PropTypes.object,
- errors: PropTypes.object,
-};
-
-const SubscriptionComponent = (props) => {
- return (
-
- );
-};
-
-SubscriptionComponent.propTypes = {
- setSubscription: PropTypes.func,
- setSubscribeNow: PropTypes.func,
- subscription: PropTypes.object,
- subscribeNow: PropTypes.bool,
- errors: PropTypes.object,
-};
-
-const ReviewComponent = (props) => {
- return (
- <>
- { (Object.keys(props.uploadErrors).length > 0 ||
- Object.keys(props.subscriptionErrors).length > 0) &&
- }
-
- Create image
-
- Review the information and click Create image
- to create the image using the following criteria.
-
- Release
-
-
- Release
-
-
- { props.release }
-
-
- Image output
-
-
- Destination
-
-
- { props.upload && <>{ props.upload.type }> }
-
-
- { Object.entries(props.uploadErrors).map(([ key, error ]) => {
- return (
-
- { error.label }
-
-
- { error.value }
-
- );
- })}
- Registration
-
-
- Subscription
-
- { !props.subscribeNow &&
-
- Register the system later
- }
- { props.subscribeNow &&
-
- Register the system on first boot
- }
-
- { Object.entries(props.subscriptionErrors).map(([ key, error ]) => {
- return (
-
- { error.label }
-
-
- { error.value }
-
- );
- })}
-
- >
- );
-};
-
-ReviewComponent.propTypes = {
- release: PropTypes.string,
- upload: PropTypes.object,
- subscription: PropTypes.object,
- subscribeNow: PropTypes.bool,
- uploadErrors: PropTypes.object,
- subscriptionErrors: PropTypes.object,
-};
-
class CreateImageWizard extends Component {
constructor(props) {
super(props);
@@ -283,7 +49,7 @@ class CreateImageWizard extends Component {
'base-url': 'https://cdn.redhat.com/',
insights: true
},
- subscribeNow: false,
+ subscribeNow: true,
/* errors take form of $fieldId: error */
uploadErrors: {},
subscriptionErrors: {},
@@ -431,22 +197,28 @@ class CreateImageWizard extends Component {
}
render() {
+ const StepImageOutput = {
+ name: 'Image output',
+ component:
+ };
+ const StepUploadAWS = {
+ name: 'Upload to AWS',
+ component:
+ };
+
const steps = [
- {
- name: 'Release',
- component: },
- {
- name: 'Target environment',
- component: },
+ StepImageOutput,
+ ...(this.state.upload.type === 'aws' ? [ StepUploadAWS ] : []),
{
name: 'Registration',
- component: },
{
name: 'Review',
- component: {
// left sidebar navigation
const sidebar = screen.getByRole('navigation');
- getByText(sidebar, 'Release');
- getByText(sidebar, 'Target environment');
+ getByText(sidebar, 'Image output');
getByText(sidebar, 'Registration');
getByText(sidebar, 'Review');
});
});
-describe('Step Release', () => {
+describe('Step Image output', () => {
beforeEach(() => {
const { _component, history } = renderWithReduxRouter();
historySpy = jest.spyOn(history, 'push');
// left sidebar navigation
const sidebar = screen.getByRole('navigation');
- const anchor = getByText(sidebar, 'Release');
+ const anchor = getByText(sidebar, 'Image output');
+ screen.getByTestId('upload-destination');
// load from sidebar
anchor.click();
});
- test('clicking Next loads Target environment', () => {
+ test('clicking Next loads Upload to AWS', () => {
const [ next, , ] = verifyButtons();
next.click();
- screen.getByText('Destination');
screen.getByText('Secret access key');
});
@@ -115,16 +114,22 @@ describe('Step Release', () => {
userEvent.selectOptions(release, [ 'rhel-8' ]);
});
+
+ test('target environment is required', () => {
+ const destination = screen.getByTestId('upload-destination');
+ expect(destination).toBeEnabled();
+ expect(destination).toBeRequired();
+ });
});
-describe('Step Target environment', () => {
+describe('Step Upload to AWS', () => {
beforeEach(() => {
const { _component, history } = renderWithReduxRouter();
historySpy = jest.spyOn(history, 'push');
// left sidebar navigation
const sidebar = screen.getByRole('navigation');
- const anchor = getByText(sidebar, 'Target environment');
+ const anchor = getByText(sidebar, 'Upload to AWS');
// load from sidebar
anchor.click();
@@ -153,10 +158,6 @@ describe('Step Target environment', () => {
// change the select to enable the bucket field
userEvent.selectOptions(screen.getByTestId('aws-service-select'), [ 's3' ]);
- const destination = screen.getByTestId('upload-destination');
- expect(destination).toBeEnabled();
- expect(destination).toBeRequired();
-
const accessKeyId = screen.getByTestId('aws-access-key');
expect(accessKeyId).toHaveValue('');
expect(accessKeyId).toBeEnabled();
@@ -182,10 +183,6 @@ describe('Step Target environment', () => {
// change the select to enable the bucket field
userEvent.selectOptions(screen.getByTestId('aws-service-select'), [ 's3' ]);
- const destination = screen.getByTestId('upload-destination');
- expect(destination).toBeEnabled();
- expect(destination).toBeRequired();
-
const accessKeyId = screen.getByTestId('aws-access-key');
expect(accessKeyId).toHaveValue('');
expect(accessKeyId).toBeEnabled();
@@ -229,11 +226,11 @@ describe('Step Registration', () => {
screen.getByText('Review the information and click Create image to create the image using the following criteria.');
});
- test('clicking Back loads Target environment', () => {
+ test('clicking Back loads Upload to AWS', () => {
const [ , back, ] = verifyButtons();
back.click();
- screen.getByText('Destination');
+ screen.getByText('Access key ID');
screen.getByText('Secret access key');
});
@@ -320,13 +317,13 @@ describe('Click through all steps', () => {
test('with valid values', async () => {
const next = screen.getByRole('button', { name: /Next/ });
- // select release
+ // select image output
userEvent.selectOptions(screen.getByTestId('release-select'), [ 'rhel-8' ]);
+ userEvent.selectOptions(screen.getByTestId('upload-destination'), [ 'aws' ]);
next.click();
// select upload target
- await screen.findByTestId('upload-destination');
- userEvent.selectOptions(screen.getByTestId('upload-destination'), [ 'aws' ]);
+ await screen.findByTestId('aws-access-key');
userEvent.type(screen.getByTestId('aws-access-key'), 'key');
userEvent.type(screen.getByTestId('aws-secret-access-key'), 'secret');
userEvent.selectOptions(screen.getByTestId('aws-service-select'), [ 's3' ]);
@@ -342,10 +339,10 @@ describe('Click through all steps', () => {
userEvent.type(screen.getByTestId('subscription-activation'), '1234567890');
next.click();
+ // review
await screen.
findByText('Review the information and click Create image to create the image using the following criteria.');
- await screen.findByText('rhel-8');
- await screen.findByText('aws');
+ await screen.findByText('Amazon Web Services');
await screen.findByText('Register the system on first boot');
// mock the backend API
@@ -369,11 +366,9 @@ describe('Click through all steps', () => {
// select release
userEvent.selectOptions(screen.getByTestId('release-select'), [ 'rhel-8' ]);
+ userEvent.selectOptions(screen.getByTestId('upload-destination'), [ 'aws' ]);
next.click();
- // select upload target
- await screen.findByTestId('upload-destination');
- userEvent.selectOptions(screen.getByTestId('upload-destination'), [ 'aws' ]);
// leave AWS access keys empty
userEvent.selectOptions(screen.getByTestId('aws-service-select'), [ 's3' ]);
userEvent.clear(screen.getByTestId('aws-region'));
@@ -389,8 +384,7 @@ describe('Click through all steps', () => {
await screen.
findByText('Review the information and click Create image to create the image using the following criteria.');
- await screen.findByText('rhel-8');
- await screen.findByText('aws');
+ await screen.findByText('Amazon Web Services');
await screen.findByText('Register the system on first boot');
const errorMessages = await screen.findAllByText('A value is required');