Created
September 2, 2018 13:51
-
-
Save ohadlevy/4beecb5ee0f0956b14ba055fef01c6c4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/package.json b/package.json | |
index 1b0329e..35e4d63 100644 | |
--- a/package.json | |
+++ b/package.json | |
@@ -74,7 +74,7 @@ | |
"lint:fix": "yarn lint:js --fix && yarn lint:styles --fix", | |
"lint:js": "eslint --max-warnings 0 src storybook", | |
"lint:styles": "yarn stylelint", | |
- "prettier": "prettier --write src/**/*.js'" | |
+ "prettier": "prettier --write 'src/**/*.js'" | |
}, | |
"jest": { | |
"collectCoverageFrom": [ | |
diff --git a/src/components/buttons/ButtonWithIcon.js b/src/components/buttons/ButtonWithIcon.js | |
index d8ce461..38ef3ec 100644 | |
--- a/src/components/buttons/ButtonWithIcon.js | |
+++ b/src/components/buttons/ButtonWithIcon.js | |
@@ -2,15 +2,13 @@ import React from 'react'; | |
import { Button, Icon, Col } from 'patternfly-react'; | |
import './ButtonWithIcon.css'; | |
-export const ButtonWithIcon = (props) => { | |
- return ( | |
- <Button onClick={props.onClick} bsClass="btn btn-link btn-with-icon"> | |
- <Col md={12}> | |
- <Icon type={props.iconType} name={props.icon} className="fa-5x"/> | |
- </Col> | |
- <Col md={12} className="label-column"> | |
- <span className="lead">{props.label}</span> | |
- </Col> | |
- </Button> | |
- ); | |
-} | |
+export const ButtonWithIcon = props => ( | |
+ <Button onClick={props.onClick} bsClass="btn btn-link btn-with-icon"> | |
+ <Col md={12}> | |
+ <Icon type={props.iconType} name={props.icon} className="fa-5x" /> | |
+ </Col> | |
+ <Col md={12} className="label-column"> | |
+ <span className="lead">{props.label}</span> | |
+ </Col> | |
+ </Button> | |
+); | |
diff --git a/src/components/forms/FormFactory.js b/src/components/forms/FormFactory.js | |
index bc6d2e6..b6b237a 100644 | |
--- a/src/components/forms/FormFactory.js | |
+++ b/src/components/forms/FormFactory.js | |
@@ -1,20 +1,20 @@ | |
import React from 'react'; | |
import { | |
- FormControl, | |
- FormGroup, | |
- Col, | |
- ControlLabel, | |
- HelpBlock, | |
- ButtonGroup, | |
- DropdownButton, | |
- MenuItem, | |
- Checkbox, | |
- Form | |
- } from 'patternfly-react'; | |
- import { get, has } from 'lodash'; | |
- import './FormFactory.css'; | |
+ FormControl, | |
+ FormGroup, | |
+ Col, | |
+ ControlLabel, | |
+ HelpBlock, | |
+ ButtonGroup, | |
+ DropdownButton, | |
+ MenuItem, | |
+ Checkbox, | |
+ Form | |
+} from 'patternfly-react'; | |
+import { get, has } from 'lodash'; | |
+import './FormFactory.css'; | |
-export const FormFactory = (props) => { | |
+export const FormFactory = props => { | |
const formGroups = Object.keys(props.fields) | |
.filter(key => !(props.fields[key].isVisible && props.fields[key].isVisible(props.fieldsValues) === false)) | |
.map(key => { | |
@@ -22,51 +22,73 @@ export const FormFactory = (props) => { | |
const validMsg = get(props.fieldsValues[key], 'validMsg', null); | |
switch (props.fields[key].type) { | |
case 'textarea': | |
- child = <FormControl | |
- componentClass="textarea" | |
- value={get(props.fieldsValues[key], 'value', '')} | |
- onChange={event => props.onFormChange(event.target.value, key)} | |
- />; | |
+ child = ( | |
+ <FormControl | |
+ componentClass="textarea" | |
+ value={get(props.fieldsValues[key], 'value', '')} | |
+ onChange={event => props.onFormChange(event.target.value, key)} | |
+ /> | |
+ ); | |
break; | |
case 'dropdown': | |
- child = <ButtonGroup justified> | |
- <DropdownButton | |
- id={`dropdown-${key}`} | |
- bsStyle="default" | |
- className="form-dropdown" | |
- title={has(props.fieldsValues[key], 'value') ? props.fieldsValues[key].value : props.fields[key].default} | |
- onSelect={value => props.onFormChange(value, key)}> | |
- {props.fields[key].values.map(value => <MenuItem key={value.id ? value.id : value.name} eventKey={value.id ? value.id : value.name}>{value.name}</MenuItem>)} | |
- </DropdownButton> | |
- </ButtonGroup>; | |
+ child = ( | |
+ <ButtonGroup justified> | |
+ <DropdownButton | |
+ id={`dropdown-${key}`} | |
+ bsStyle="default" | |
+ className="form-dropdown" | |
+ title={ | |
+ has(props.fieldsValues[key], 'value') ? props.fieldsValues[key].value : props.fields[key].default | |
+ } | |
+ onSelect={value => props.onFormChange(value, key)} | |
+ > | |
+ {props.fields[key].values.map(value => ( | |
+ <MenuItem key={value.id ? value.id : value.name} eventKey={value.id ? value.id : value.name}> | |
+ {value.name} | |
+ </MenuItem> | |
+ ))} | |
+ </DropdownButton> | |
+ </ButtonGroup> | |
+ ); | |
break; | |
case 'checkbox': | |
- child = <Checkbox | |
- checked={get(props.fieldsValues[key], 'value', false)} | |
- onChange={event => props.onFormChange(event.target.checked, key)} | |
- > | |
- {props.fields[key].title} | |
- </Checkbox>; | |
+ child = ( | |
+ <Checkbox | |
+ checked={get(props.fieldsValues[key], 'value', false)} | |
+ onChange={event => props.onFormChange(event.target.checked, key)} | |
+ > | |
+ {props.fields[key].title} | |
+ </Checkbox> | |
+ ); | |
break; | |
default: | |
- child = <FormControl | |
- type="text" | |
- value={get(props.fieldsValues[key], 'value', '')} | |
- onChange={event => props.onFormChange(event.target.value, key)} | |
- />; | |
+ child = ( | |
+ <FormControl | |
+ type="text" | |
+ value={get(props.fieldsValues[key], 'value', '')} | |
+ onChange={event => props.onFormChange(event.target.value, key)} | |
+ /> | |
+ ); | |
} | |
return ( | |
- <FormGroup key={key} validationState={validMsg ? 'error' : null} className={props.fields[key].noBottom ? 'form-group-no-bottom' : undefined}> | |
- <Col sm={3} className="text-right"> | |
- {props.fields[key].type === 'checkbox' ? null: | |
- <ControlLabel className={props.fields[key].required ? 'required-pf': null}>{props.fields[key].title}</ControlLabel>} | |
- </Col> | |
- <Col sm={5}> | |
- {child} | |
- <HelpBlock>{validMsg ? validMsg: null}</HelpBlock> | |
- </Col> | |
- </FormGroup>); | |
+ <FormGroup | |
+ key={key} | |
+ validationState={validMsg ? 'error' : null} | |
+ className={props.fields[key].noBottom ? 'form-group-no-bottom' : undefined} | |
+ > | |
+ <Col sm={3} className="text-right"> | |
+ {props.fields[key].type === 'checkbox' ? null : ( | |
+ <ControlLabel className={props.fields[key].required ? 'required-pf' : null}> | |
+ {props.fields[key].title} | |
+ </ControlLabel> | |
+ )} | |
+ </Col> | |
+ <Col sm={5}> | |
+ {child} | |
+ <HelpBlock>{validMsg || null}</HelpBlock> | |
+ </Col> | |
+ </FormGroup> | |
+ ); | |
}); | |
- return <Form horizontal>{formGroups}</Form>; | |
- | |
-} | |
+ return <Form horizontal>{formGroups}</Form>; | |
+}; | |
diff --git a/src/components/wizards/create-vm/CreateVmWizard.js b/src/components/wizards/create-vm/CreateVmWizard.js | |
index f7a524d..e5ae01d 100644 | |
--- a/src/components/wizards/create-vm/CreateVmWizard.js | |
+++ b/src/components/wizards/create-vm/CreateVmWizard.js | |
@@ -1,207 +1,214 @@ | |
import React from 'react'; | |
import { Wizard } from 'patternfly-react'; | |
-import { get } from 'lodash'; | |
+import { get } from 'lodash'; | |
import { createVM } from '../../../k8s/request'; | |
import { FormFactory } from '../../forms/FormFactory'; | |
export class CreateVmWizard extends React.Component { | |
+ state = { | |
+ activeStepIndex: 0, | |
+ basicVmSettings: {}, | |
+ wizardValid: false | |
+ }; | |
- state = { | |
- activeStepIndex: 0, | |
- basicVmSettings: {}, | |
- wizardValid: false | |
+ onFormChange = (newValue, target) => { | |
+ let validMsg = null; | |
+ if (this.basicFormFields[target].required && newValue.trim().length === 0) { | |
+ validMsg = `${this.basicFormFields[target].title} is required`; | |
} | |
- | |
- onFormChange = (newValue, target) => { | |
- let validMsg = null; | |
- if (this.basicFormFields[target].required && newValue.trim().length === 0){ | |
- validMsg = `${this.basicFormFields[target].title} is required`; | |
+ const basicVmSettings = { | |
+ ...this.state.basicVmSettings, | |
+ [target]: { | |
+ value: newValue, | |
+ validMsg | |
} | |
- const basicVmSettings = { | |
- ...this.state.basicVmSettings, | |
- [target]: { | |
- value: newValue, | |
- validMsg | |
- } | |
- }; | |
- this.setState({ | |
- basicVmSettings | |
- }); | |
- this.validateWizard(basicVmSettings); | |
+ }; | |
+ this.setState({ | |
+ basicVmSettings | |
+ }); | |
+ this.validateWizard(basicVmSettings); | |
+ }; | |
+ | |
+ validateWizard = values => { | |
+ let wizardValid = true; | |
+ | |
+ // check if all required fields are defined | |
+ const requiredKeys = Object.keys(this.basicFormFields).filter(key => this.isFieldRequired(key, values)); | |
+ const requiredKeysInValues = Object.keys(values).filter(key => this.isFieldRequired(key, values)); | |
+ if (requiredKeys.length !== requiredKeysInValues.length) { | |
+ wizardValid = false; | |
} | |
- | |
- validateWizard = values => { | |
- let wizardValid = true; | |
- //check if all required fields are defined | |
- const requiredKeys = Object.keys(this.basicFormFields).filter(key => this.isFieldRequired(key, values)); | |
- const requiredKeysInValues = Object.keys(values).filter(key => this.isFieldRequired(key, values)); | |
- if(requiredKeys.length !== requiredKeysInValues.length){ | |
+ // check if all fields are valid | |
+ for (const key in values) { | |
+ if ( | |
+ values[key].validMsg && | |
+ (this.basicFormFields[key].isVisible ? this.basicFormFields[key].isVisible(values) : true) | |
+ ) { | |
wizardValid = false; | |
+ break; | |
} | |
+ } | |
- //check if all fields are valid | |
- for (let key in values) { | |
- if (values[key].validMsg && (this.basicFormFields[key].isVisible ? this.basicFormFields[key].isVisible(values) : true)) { | |
- wizardValid = false; | |
- break; | |
- } | |
- } | |
+ this.setState({ | |
+ wizardValid | |
+ }); | |
+ }; | |
- this.setState({ | |
- wizardValid | |
- }); | |
- } | |
+ isFieldRequired = (key, basicVmSettings) => | |
+ this.basicFormFields[key].required && | |
+ (this.basicFormFields[key].isVisible ? this.basicFormFields[key].isVisible(basicVmSettings) : true); | |
- isFieldRequired = (key, basicVmSettings) => { | |
- return this.basicFormFields[key].required && (this.basicFormFields[key].isVisible ? this.basicFormFields[key].isVisible(basicVmSettings) : true); | |
+ basicFormFields = { | |
+ name: { | |
+ title: 'Name', | |
+ required: true | |
+ }, | |
+ description: { | |
+ title: 'Description', | |
+ type: 'textarea' | |
+ }, | |
+ namespace: { | |
+ title: 'Namespace', | |
+ type: 'dropdown', | |
+ default: '--- Select Namespace ---', | |
+ values: this.props.namespaces | |
+ }, | |
+ imageSourceType: { | |
+ title: 'Provision Source', | |
+ type: 'dropdown', | |
+ default: '--- Select Provision Source ---', | |
+ values: [ | |
+ { | |
+ name: 'PXE' | |
+ }, | |
+ { | |
+ name: 'URL' | |
+ }, | |
+ { | |
+ name: 'Template' | |
+ }, | |
+ { | |
+ name: 'Registry' | |
+ } | |
+ ], | |
+ required: true | |
+ }, | |
+ template: { | |
+ title: 'Template', | |
+ type: 'dropdown', | |
+ default: '--- Select Template ---', | |
+ required: true, | |
+ isVisible: basicVmSettings => get(basicVmSettings, 'imageSourceType.value') === 'Template', | |
+ values: this.props.templates | |
+ }, | |
+ registryImage: { | |
+ title: 'Registry Image', | |
+ required: true, | |
+ isVisible: basicVmSettings => get(basicVmSettings, 'imageSourceType.value') === 'Registry' | |
+ }, | |
+ imageURL: { | |
+ title: 'URL', | |
+ required: true, | |
+ isVisible: basicVmSettings => get(basicVmSettings, 'imageSourceType.value') === 'URL' | |
+ }, | |
+ operatingSystem: { | |
+ title: 'Operating System', | |
+ type: 'dropdown', | |
+ default: '--- Select Operating System ---', | |
+ values: this.props.operatingSystems, | |
+ required: true | |
+ }, | |
+ flavor: { | |
+ title: 'Flavor', | |
+ type: 'dropdown', | |
+ default: '--- Select Flavor ---', | |
+ values: this.props.flavors.concat([{ name: 'Custom' }]), | |
+ required: true | |
+ }, | |
+ memory: { | |
+ title: 'Memory (GB)', | |
+ required: true, | |
+ isVisible: basicVmSettings => get(basicVmSettings, 'flavor.value', '') === 'Custom' | |
+ }, | |
+ cpu: { | |
+ title: 'CPUs', | |
+ required: true, | |
+ isVisible: basicVmSettings => get(basicVmSettings, 'flavor.value', '') === 'Custom' | |
+ }, | |
+ workloadProfile: { | |
+ title: 'Workload Profile', | |
+ type: 'dropdown', | |
+ default: '--- Select Workload Profile ---', | |
+ values: this.props.workloadProfiles, | |
+ required: true | |
+ }, | |
+ startVM: { | |
+ title: 'Start virtual machine on creation', | |
+ type: 'checkbox', | |
+ noBottom: true | |
+ }, | |
+ createTemplate: { | |
+ title: 'Create new template from configuration', | |
+ type: 'checkbox', | |
+ noBottom: true | |
+ }, | |
+ cloudInit: { | |
+ title: 'Use cloud-init', | |
+ type: 'checkbox' | |
+ }, | |
+ hostname: { | |
+ title: 'Hostname', | |
+ isVisible: basicVmSettings => get(basicVmSettings, 'cloudInit.value', false), | |
+ required: true | |
+ }, | |
+ authKeys: { | |
+ title: 'Authenticated SSH Keys', | |
+ type: 'textarea', | |
+ isVisible: basicVmSettings => get(basicVmSettings, 'cloudInit.value', false), | |
+ required: true | |
} | |
- | |
- basicFormFields = { | |
- name: { | |
- title: 'Name', | |
- required: true | |
- }, | |
- description: { | |
- title: 'Description', | |
- type: 'textarea' | |
- }, | |
- namespace: { | |
- title: 'Namespace', | |
- type: 'dropdown', | |
- default: '--- Select Namespace ---', | |
- values: this.props.namespaces | |
- }, | |
- imageSourceType: { | |
- title: 'Provision Source', | |
- type: 'dropdown', | |
- default: '--- Select Provision Source ---', | |
- values: [ | |
- { | |
- name: 'PXE' | |
- }, | |
- { | |
- name: 'URL' | |
- }, | |
- { | |
- name: 'Template' | |
- }, | |
- { | |
- name: 'Registry' | |
- } | |
- ], | |
- required: true | |
- }, | |
- template: { | |
- title: 'Template', | |
- type: 'dropdown', | |
- default: '--- Select Template ---', | |
- required: true, | |
- isVisible: (basicVmSettings) => get(basicVmSettings, 'imageSourceType.value') === 'Template', | |
- values: this.props.templates | |
- }, | |
- registryImage: { | |
- title: 'Registry Image', | |
- required: true, | |
- isVisible: (basicVmSettings) => get(basicVmSettings,'imageSourceType.value') === 'Registry' | |
- }, | |
- imageURL: { | |
- title: 'URL', | |
- required: true, | |
- isVisible: (basicVmSettings) => get(basicVmSettings,'imageSourceType.value') === 'URL' | |
- }, | |
- operatingSystem: { | |
- title: 'Operating System', | |
- type: 'dropdown', | |
- default: '--- Select Operating System ---', | |
- values: this.props.operatingSystems, | |
- required: true | |
- }, | |
- flavor:{ | |
- title: 'Flavor', | |
- type: 'dropdown', | |
- default: '--- Select Flavor ---', | |
- values: this.props.flavors.concat([{name:'Custom'}]), | |
- required: true | |
- }, | |
- memory:{ | |
- title: 'Memory (GB)', | |
- required: true, | |
- isVisible: (basicVmSettings) => get(basicVmSettings, 'flavor.value', '') === 'Custom' | |
- }, | |
- cpu: { | |
- title: 'CPUs', | |
- required: true, | |
- isVisible: (basicVmSettings) => get(basicVmSettings, 'flavor.value', '') === 'Custom' | |
- }, | |
- workloadProfile:{ | |
- title: 'Workload Profile', | |
- type: 'dropdown', | |
- default: '--- Select Workload Profile ---', | |
- values: this.props.workloadProfiles, | |
- required: true | |
- }, | |
- startVM:{ | |
- title: 'Start virtual machine on creation', | |
- type: 'checkbox', | |
- noBottom: true | |
- }, | |
- createTemplate:{ | |
- title: 'Create new template from configuration', | |
- type: 'checkbox', | |
- noBottom: true | |
- }, | |
- cloudInit:{ | |
- title: 'Use cloud-init', | |
- type: 'checkbox' | |
- }, | |
- hostname:{ | |
- title: 'Hostname', | |
- isVisible: (basicVmSettings) => get(basicVmSettings, 'cloudInit.value', false), | |
- required: true | |
- }, | |
- authKeys:{ | |
- title: 'Authenticated SSH Keys', | |
- type: 'textarea', | |
- isVisible: (basicVmSettings) => get(basicVmSettings, 'cloudInit.value', false), | |
- required: true | |
+ }; | |
+ | |
+ wizardStepsNewVM = [ | |
+ { | |
+ title: 'Basic Settings', | |
+ render: () => ( | |
+ <FormFactory | |
+ fields={this.basicFormFields} | |
+ fieldsValues={this.state.basicVmSettings} | |
+ onFormChange={this.onFormChange} | |
+ /> | |
+ ) | |
+ }, | |
+ { | |
+ title: 'Networking', | |
+ render: () => <p>Render</p> | |
+ }, | |
+ { | |
+ title: 'Result', | |
+ render: () => { | |
+ createVM(this.state.basicVmSettings, this.state.network, this.state.storage); | |
+ return <p>object visible in console</p>; | |
} | |
- | |
} | |
- | |
- wizardStepsNewVM = [ | |
- { | |
- title: 'Basic Settings', | |
- render: () => <FormFactory fields={this.basicFormFields} fieldsValues={this.state.basicVmSettings} onFormChange={this.onFormChange}/> | |
- }, | |
- { | |
- title: 'Networking', | |
- render: () => <p>Render</p> | |
- }, | |
- { | |
- title: 'Result', | |
- render: () => { | |
- createVM(this.state.basicVmSettings, this.state.network, this.state.storage); | |
- return <p>object visible in console</p> | |
- } | |
- } | |
- ] | |
+ ]; | |
- onStepChanged = (index) => { | |
- this.setState({ activeStepIndex: index }) | |
- } | |
- | |
- render() { | |
- return ( | |
- <Wizard.Pattern | |
- show | |
- onHide={this.props.onHide} | |
- steps={this.wizardStepsNewVM} | |
- activeStepIndex={this.state.activeStepIndex} | |
- onStepChanged={index => this.onStepChanged(index)} | |
- nextStepDisabled={!this.state.wizardValid} | |
- nextText={this.state.activeStepIndex === 2 ? 'Create Virtual Machine':'Next'} | |
- />); | |
- } | |
- | |
+ onStepChanged = index => { | |
+ this.setState({ activeStepIndex: index }); | |
+ }; | |
+ | |
+ render() { | |
+ return ( | |
+ <Wizard.Pattern | |
+ show | |
+ onHide={this.props.onHide} | |
+ steps={this.wizardStepsNewVM} | |
+ activeStepIndex={this.state.activeStepIndex} | |
+ onStepChanged={index => this.onStepChanged(index)} | |
+ nextStepDisabled={!this.state.wizardValid} | |
+ nextText={this.state.activeStepIndex === 2 ? 'Create Virtual Machine' : 'Next'} | |
+ /> | |
+ ); | |
+ } | |
} | |
diff --git a/src/components/wizards/import-vm/ImportVmWizard.js b/src/components/wizards/import-vm/ImportVmWizard.js | |
index 1177897..d1ed53f 100644 | |
--- a/src/components/wizards/import-vm/ImportVmWizard.js | |
+++ b/src/components/wizards/import-vm/ImportVmWizard.js | |
@@ -3,62 +3,65 @@ import { Wizard } from 'patternfly-react'; | |
import { FormFactory } from '../../forms/FormFactory'; | |
export class ImportVmWizard extends React.Component { | |
+ state = { | |
+ activeStepIndex: 0, | |
+ importValues: {} | |
+ }; | |
- state = { | |
- activeStepIndex: 0, | |
- importValues: {} | |
+ importFields = { | |
+ sourceType: { | |
+ title: 'Import Source Type', | |
+ type: 'dropdown', | |
+ default: '--- Select Import Source ---', | |
+ required: true, | |
+ values: [ | |
+ { | |
+ name: 'Foo import source' | |
+ } | |
+ ] | |
+ }, | |
+ url: { | |
+ title: 'VMWare URL to EXSi', | |
+ required: true | |
+ }, | |
+ username: { | |
+ title: 'VMWare Username', | |
+ required: true | |
+ }, | |
+ password: { | |
+ title: 'VMWare Password', | |
+ required: true | |
} | |
+ }; | |
- importFields = { | |
- sourceType: { | |
- title: 'Import Source Type', | |
- type: 'dropdown', | |
- default: '--- Select Import Source ---', | |
- required: true, | |
- values: [ | |
- { | |
- name: 'Foo import source' | |
- } | |
- ] | |
- }, | |
- url: { | |
- title: 'VMWare URL to EXSi', | |
- required: true | |
- }, | |
- username: { | |
- title: 'VMWare Username', | |
- required: true | |
- }, | |
- password: { | |
- title: 'VMWare Password', | |
- required: true | |
- } | |
- } | |
- | |
- onFormChange = (newValue, target) => { | |
+ onFormChange = (newValue, target) => {}; | |
+ wizardStepsImportVM = [ | |
+ { | |
+ title: 'Basic Information', | |
+ render: () => ( | |
+ <FormFactory | |
+ fields={this.importFields} | |
+ fieldsValues={this.state.importValues} | |
+ onFormChange={this.onFormChange} | |
+ /> | |
+ ) | |
+ }, | |
+ { | |
+ title: 'Virtual Machines', | |
+ render: () => <p>Render</p> | |
} | |
- | |
- wizardStepsImportVM = [ | |
- { | |
- title: 'Basic Information', | |
- render: () => <FormFactory fields={this.importFields} fieldsValues={this.state.importValues} onFormChange={this.onFormChange} /> | |
- }, | |
- { | |
- title: 'Virtual Machines', | |
- render: () => <p>Render</p> | |
- } | |
- ] | |
- | |
- render() { | |
- return ( | |
- <Wizard.Pattern | |
- show | |
- onHide={this.props.onHide} | |
- steps={this.wizardStepsImportVM} | |
- activeStepIndex={this.state.activeStepIndex} | |
- onStepChanged={index => this.setState({ activeStepIndex: index })} | |
- />); | |
- } | |
- | |
+ ]; | |
+ | |
+ render() { | |
+ return ( | |
+ <Wizard.Pattern | |
+ show | |
+ onHide={this.props.onHide} | |
+ steps={this.wizardStepsImportVM} | |
+ activeStepIndex={this.state.activeStepIndex} | |
+ onStepChanged={index => this.setState({ activeStepIndex: index })} | |
+ /> | |
+ ); | |
+ } | |
} | |
diff --git a/src/components/wizards/new-vm/NewVmWizard.js b/src/components/wizards/new-vm/NewVmWizard.js | |
index cdd863b..052f364 100644 | |
--- a/src/components/wizards/new-vm/NewVmWizard.js | |
+++ b/src/components/wizards/new-vm/NewVmWizard.js | |
@@ -6,53 +6,54 @@ import { ButtonWithIcon } from '../../buttons/ButtonWithIcon'; | |
import './NewVmWizard.css'; | |
export class NewVmWizard extends React.Component { | |
+ state = { | |
+ createVM: false, | |
+ importVM: false | |
+ }; | |
- state = { | |
- createVM: false, | |
- importVM: false | |
- } | |
- | |
- openCreateVmWizard = () => this.setState({createVM: true}); | |
+ openCreateVmWizard = () => this.setState({ createVM: true }); | |
+ | |
+ openImportVmWizard = () => this.setState({ importVM: true }); | |
- openImportVmWizard = () => this.setState({importVM: true}); | |
- | |
- render() { | |
- let wizard; | |
- if(this.state.createVM) { | |
- wizard = <CreateVmWizard onHide={this.props.onHide} {...this.props}/> | |
- } else if(this.state.importVM) { | |
- wizard = <ImportVmWizard onHide={this.props.onHide} {...this.props}/> | |
- } | |
- return ( | |
- <React.Fragment> | |
- <Wizard show onHide={this.props.onHide}> | |
- <Wizard.Header title="Create Virtual Machine" onClose={this.props.onHide} /> | |
- <Wizard.Body> | |
- <Wizard.Row> | |
- <Wizard.Main> | |
- <Wizard.Contents stepIndex={0} activeStepIndex={0} className="wizard-content"> | |
- <ButtonWithIcon | |
- label="Create New Virtual Machine" | |
- iconType="pf" | |
- icon="virtual-machine" | |
- onClick={this.openCreateVmWizard} | |
- /> | |
- <ButtonWithIcon | |
- label="Import Existing Virtual Machine" | |
- iconType="pf" | |
- icon="import" | |
- onClick={this.openImportVmWizard} | |
- /> | |
- </Wizard.Contents> | |
- </Wizard.Main> | |
- </Wizard.Row> | |
- </Wizard.Body> | |
- <Wizard.Footer> | |
- <Button bsStyle="default" className="btn-cancel" onClick={this.props.onHide}>Cancel</Button> | |
- </Wizard.Footer> | |
- </Wizard> | |
- {wizard} | |
- </React.Fragment> | |
- ); | |
+ render() { | |
+ let wizard; | |
+ if (this.state.createVM) { | |
+ wizard = <CreateVmWizard onHide={this.props.onHide} {...this.props} />; | |
+ } else if (this.state.importVM) { | |
+ wizard = <ImportVmWizard onHide={this.props.onHide} {...this.props} />; | |
} | |
+ return ( | |
+ <React.Fragment> | |
+ <Wizard show onHide={this.props.onHide}> | |
+ <Wizard.Header title="Create Virtual Machine" onClose={this.props.onHide} /> | |
+ <Wizard.Body> | |
+ <Wizard.Row> | |
+ <Wizard.Main> | |
+ <Wizard.Contents stepIndex={0} activeStepIndex={0} className="wizard-content"> | |
+ <ButtonWithIcon | |
+ label="Create New Virtual Machine" | |
+ iconType="pf" | |
+ icon="virtual-machine" | |
+ onClick={this.openCreateVmWizard} | |
+ /> | |
+ <ButtonWithIcon | |
+ label="Import Existing Virtual Machine" | |
+ iconType="pf" | |
+ icon="import" | |
+ onClick={this.openImportVmWizard} | |
+ /> | |
+ </Wizard.Contents> | |
+ </Wizard.Main> | |
+ </Wizard.Row> | |
+ </Wizard.Body> | |
+ <Wizard.Footer> | |
+ <Button bsStyle="default" className="btn-cancel" onClick={this.props.onHide}> | |
+ Cancel | |
+ </Button> | |
+ </Wizard.Footer> | |
+ </Wizard> | |
+ {wizard} | |
+ </React.Fragment> | |
+ ); | |
+ } | |
} | |
diff --git a/src/components/wizards/new-vm/NewVmWizard.stories.js b/src/components/wizards/new-vm/NewVmWizard.stories.js | |
index fec0e1d..037916e 100644 | |
--- a/src/components/wizards/new-vm/NewVmWizard.stories.js | |
+++ b/src/components/wizards/new-vm/NewVmWizard.stories.js | |
@@ -5,10 +5,9 @@ import { Button } from 'patternfly-react'; | |
import { os } from './OperatingSystem'; | |
class NewVmWizardExample extends React.Component { | |
- | |
state = { | |
show: false | |
- } | |
+ }; | |
storageClasses = [ | |
{ | |
@@ -26,7 +25,7 @@ class NewVmWizardExample extends React.Component { | |
class: 'storage class 3', | |
size: 30 | |
} | |
- ] | |
+ ]; | |
namespaces = [ | |
{ | |
@@ -35,7 +34,7 @@ class NewVmWizardExample extends React.Component { | |
{ | |
name: 'namespace2' | |
} | |
- ] | |
+ ]; | |
flavors = [ | |
{ | |
@@ -44,7 +43,7 @@ class NewVmWizardExample extends React.Component { | |
{ | |
name: 'flavor2' | |
} | |
- ] | |
+ ]; | |
workloadProfiles = [ | |
{ | |
@@ -53,7 +52,7 @@ class NewVmWizardExample extends React.Component { | |
{ | |
name: 'workloadProfile2' | |
} | |
- ] | |
+ ]; | |
templates = [ | |
{ | |
@@ -62,33 +61,36 @@ class NewVmWizardExample extends React.Component { | |
{ | |
name: 'template2' | |
} | |
- ] | |
+ ]; | |
openWizard = () => { | |
- this.setState({show: true}); | |
- } | |
+ this.setState({ show: true }); | |
+ }; | |
onHide = () => { | |
- this.setState({show: false}); | |
- } | |
+ this.setState({ show: false }); | |
+ }; | |
render() { | |
return ( | |
<React.Fragment> | |
<Button onClick={this.openWizard}>Open New VM Wizard</Button> | |
- {this.state.show ? <NewVmWizard | |
+ {this.state.show ? ( | |
+ <NewVmWizard | |
onHide={this.onHide} | |
storageClasses={this.storageClasses} | |
workloadProfiles={this.workloadProfiles} | |
flavors={this.flavors} | |
namespaces={this.namespaces} | |
- operatingSystems = {os} | |
- templates={this.templates}/> : undefined } | |
- </React.Fragment>); | |
+ operatingSystems={os} | |
+ templates={this.templates} | |
+ /> | |
+ ) : ( | |
+ undefined | |
+ )} | |
+ </React.Fragment> | |
+ ); | |
} | |
} | |
-storiesOf('Wizards', module) | |
- .add('New VM Wizard', () => ( | |
- <NewVmWizardExample/> | |
- )); | |
+storiesOf('Wizards', module).add('New VM Wizard', () => <NewVmWizardExample />); | |
diff --git a/src/components/wizards/new-vm/OperatingSystem.js b/src/components/wizards/new-vm/OperatingSystem.js | |
index 4505c17..5c08eb0 100644 | |
--- a/src/components/wizards/new-vm/OperatingSystem.js | |
+++ b/src/components/wizards/new-vm/OperatingSystem.js | |
@@ -1,20 +1,20 @@ | |
export const os = [ | |
- { | |
- name: 'Alpine Linux 3.5', | |
- id: 'alpinelinux3.5' | |
- }, | |
- { | |
- name: 'Alpine Linux 3.6', | |
- id: 'alpinelinux3.6' | |
- }, | |
- { | |
- name: 'Alpine Linux 3.7', | |
- id: 'alpinelinux3.7' | |
- }, | |
- { | |
- name: 'Mandrake RE Spring 2001', | |
- id: 'altlinux1.0' | |
- } | |
+ { | |
+ name: 'Alpine Linux 3.5', | |
+ id: 'alpinelinux3.5' | |
+ }, | |
+ { | |
+ name: 'Alpine Linux 3.6', | |
+ id: 'alpinelinux3.6' | |
+ }, | |
+ { | |
+ name: 'Alpine Linux 3.7', | |
+ id: 'alpinelinux3.7' | |
+ }, | |
+ { | |
+ name: 'Mandrake RE Spring 2001', | |
+ id: 'altlinux1.0' | |
+ } | |
]; | |
/* | |
diff --git a/src/constants/index.js b/src/constants/index.js | |
index 183cca1..09da67f 100644 | |
--- a/src/constants/index.js | |
+++ b/src/constants/index.js | |
@@ -1,4 +1,4 @@ | |
-export const API_VERSION='kubevirt.io/v1alpha2' | |
-export const VM_KIND='VirtualMachine' | |
-export const OS_LABEL='kubevirt.io/os' | |
-export const FLAVOR_LABEL='kubevirt.io/flavor' | |
+export const API_VERSION = 'kubevirt.io/v1alpha2'; | |
+export const VM_KIND = 'VirtualMachine'; | |
+export const OS_LABEL = 'kubevirt.io/os'; | |
+export const FLAVOR_LABEL = 'kubevirt.io/flavor'; | |
diff --git a/src/k8s/request.js b/src/k8s/request.js | |
index 112a03f..ba0a7bb 100644 | |
--- a/src/k8s/request.js | |
+++ b/src/k8s/request.js | |
@@ -1,47 +1,47 @@ | |
-import { API_VERSION, VM_KIND, OS_LABEL, FLAVOR_LABEL} from '../constants'; | |
+import { API_VERSION, VM_KIND, OS_LABEL, FLAVOR_LABEL } from '../constants'; | |
import { get } from 'lodash'; | |
export const createVM = (basicSettings, network, storage) => { | |
const vm = generateVmJson(basicSettings, network, storage); | |
- | |
+ | |
createK8sObject(vm); | |
-} | |
+}; | |
export const generateVmJson = (basicSettings, network, storage) => { | |
- let vm = { | |
+ const vm = { | |
apiVersion: API_VERSION, | |
kind: VM_KIND, | |
- metadata : { | |
+ metadata: { | |
name: basicSettings.name.value, | |
labels: { | |
[OS_LABEL]: basicSettings.operatingSystem.value | |
} | |
}, | |
- spec: { | |
- template: {} | |
- } | |
- } | |
+ spec: { | |
+ template: {} | |
+ } | |
+ }; | |
- if(basicSettings.namespace){ | |
+ if (basicSettings.namespace) { | |
vm.metadata.namespace = basicSettings.namespace.value; | |
} | |
- if(basicSettings.description){ | |
+ if (basicSettings.description) { | |
vm.metadata.labels.description = basicSettings.description; | |
} | |
- | |
+ | |
addFlavor(vm, basicSettings); | |
addImageSourceType(vm, basicSettings); | |
addCloudInit(vm, basicSettings); | |
- if(basicSettings.startVM){ | |
- vm.spec.running=basicSettings.startVM.value; | |
+ if (basicSettings.startVM) { | |
+ vm.spec.running = basicSettings.startVM.value; | |
} | |
return vm; | |
-} | |
+}; | |
const addFlavor = (vm, basicSettings) => { | |
- if(basicSettings.flavor.value === 'Custom'){ | |
+ if (basicSettings.flavor.value === 'Custom') { | |
vm.spec.template.spec = { | |
domain: { | |
cpu: { | |
@@ -53,7 +53,7 @@ const addFlavor = (vm, basicSettings) => { | |
} | |
} | |
} | |
- } | |
+ }; | |
} else { | |
vm.spec.template.spec = { | |
metadata: { | |
@@ -61,15 +61,15 @@ const addFlavor = (vm, basicSettings) => { | |
[FLAVOR_LABEL]: basicSettings.flavor.value | |
} | |
} | |
- } | |
+ }; | |
} | |
-} | |
+}; | |
const addImageSourceType = (vm, basicSettings) => { | |
- if(get(basicSettings.imageSourceType, 'value') === 'Registry'){ | |
- let domain = get(vm.spec.template.spec, 'domain', {}); | |
- let devices = get(domain,'devices',{}); | |
- let disks = get(devices,'disks',[]); | |
+ if (get(basicSettings.imageSourceType, 'value') === 'Registry') { | |
+ const domain = get(vm.spec.template.spec, 'domain', {}); | |
+ const devices = get(domain, 'devices', {}); | |
+ const disks = get(devices, 'disks', []); | |
disks.push({ | |
name: 'registryvolume', | |
volumeName: 'registryvolume', | |
@@ -81,7 +81,7 @@ const addImageSourceType = (vm, basicSettings) => { | |
domain.devices = devices; | |
vm.spec.template.spec.domain = domain; | |
- let volumes = get(vm.spec.template.spec, 'volumes', []); | |
+ const volumes = get(vm.spec.template.spec, 'volumes', []); | |
volumes.push({ | |
name: 'registryvolume', | |
registryDisk: { | |
@@ -90,12 +90,12 @@ const addImageSourceType = (vm, basicSettings) => { | |
}); | |
vm.spec.template.spec.volumes = volumes; | |
} | |
-} | |
+}; | |
const addCloudInit = (vm, basicSettings) => { | |
- if(get(basicSettings.cloudInit, 'value', false)) { | |
- let domain = get(vm.spec.template.spec, 'domain', {}); | |
- let devices = get(domain,'devices',[]); | |
+ if (get(basicSettings.cloudInit, 'value', false)) { | |
+ const domain = get(vm.spec.template.spec, 'domain', {}); | |
+ const devices = get(domain, 'devices', []); | |
devices.push({ | |
name: 'cloudinitdisk', | |
volumeName: 'cloudinitdisk', | |
@@ -106,30 +106,30 @@ const addCloudInit = (vm, basicSettings) => { | |
domain.devices = devices; | |
vm.spec.template.spec.domain = domain; | |
- let volumes = get(vm.spec.template.spec, 'volumes', []); | |
+ const volumes = get(vm.spec.template.spec, 'volumes', []); | |
let userData = ''; | |
userData = appendToUserData(userData, 'ssh-authorized-keys', basicSettings.authKeys.value); | |
- if(get(basicSettings.hostname, 'value')) { | |
- userData = appendToUserData(userData, 'hostname',basicSettings.hostname.value) | |
+ if (get(basicSettings.hostname, 'value')) { | |
+ userData = appendToUserData(userData, 'hostname', basicSettings.hostname.value); | |
} | |
volumes.push({ | |
name: 'cloudinitvolume', | |
- cloudInitNoCloud: { | |
- userData: userData | |
+ cloudInitNoCloud: { | |
+ userData | |
} | |
}); | |
vm.spec.template.spec.volumes = volumes; | |
} | |
-} | |
+}; | |
const appendToUserData = (userData, key, value) => { | |
- if(userData !== '') { | |
+ if (userData !== '') { | |
userData += '\n'; | |
- } | |
- userData += `${key}:\n - ${value}` | |
+ } | |
+ userData += `${key}:\n - ${value}`; | |
return userData; | |
-} | |
+}; | |
-export const createK8sObject = (k8sObject) => { | |
+export const createK8sObject = k8sObject => { | |
console.log(JSON.stringify(k8sObject)); | |
-} | |
+}; | |
diff --git a/src/k8s/request.test.js b/src/k8s/request.test.js | |
index 3df8558..107f6ad 100644 | |
--- a/src/k8s/request.test.js | |
+++ b/src/k8s/request.test.js | |
@@ -4,10 +4,10 @@ import { API_VERSION, VM_KIND, OS_LABEL, FLAVOR_LABEL } from '../constants'; | |
const minimalBasicSettings = { | |
name: { | |
- value:'name' | |
+ value: 'name' | |
}, | |
operatingSystem: { | |
- value: 'os', | |
+ value: 'os' | |
}, | |
flavor: { | |
value: 'flavor' | |
@@ -18,32 +18,32 @@ const minimalBasicSettings = { | |
registryImage: { | |
value: 'imageURL' | |
} | |
-} | |
+}; | |
const runAfterCreationSettings = { | |
...minimalBasicSettings, | |
startVM: { | |
value: true | |
} | |
-} | |
+}; | |
const customFlavorBasicSettings = { | |
...minimalBasicSettings, | |
flavor: { | |
value: 'Custom' | |
}, | |
- cpu:{ | |
+ cpu: { | |
value: 3 | |
}, | |
- memory:{ | |
+ memory: { | |
value: 3 | |
} | |
-} | |
+}; | |
const minimalVM = { | |
apiVersion: API_VERSION, | |
kind: VM_KIND, | |
- metadata : { | |
+ metadata: { | |
name: minimalBasicSettings.name.value, | |
labels: { | |
[OS_LABEL]: minimalBasicSettings.operatingSystem.value | |
@@ -57,24 +57,24 @@ const minimalVM = { | |
[FLAVOR_LABEL]: minimalBasicSettings.flavor.value | |
} | |
}, | |
- domain:{ | |
- devices:{ | |
- disks:[ | |
+ domain: { | |
+ devices: { | |
+ disks: [ | |
{ | |
name: 'registryvolume', | |
volumeName: 'registryvolume', | |
disk: { | |
- bus: 'virtio' | |
+ bus: 'virtio' | |
} | |
} | |
] | |
} | |
}, | |
- volumes:[ | |
+ volumes: [ | |
{ | |
name: 'registryvolume', | |
registryDisk: { | |
- image: minimalBasicSettings.registryImage.value | |
+ image: minimalBasicSettings.registryImage.value | |
} | |
} | |
] | |
@@ -85,30 +85,30 @@ const minimalVM = { | |
const runAfterCreationVM = { | |
...minimalVM, | |
- spec:{ | |
+ spec: { | |
...minimalVM.spec, | |
running: true | |
} | |
-} | |
+}; | |
-let customFlavorVM = omit(minimalVM, 'spec.template.spec.metadata'); | |
+const customFlavorVM = omit(minimalVM, 'spec.template.spec.metadata'); | |
customFlavorVM.spec.template.spec.domain.cpu = { | |
- cores: customFlavorBasicSettings.cpu.value | |
-} | |
+ cores: customFlavorBasicSettings.cpu.value | |
+}; | |
customFlavorVM.spec.template.spec.domain.resources = { | |
requests: { | |
memory: `${customFlavorBasicSettings.memory.value}Gi` | |
} | |
-} | |
+}; | |
describe('Create VM JSON', () => { | |
- it('minimal VM JSON', () =>{ | |
+ it('minimal VM JSON', () => { | |
expect(request.generateVmJson(minimalBasicSettings)).toEqual(minimalVM); | |
}); | |
- it('with custom flavor', () =>{ | |
+ it('with custom flavor', () => { | |
expect(request.generateVmJson(customFlavorBasicSettings)).toEqual(customFlavorVM); | |
}); | |
- it('with running VM', () =>{ | |
+ it('with running VM', () => { | |
expect(request.generateVmJson(runAfterCreationSettings)).toEqual(runAfterCreationVM); | |
- }) | |
+ }); | |
}); | |
diff --git a/storybook/config.js b/storybook/config.js | |
index b048ba2..dcde8eb 100644 | |
--- a/storybook/config.js | |
+++ b/storybook/config.js | |
@@ -1,8 +1,8 @@ | |
import { configure } from '@storybook/react'; | |
import { setOptions } from '@storybook/addon-options'; | |
import 'patternfly-react/dist/css/patternfly-react.css'; | |
-import 'patternfly/dist/css/patternfly.css' | |
-import 'patternfly/dist/css/patternfly-additions.css' | |
+import 'patternfly/dist/css/patternfly.css'; | |
+import 'patternfly/dist/css/patternfly-additions.css'; | |
const storyContext = require.context('../src', true, /\.stories\.js$/); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment