components: Moves wizard steps into separate files
Replaces the flex layout in Review step with more semantic `<dl>` elements. Be more compliant with designs.
This commit is contained in:
parent
31eef3b83e
commit
142674b43b
7 changed files with 311 additions and 282 deletions
|
|
@ -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 (
|
||||
<Form>
|
||||
<Title headingLevel="h2" size="xl">Image output</Title>
|
||||
<FormGroup isRequired label="Release" fieldId="release-select">
|
||||
<FormSelect value={ props.value } onChange={ value => props.setRelease(value) } isRequired
|
||||
aria-label="Select release input" id="release-select" data-testid="release-select">
|
||||
{ releaseOptions.map(option => <FormSelectOption key={ option.value } value={ option.value } label={ option.label } />) }
|
||||
</FormSelect>
|
||||
</FormGroup>
|
||||
<FormGroup isRequired label="Target environment" fieldId="upload-destination">
|
||||
<FormSelect value={ props.upload.type || '' } id="upload-destination"
|
||||
data-testid="upload-destination" isRequired
|
||||
onChange={ value => props.setUpload({ type: value, options: props.upload.options }) } aria-label="Select upload destination">
|
||||
{ uploadOptions.map(option => <FormSelectOption key={ option.value } value={ option.value } label={ option.label } />) }
|
||||
</FormSelect>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
WizardStepImageOutput.propTypes = {
|
||||
setRelease: PropTypes.func,
|
||||
value: PropTypes.string,
|
||||
upload: PropTypes.object,
|
||||
setUpload: PropTypes.func,
|
||||
};
|
||||
|
||||
export default WizardStepImageOutput;
|
||||
|
|
@ -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 (
|
||||
<Form>
|
||||
<Title headingLevel="h2" size="xl">Registration</Title>
|
||||
<FormGroup isRequired label="Register the system">
|
||||
<Radio name="subscribe-now-radio" isChecked={ props.subscribeNow } id="subscribe-now-radio"
|
||||
label="Embed an activation key and register systems on first boot"
|
||||
onChange={ () => props.setSubscribeNow(true) }
|
||||
data-testid="register-now-radio-button" />
|
||||
<Radio name="subscribe-later-radio" isChecked={ !props.subscribeNow }
|
||||
label="Register the system later" id="subscribe-later-radio"
|
||||
onChange={ () => props.setSubscribeNow(false) }
|
||||
data-testid="register-later-radio-button" />
|
||||
</FormGroup>
|
||||
{ props.subscribeNow &&
|
||||
<>
|
||||
<FormGroup label="Organization ID" fieldId="subscription-organization">
|
||||
<TextInput isDisabled value={ props.subscription.organization || '' } type="text"
|
||||
id="subscription-organization" aria-label="Subscription organization ID"
|
||||
data-testid="organization-id" />
|
||||
</FormGroup>
|
||||
<FormGroup isRequired label="Activation key" fieldId="subscription-activation"
|
||||
helperTextInvalid={ (props.errors['subscription-activation'] && props.errors['subscription-activation'].value) || '' }
|
||||
validated={ (props.errors['subscription-activation'] && 'error') || 'default' }>
|
||||
<TextInput value={ props.subscription['activation-key'] || '' } type="password"
|
||||
data-testid="subscription-activation" isRequired
|
||||
id="subscription-activation" aria-label="Subscription activation key"
|
||||
onChange={ value => props.setSubscription(Object.assign(props.subscription, { 'activation-key': value })) } />
|
||||
</FormGroup>
|
||||
</> }
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
WizardStepRegistration.propTypes = {
|
||||
setSubscription: PropTypes.func,
|
||||
setSubscribeNow: PropTypes.func,
|
||||
subscription: PropTypes.object,
|
||||
subscribeNow: PropTypes.bool,
|
||||
errors: PropTypes.object,
|
||||
};
|
||||
|
||||
export default WizardStepRegistration;
|
||||
|
|
@ -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) &&
|
||||
<Alert variant="danger" className="pf-u-mb-xl" isInline title="Required information is missing" /> }
|
||||
<Title headingLevel="h2" size="xl">Create image</Title>
|
||||
<TextContent>
|
||||
<small>
|
||||
Review the information and click Create image
|
||||
to create the image using the following criteria.
|
||||
</small>
|
||||
<h3>Image output</h3>
|
||||
<dl>
|
||||
<dt>
|
||||
Release
|
||||
</dt>
|
||||
<dd>
|
||||
{ releaseOptions[props.release]}
|
||||
</dd>
|
||||
<dt>
|
||||
Target environment
|
||||
</dt>
|
||||
<dd>
|
||||
{ props.upload && <>{ uploadOptions[props.upload.type] }</> }
|
||||
</dd>
|
||||
</dl>
|
||||
{ Object.entries(props.uploadErrors).length > 0 && (
|
||||
<h3>Upload to AWS</h3>
|
||||
)}
|
||||
<dl>
|
||||
{ Object.entries(props.uploadErrors).map(([ key, error ]) => {
|
||||
return (<React.Fragment key={ key }>
|
||||
<dt>
|
||||
{ error.label }
|
||||
</dt>
|
||||
<dd>
|
||||
<ExclamationCircleIcon className="error" /> { error.value }
|
||||
</dd>
|
||||
</React.Fragment>);
|
||||
})}
|
||||
</dl>
|
||||
<h3>Registration</h3>
|
||||
<dl>
|
||||
<dt>
|
||||
Subscription
|
||||
</dt>
|
||||
{ !props.subscribeNow &&
|
||||
<dd>
|
||||
Register the system later
|
||||
</dd> }
|
||||
{ props.subscribeNow &&
|
||||
<dd>
|
||||
Register the system on first boot
|
||||
</dd> }
|
||||
{ Object.entries(props.subscriptionErrors).map(([ key, error ]) => {
|
||||
return (<React.Fragment key={ key }>
|
||||
<dt>
|
||||
{ error.label }
|
||||
</dt>
|
||||
<dd>
|
||||
<ExclamationCircleIcon className="error" /> { error.value }
|
||||
</dd>
|
||||
</React.Fragment>);
|
||||
})}
|
||||
</dl>
|
||||
</TextContent>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
WizardStepReview.propTypes = {
|
||||
release: PropTypes.string,
|
||||
upload: PropTypes.object,
|
||||
subscription: PropTypes.object,
|
||||
subscribeNow: PropTypes.bool,
|
||||
uploadErrors: PropTypes.object,
|
||||
subscriptionErrors: PropTypes.object,
|
||||
};
|
||||
|
||||
export default WizardStepReview;
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 (
|
||||
<Form>
|
||||
<Title headingLevel="h2" size="xl">Upload to AWS</Title>
|
||||
<FormGroup isRequired label="Access key ID" fieldId="amazon-access-id"
|
||||
helperTextInvalid={ (props.errors['amazon-access-id'] && props.errors['amazon-access-id'].value) || '' }
|
||||
validated={ (props.errors['amazon-access-id'] && 'error') || 'default' }>
|
||||
<TextInput value={ props.upload.options.access_key_id || '' }
|
||||
type="text" aria-label="amazon access key ID" id="amazon-access-id"
|
||||
data-testid="aws-access-key" isRequired
|
||||
onChange={ value => props.setUploadOptions(Object.assign(props.upload.options, { access_key_id: value })) } />
|
||||
</FormGroup>
|
||||
<FormGroup isRequired label="Secret access key" fieldId="amazon-access-secret"
|
||||
helperTextInvalid={ (props.errors['amazon-access-secret'] && props.errors['amazon-access-secret'].value) || '' }
|
||||
validated={ (props.errors['amazon-access-secret'] && 'error') || 'default' }>
|
||||
<TextInput value={ props.upload.options.secret_access_key || '' }
|
||||
data-testid="aws-secret-access-key" isRequired
|
||||
type="password" aria-label="amazon secret access key" id="amazon-access-secret"
|
||||
onChange={ value => props.setUploadOptions(Object.assign(props.upload.options, { secret_access_key: value })) } />
|
||||
</FormGroup>
|
||||
<FormGroup isRequired label="Service" fieldId="amazon-service">
|
||||
<FormSelect value={ props.upload.options.service } aria-label="Select amazon service" id="amazon-service"
|
||||
data-testid="aws-service-select"
|
||||
onChange={ value => props.setUploadOptions(Object.assign(props.upload.options, { service: value })) }>
|
||||
{ serviceOptions.map(option => <FormSelectOption key={ option.value } value={ option.value } label={ option.label } />) }
|
||||
</FormSelect>
|
||||
</FormGroup>
|
||||
<FormGroup isRequired label="Region" fieldId="amazon-region"
|
||||
helperTextInvalid={ (props.errors['amazon-region'] && props.errors['amazon-region'].value) || '' }
|
||||
validated={ (props.errors['amazon-region'] && 'error') || 'default' }>
|
||||
<TextInput value={ props.upload.options.region } type="text" aria-label="amazon region" id="amazon-region"
|
||||
data-testid="aws-region" isRequired
|
||||
onChange={ value => props.setUploadOptions(Object.assign(props.upload.options, { region: value })) } />
|
||||
</FormGroup>
|
||||
{ props.upload.options.service === 's3' &&
|
||||
<FormGroup isRequired label="Bucket" fieldId="amazon-bucket"
|
||||
helperTextInvalid={ (props.errors['amazon-bucket'] && props.errors['amazon-bucket'].value) || '' }
|
||||
validated={ (props.errors['amazon-bucket'] && 'error') || 'default' }>
|
||||
<TextInput value={ props.upload.options.bucket || '' } type="text" aria-label="amazon bucket" id="amazon-bucket"
|
||||
data-testid="aws-bucket" isRequired
|
||||
onChange={ value => props.setUploadOptions(Object.assign(props.upload.options, { bucket: value })) } />
|
||||
</FormGroup> }
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
WizardStepUploadAWS.propTypes = {
|
||||
setUploadOptions: PropTypes.func,
|
||||
upload: PropTypes.object,
|
||||
errors: PropTypes.object,
|
||||
};
|
||||
|
||||
export default WizardStepUploadAWS;
|
||||
|
|
@ -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 (
|
||||
<Form isHorizontal>
|
||||
<FormGroup label="Release" fieldId="release-select">
|
||||
<FormSelect value={ props.value } onChange={ value => props.setRelease(value) }
|
||||
aria-label="Select release input" id="release-select" data-testid="release-select">
|
||||
{ options.map(option => <FormSelectOption key={ option.value } value={ option.value } label={ option.label } />) }
|
||||
</FormSelect>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<>
|
||||
<FormGroup isRequired label="Access key ID" fieldId="amazon-access-id"
|
||||
helperTextInvalid={ (props.errors['amazon-access-id'] && props.errors['amazon-access-id'].value) || '' }
|
||||
validated={ (props.errors['amazon-access-id'] && 'error') || 'default' }>
|
||||
<TextInput value={ props.upload.options.access_key_id || '' }
|
||||
type="text" aria-label="amazon access key ID" id="amazon-access-id"
|
||||
data-testid="aws-access-key" isRequired
|
||||
onChange={ value => props.setUploadOptions(Object.assign(props.upload.options, { access_key_id: value })) } />
|
||||
</FormGroup>
|
||||
<FormGroup isRequired label="Secret access key" fieldId="amazon-access-secret"
|
||||
helperTextInvalid={ (props.errors['amazon-access-secret'] && props.errors['amazon-access-secret'].value) || '' }
|
||||
validated={ (props.errors['amazon-access-secret'] && 'error') || 'default' }>
|
||||
<TextInput value={ props.upload.options.secret_access_key || '' }
|
||||
data-testid="aws-secret-access-key" isRequired
|
||||
type="password" aria-label="amazon secret access key" id="amazon-access-secret"
|
||||
onChange={ value => props.setUploadOptions(Object.assign(props.upload.options, { secret_access_key: value })) } />
|
||||
</FormGroup>
|
||||
<FormGroup isRequired label="Service" fieldId="amazon-service">
|
||||
<FormSelect value={ props.upload.options.service } aria-label="Select amazon service" id="amazon-service"
|
||||
data-testid="aws-service-select"
|
||||
onChange={ value => props.setUploadOptions(Object.assign(props.upload.options, { service: value })) }>
|
||||
{ serviceOptions.map(option => <FormSelectOption key={ option.value } value={ option.value } label={ option.label } />) }
|
||||
</FormSelect>
|
||||
</FormGroup>
|
||||
<FormGroup isRequired label="Region" fieldId="amazon-region"
|
||||
helperTextInvalid={ (props.errors['amazon-region'] && props.errors['amazon-region'].value) || '' }
|
||||
validated={ (props.errors['amazon-region'] && 'error') || 'default' }>
|
||||
<TextInput value={ props.upload.options.region } type="text" aria-label="amazon region" id="amazon-region"
|
||||
data-testid="aws-region" isRequired
|
||||
onChange={ value => props.setUploadOptions(Object.assign(props.upload.options, { region: value })) } />
|
||||
</FormGroup>
|
||||
{ props.upload.options.service === 's3' &&
|
||||
<FormGroup isRequired label="Bucket" fieldId="amazon-bucket"
|
||||
helperTextInvalid={ (props.errors['amazon-bucket'] && props.errors['amazon-bucket'].value) || '' }
|
||||
validated={ (props.errors['amazon-bucket'] && 'error') || 'default' }>
|
||||
<TextInput value={ props.upload.options.bucket || '' } type="text" aria-label="amazon bucket" id="amazon-bucket"
|
||||
data-testid="aws-bucket" isRequired
|
||||
onChange={ value => props.setUploadOptions(Object.assign(props.upload.options, { bucket: value })) } />
|
||||
</FormGroup> }
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
AmazonUploadComponent.propTypes = {
|
||||
setUploadOptions: PropTypes.func,
|
||||
upload: PropTypes.object,
|
||||
errors: PropTypes.object,
|
||||
};
|
||||
|
||||
const UploadComponent = (props) => {
|
||||
const uploadTypes = [
|
||||
{ value: 'aws', label: 'Amazon Machine Image (.raw)' },
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form isHorizontal>
|
||||
<FormGroup isRequired label="Destination" fieldId="upload-destination">
|
||||
<FormSelect value={ props.upload.type || '' } id="upload-destination"
|
||||
data-testid="upload-destination" isRequired
|
||||
onChange={ value => props.setUpload({ type: value, options: props.upload.options }) } aria-label="Select upload destination">
|
||||
{ uploadTypes.map(type => <FormSelectOption key={ type.value } value={ type.value } label={ type.label } />) }
|
||||
</FormSelect>
|
||||
</FormGroup>
|
||||
{ props.upload.type === 'aws' &&
|
||||
<AmazonUploadComponent upload={ props.upload } setUploadOptions={ props.setUploadOptions } errors={ props.errors } /> }
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
UploadComponent.propTypes = {
|
||||
setUpload: PropTypes.func,
|
||||
setUploadOptions: PropTypes.func,
|
||||
upload: PropTypes.object,
|
||||
errors: PropTypes.object,
|
||||
};
|
||||
|
||||
const SubscriptionComponent = (props) => {
|
||||
return (
|
||||
<Form>
|
||||
<FormGroup isRequired label="Register the system" fieldId="subscribe-radio">
|
||||
<Radio name="subscribe-radio" isChecked={ props.subscribeNow } id="subscribe-radio"
|
||||
label="Embed an activation key and register systems on first boot"
|
||||
onChange={ () => props.setSubscribeNow(true) }
|
||||
data-testid="register-now-radio-button" />
|
||||
<Radio name="subscribe-radio" isChecked={ !props.subscribeNow }
|
||||
label="Register the system later" id="subscribe-radio"
|
||||
onChange={ () => props.setSubscribeNow(false) }
|
||||
data-testid="register-later-radio-button" />
|
||||
</FormGroup>
|
||||
{ props.subscribeNow &&
|
||||
<>
|
||||
<FormGroup label="Organization ID" fieldId="subscription-organization">
|
||||
<TextInput isDisabled value={ props.subscription.organization || '' } type="text"
|
||||
id="subscription-organization" aria-label="Subscription organization ID"
|
||||
data-testid="organization-id" />
|
||||
</FormGroup>
|
||||
<FormGroup isRequired label="Activation key" fieldId="subscription-activation"
|
||||
helperTextInvalid={ (props.errors['subscription-activation'] && props.errors['subscription-activation'].value) || '' }
|
||||
validated={ (props.errors['subscription-activation'] && 'error') || 'default' }>
|
||||
<TextInput value={ props.subscription['activation-key'] || '' } type="password"
|
||||
data-testid="subscription-activation" isRequired
|
||||
id="subscription-activation" aria-label="Subscription activation key"
|
||||
onChange={ value => props.setSubscription(Object.assign(props.subscription, { 'activation-key': value })) } />
|
||||
</FormGroup>
|
||||
</> }
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
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) &&
|
||||
<Alert variant="danger" isInline title="Required information is missing" /> }
|
||||
<TextContent>
|
||||
<h2>Create image</h2>
|
||||
<small>
|
||||
Review the information and click Create image
|
||||
to create the image using the following criteria.
|
||||
</small>
|
||||
<h3>Release</h3>
|
||||
<Flex>
|
||||
<FlexItem flex={ { default: 'flex_1' } }>
|
||||
Release
|
||||
</FlexItem>
|
||||
<FlexItem flex={ { default: 'flex_2' } }>
|
||||
{ props.release }
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
<h3>Image output</h3>
|
||||
<Flex>
|
||||
<FlexItem flex={ { default: 'flex_1' } }>
|
||||
Destination
|
||||
</FlexItem>
|
||||
<FlexItem flex={ { default: 'flex_2' } }>
|
||||
{ props.upload && <>{ props.upload.type }</> }
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
{ Object.entries(props.uploadErrors).map(([ key, error ]) => {
|
||||
return (<Flex key={ key }>
|
||||
<FlexItem flex={ { default: 'flex_1' } }>
|
||||
{ error.label }
|
||||
</FlexItem>
|
||||
<FlexItem flex={ { default: 'flex_2' } }>
|
||||
<ExclamationCircleIcon className="error" /> { error.value }
|
||||
</FlexItem>
|
||||
</Flex>);
|
||||
})}
|
||||
<h3>Registration</h3>
|
||||
<Flex>
|
||||
<FlexItem flex={ { default: 'flex_1' } }>
|
||||
Subscription
|
||||
</FlexItem>
|
||||
{ !props.subscribeNow &&
|
||||
<FlexItem flex={ { default: 'flex_2' } }>
|
||||
Register the system later
|
||||
</FlexItem> }
|
||||
{ props.subscribeNow &&
|
||||
<FlexItem flex={ { default: 'flex_2' } }>
|
||||
Register the system on first boot
|
||||
</FlexItem> }
|
||||
</Flex>
|
||||
{ Object.entries(props.subscriptionErrors).map(([ key, error ]) => {
|
||||
return (<Flex key={ key }>
|
||||
<FlexItem flex={ { default: 'flex_1' } }>
|
||||
{ error.label }
|
||||
</FlexItem>
|
||||
<FlexItem flex={ { default: 'flex_2' } }>
|
||||
<ExclamationCircleIcon className="error" /> { error.value }
|
||||
</FlexItem>
|
||||
</Flex>);
|
||||
})}
|
||||
</TextContent>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
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: <WizardStepImageOutput
|
||||
value={ this.state.release }
|
||||
upload={ this.state.upload }
|
||||
setRelease={ this.setRelease }
|
||||
setUpload={ this.setUpload } />
|
||||
};
|
||||
const StepUploadAWS = {
|
||||
name: 'Upload to AWS',
|
||||
component: <WizardStepUploadAWS
|
||||
upload={ this.state.upload }
|
||||
setUploadOptions={ this.setUploadOptions }
|
||||
errors={ this.state.uploadErrors } />
|
||||
};
|
||||
|
||||
const steps = [
|
||||
{
|
||||
name: 'Release',
|
||||
component: <ReleaseComponent
|
||||
value={ this.state.release }
|
||||
setRelease={ this.setRelease } /> },
|
||||
{
|
||||
name: 'Target environment',
|
||||
component: <UploadComponent
|
||||
upload={ this.state.upload }
|
||||
setUpload={ this.setUpload }
|
||||
setUploadOptions={ this.setUploadOptions }
|
||||
errors={ this.state.uploadErrors } /> },
|
||||
StepImageOutput,
|
||||
...(this.state.upload.type === 'aws' ? [ StepUploadAWS ] : []),
|
||||
{
|
||||
name: 'Registration',
|
||||
component: <SubscriptionComponent
|
||||
component: <WizardStepRegistration
|
||||
subscription={ this.state.subscription }
|
||||
subscribeNow={ this.state.subscribeNow }
|
||||
setSubscription={ this.setSubscription }
|
||||
|
|
@ -454,7 +226,7 @@ class CreateImageWizard extends Component {
|
|||
errors={ this.state.subscriptionErrors } /> },
|
||||
{
|
||||
name: 'Review',
|
||||
component: <ReviewComponent
|
||||
component: <WizardStepReview
|
||||
release={ this.state.release }
|
||||
upload={ this.state.upload }
|
||||
subscription={ this.state.subscription }
|
||||
|
|
|
|||
|
|
@ -68,31 +68,30 @@ describe('Create Image Wizard', () => {
|
|||
// 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(<CreateImageWizard />);
|
||||
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(<CreateImageWizard />);
|
||||
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');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue