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
|
|
@ -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 }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue