Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
Add Advanced Options Step to Plan Wizard
Browse files Browse the repository at this point in the history
* Add VM/Playbook selection table
  * Custom reactabular formatters to enable dual selection columns
  * Extract some common helpers shared with VMStep table
* Make modifications to BootstrapSelect for this use case
* Confirm modal for case when a user selects a playbook, but does not
  select any VMs on which to run service
* Form data is reset if user navigates back from Advanced Options Step
  to the VM Selection Step
* Add schema validator for ServiceTemplateAnsiblePlaybook
  • Loading branch information
michaelkro committed Jul 24, 2018
1 parent 85699b7 commit bdd9431
Show file tree
Hide file tree
Showing 35 changed files with 1,325 additions and 47 deletions.
9 changes: 9 additions & 0 deletions app/javascript/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import MappingWizardResultsStepContainer from '../react/screens/App/Overview/scr
import PlanWizardVMStepContainer from '../react/screens/App/Overview/screens/PlanWizard/components/PlanWizardVMStep';
import PlanWizardResultsStepContainer from '../react/screens/App/Overview/screens/PlanWizard/components/PlanWizardResultsStep';
import PlanWizardContainer from '../react/screens/App/Overview/screens/PlanWizard';
import PlanWizardAdvancedOptionsStepContainer from '../react/screens/App/Overview/screens/PlanWizard/components/PlanWizardAdvancedOptionsStep';

import OverviewContainer from '../react/screens/App/Overview';
import PlanContainer from '../react/screens/App/Plan';
Expand Down Expand Up @@ -84,6 +85,14 @@ export const coreComponents = [
},
store: true
},
{
name: 'PlanWizardAdvancedOptionsStepContainer',
type: PlanWizardAdvancedOptionsStepContainer,
data: {
fetchPlaybooksUrl: "/api/service_templates/?filter[]=type='ServiceTemplateAnsiblePlaybook'&expand=resources"
},
store: true
},
{
name: 'OverviewContainer',
type: OverviewContainer,
Expand Down
8 changes: 8 additions & 0 deletions app/javascript/data/models/serviceTemplateAnsiblePlaybook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { string, object } from 'yup';

export const playbookSchema = object().shape({
href: string().required(),
id: string().required(),
name: string().required(),
description: string().nullable()
});
6 changes: 6 additions & 0 deletions app/javascript/data/models/serviceTemplateAnsiblePlaybooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { array } from 'yup';
import { playbookSchema } from './serviceTemplateAnsiblePlaybook';

export const playbooksSchema = array()
.of(playbookSchema)
.nullable();
1 change: 1 addition & 0 deletions app/javascript/react/screens/App/Overview/Overview.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import './screens/MappingWizard/MappingWizard.scss';
@import './screens/PlanWizard/PlanWizard.scss';
@import './screens/PlanWizard/components/PlanWizardResultsStep/PlanWizardResultsStep.scss';
@import 'components/InfrastructureMappingsList/InfrastructureMappingsList.scss';
@import 'components/Migrations/Migrations.scss';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ class MappingWizardDatastoresStep extends React.Component {
choose_text={`<${__('Select a source cluster')}>`}
render_within_form="true"
form_name={form}
inline_label
labelWidth={6}
controlWidth={4}
/>
<Field
name="datastoresMappings"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ class MappingWizardNetworksStep extends React.Component {
choose_text={`<${__('Select a source cluster')}>`}
render_within_form="true"
form_name={form}
inline_label
labelWidth={6}
controlWidth={4}
/>
<Field
name="networksMappings"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,26 @@ import { createMigrationPlans } from './helpers';
import PlanWizardBody from './PlanWizardBody';
import { MIGRATIONS_FILTERS } from '../../OverviewConstants';

const planWizardSteps = ['planWizardGeneralStep', 'planWizardVMStep', 'planWizardOptionsStep', 'planWizardResultsStep'];
const planWizardSteps = [
'planWizardGeneralStep',
'planWizardVMStep',
'planWizardAdvancedOptionsStep',
'planWizardScheduleStep',
'planWizardResultsStep'
];

class PlanWizard extends React.Component {
state = { activeStepIndex: 0 };

prevStep = () => {
const { resetVmStepAction } = this.props;
const { resetVmStepAction, resetAdvancedOptionsStepAction } = this.props;
const { activeStepIndex } = this.state;

if (activeStepIndex === 1) {
// reset all vm step values if going back from that step
resetVmStepAction();
} else if (activeStepIndex === 2) {
resetAdvancedOptionsStepAction();
}
this.setState({ activeStepIndex: Math.max(activeStepIndex - 1, 0) });
};
Expand All @@ -26,10 +34,13 @@ class PlanWizard extends React.Component {
const {
planWizardGeneralStep,
planWizardVMStep,
planWizardOptionsStep,
planWizardAdvancedOptionsStep,
planWizardScheduleStep,
setPlansBodyAction,
setPlanScheduleAction,
setMigrationsFilterAction,
showConfirmModalAction,
hideConfirmModalAction,
showAlertAction,
hideAlertAction
} = this.props;
Expand All @@ -42,22 +53,48 @@ class PlanWizard extends React.Component {
hideAlertAction();
}

if (activeStepIndex === 2) {
const plansBody = createMigrationPlans(planWizardGeneralStep, planWizardVMStep);

setPlanScheduleAction(planWizardOptionsStep.values.migration_plan_choice_radio);
if (
activeStepIndex === 2 &&
((planWizardAdvancedOptionsStep.values.preMigrationPlaybook &&
planWizardAdvancedOptionsStep.values.playbookVms.preMigration.length === 0) ||
(planWizardAdvancedOptionsStep.values.postMigrationPlaybook &&
planWizardAdvancedOptionsStep.values.playbookVms.postMigration.length === 0))
) {
const onConfirm = () => {
this.setState({ activeStepIndex: 3 });
hideConfirmModalAction();
};

showConfirmModalAction({
title: __('No VMs Selected'),
body: __(
"You've selected a pre-migration or post-migration playbook service but no VMs on which to run the playbook service. Are you sure you want to continue?"
),
icon: <Icon className="confirm-warning-icon" type="pf" name="warning-triangle-o" />,
confirmButtonLabel: __('Continue'),
dialogClassName: 'plan-wizard-confirm-modal',
backdropClassName: 'plan-wizard-confirm-backdrop',
onConfirm
});
} else if (activeStepIndex === 3) {
const plansBody = createMigrationPlans(planWizardGeneralStep, planWizardVMStep, planWizardAdvancedOptionsStep);

setPlanScheduleAction(planWizardScheduleStep.values.migration_plan_choice_radio);
setPlansBodyAction(plansBody);

if (planWizardOptionsStep.values.migration_plan_choice_radio === 'migration_plan_now') {
if (planWizardScheduleStep.values.migration_plan_choice_radio === 'migration_plan_now') {
setMigrationsFilterAction(MIGRATIONS_FILTERS.inProgress);
} else if (planWizardOptionsStep.values.migration_plan_choice_radio === 'migration_plan_later') {
} else if (planWizardScheduleStep.values.migration_plan_choice_radio === 'migration_plan_later') {
setMigrationsFilterAction(MIGRATIONS_FILTERS.notStarted);
}
this.setState({
activeStepIndex: Math.min(activeStepIndex + 1, planWizardSteps.length - 1)
});
} else {
this.setState({
activeStepIndex: Math.min(activeStepIndex + 1, planWizardSteps.length - 1)
});
}

this.setState({
activeStepIndex: Math.min(activeStepIndex + 1, planWizardSteps.length - 1)
});
};

goToStep = activeStepIndex => {
Expand All @@ -71,7 +108,7 @@ class PlanWizard extends React.Component {
planWizardExitedAction,
planWizardGeneralStep,
planWizardVMStep,
planWizardOptionsStep,
planWizardScheduleStep,
alertText,
alertType,
hideAlertAction
Expand Down Expand Up @@ -106,7 +143,7 @@ class PlanWizard extends React.Component {
plansBody={plansBody}
planWizardGeneralStep={planWizardGeneralStep}
planWizardVMStep={planWizardVMStep}
planWizardOptionsStep={planWizardOptionsStep}
planWizardScheduleStep={planWizardScheduleStep}
alertText={alertText}
alertType={alertType}
hideAlertAction={hideAlertAction}
Expand All @@ -126,7 +163,7 @@ class PlanWizard extends React.Component {
onClick={onFinalStep ? hidePlanWizardAction : this.nextStep}
disabled={disableNextStep}
>
{onFinalStep ? __('Close') : activeStepIndex === 2 ? __('Create') : __('Next')}
{onFinalStep ? __('Close') : activeStepIndex === 3 ? __('Create') : __('Next')}
<Icon type="fa" name="angle-right" />
</Button>
</Wizard.Footer>
Expand All @@ -140,11 +177,15 @@ PlanWizard.propTypes = {
planWizardExitedAction: PropTypes.func,
planWizardGeneralStep: PropTypes.object,
planWizardVMStep: PropTypes.object,
planWizardOptionsStep: PropTypes.object,
planWizardAdvancedOptionsStep: PropTypes.object, // eslint-disable-line react/no-unused-prop-types
planWizardScheduleStep: PropTypes.object,
setPlansBodyAction: PropTypes.func,
setPlanScheduleAction: PropTypes.func,
resetVmStepAction: PropTypes.func,
setMigrationsFilterAction: PropTypes.func,
showConfirmModalAction: PropTypes.func,
hideConfirmModalAction: PropTypes.func,
resetAdvancedOptionsStepAction: PropTypes.func,
showAlertAction: PropTypes.func,
hideAlertAction: PropTypes.func,
alertText: PropTypes.string,
Expand All @@ -156,7 +197,8 @@ PlanWizard.defaultProps = {
planWizardExitedAction: noop,
planWizardGeneralStep: {},
planWizardVMStep: {},
planWizardOptionsStep: {},
planWizardAdvancedOptionsStep: {},
planWizardScheduleStep: {},
setPlansBodyAction: noop,
setPlanScheduleAction: noop,
resetVmStepAction: noop,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@import './components/PlanWizardAdvancedOptionsStep/PlanWizardAdvancedOptionsStep.scss';

.plan-wizard-confirm-backdrop {
z-index: 1050;
}

.plan-wizard-confirm-modal {
margin-top: 140px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
V2V_PLAN_WIZARD_SHOW_ALERT,
V2V_PLAN_WIZARD_HIDE_ALERT
} from './PlanWizardConstants';

import { RESET_V2V_ADVANCED_OPTIONS_STEP_VMS } from './components/PlanWizardAdvancedOptionsStep/PlanWizardAdvancedOptionsStepConstants';
import { V2V_VM_STEP_RESET } from './components/PlanWizardVMStep/PlanWizardVMStepConstants';

export const hidePlanWizardAction = () => dispatch => {
Expand All @@ -25,7 +25,11 @@ export const planWizardExitedAction = () => dispatch => {
dispatch({
type: V2V_VM_STEP_RESET
});
dispatch(reset('planWizardOptionsStep'));
dispatch(reset('planWizardScheduleStep'));
dispatch(reset('planWizardAdvancedOptionsStep'));
dispatch({
type: RESET_V2V_ADVANCED_OPTIONS_STEP_VMS
});
};

export const setPlansBodyAction = body => dispatch => {
Expand Down Expand Up @@ -61,3 +65,10 @@ export const hideAlertAction = () => dispatch => {
type: V2V_PLAN_WIZARD_HIDE_ALERT
});
};

export const resetAdvancedOptionsStepAction = () => dispatch => {
dispatch({
type: RESET_V2V_ADVANCED_OPTIONS_STEP_VMS
});
dispatch(reset('planWizardAdvancedOptionsStep'));
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { noop } from 'patternfly-react';
import ModalWizard from '../../components/ModalWizard';
import componentRegistry from '../../../../../../components/componentRegistry';
import PlanWizardGeneralStep from '../PlanWizard/components/PlanWizardGeneralStep';
import PlanWizardOptionsStep from '../PlanWizard/components/PlanWizardOptionsStep';
import PlanWizardScheduleStep from '../PlanWizard/components/PlanWizardScheduleStep';

class PlanWizardBody extends React.Component {
constructor(props) {
super(props);

this.planWizardVMStepContainer = componentRegistry.markup('PlanWizardVMStepContainer');
this.planWizardResultsStepContainer = componentRegistry.markup('PlanWizardResultsStepContainer');
this.planWizardAdvancedOptionsStepContainer = componentRegistry.markup('PlanWizardAdvancedOptionsStepContainer');
}
shouldComponentUpdate(nextProps, nextState) {
return JSON.stringify(this.props) !== JSON.stringify(nextProps);
Expand Down Expand Up @@ -39,8 +40,13 @@ class PlanWizardBody extends React.Component {
disableGoto: !this.props.planWizardVMStep.values
},
{
title: __('Options'),
render: () => <PlanWizardOptionsStep />,
title: __('Advanced Options'),
render: () => this.planWizardAdvancedOptionsStepContainer,
disableGoto: true
},
{
title: __('Schedule'),
render: () => <PlanWizardScheduleStep />,
disableGoto: true
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export const planWizardOverviewFilter = overview => ({
export const planWizardFormFilter = form => ({
planWizardGeneralStep: form.planWizardGeneralStep,
planWizardVMStep: form.planWizardVMStep,
planWizardOptionsStep: form.planWizardOptionsStep
planWizardAdvancedOptionsStep: form.planWizardAdvancedOptionsStep,
planWizardScheduleStep: form.planWizardScheduleStep
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ Object {
"alertText": undefined,
"alertType": undefined,
"hideAlertAction": [Function],
"hideConfirmModalAction": [Function],
"hidePlanWizard": false,
"hidePlanWizardAction": [Function],
"planWizardAdvancedOptionsStep": Object {},
"planWizardExitedAction": [Function],
"planWizardGeneralStep": Object {},
"planWizardOptionsStep": Object {},
"planWizardScheduleStep": Object {},
"planWizardVMStep": Object {},
"resetAdvancedOptionsStepAction": [Function],
"resetVmStepAction": [Function],
"setMigrationsFilterAction": [Function],
"setPlanScheduleAction": [Function],
"setPlansBodyAction": [Function],
"showAlertAction": [Function],
"showConfirmModalAction": [Function],
}
`;
Loading

0 comments on commit bdd9431

Please sign in to comment.