WizardOptions.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. Copyright (C) 2017 Cloudbase Solutions SRL
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. import React, { PropTypes } from 'react';
  15. import Reflux from 'reflux';
  16. import withStyles from 'isomorphic-style-loader/lib/withStyles';
  17. import s from './WizardOptions.scss';
  18. import Dropdown from '../NewDropdown';
  19. import WizardActions from '../../actions/WizardActions';
  20. import WizardStore from '../../stores/WizardStore';
  21. import NotificationActions from '../../actions/NotificationActions';
  22. const title = 'Migration Options';
  23. class WizardOptions extends Reflux.Component {
  24. static contextTypes = {
  25. onSetTitle: PropTypes.func.isRequired,
  26. };
  27. static propTypes = {
  28. setWizardState: PropTypes.func
  29. }
  30. constructor(props) {
  31. super(props)
  32. this.store = WizardStore
  33. this.state = {
  34. autoFlavors: true,
  35. diskFormat: "VHD",
  36. fipPool: "public",
  37. valid: true,
  38. nextStep: "WizardNetworks",
  39. formSubmitted: false,
  40. nextCallback: (e) => this.nextCallback(e),
  41. showAdvancedOptions: props.data.showAdvancedOptions
  42. }
  43. }
  44. componentWillMount() {
  45. super.componentWillMount.call(this)
  46. WizardActions.updateWizardState(this.state)
  47. this.context.onSetTitle(title)
  48. }
  49. componentDidMount() {
  50. let destinationEnvironment = this.state.destination_environment
  51. this.state.targetCloud.cloudRef["import_" + this.state.migrationType].fields.forEach(field => {
  52. if (typeof field.default !== "undefined" && typeof destinationEnvironment[field.name] === "undefined") {
  53. destinationEnvironment[field.name] = field.default
  54. }
  55. }, this)
  56. WizardActions.updateWizardState({ destination_environment: destinationEnvironment })
  57. }
  58. handleChangeAutoFlavor() {
  59. this.setState({ autoFlavors: !this.state.autoFlavors }, this.updateWizard)
  60. }
  61. handleChangeDiskFormat(value) {
  62. this.setState({ diskFormat: value }, this.updateWizard)
  63. }
  64. handleChangeFipPool(value) {
  65. this.setState({ fipPool: value }, this.updateWizard)
  66. }
  67. updateWizard() {
  68. WizardActions.updateWizardState(this.state)
  69. }
  70. isValid(field) {
  71. if (field.required && this.state.formSubmitted && field.name != "network_map"
  72. && field.name != "destination_network") {
  73. if (!this.state.destination_environment[field.name]) {
  74. return false
  75. } else {
  76. return this.state.destination_environment[field.name].trim().length != 0;
  77. }
  78. } else {
  79. return true
  80. }
  81. }
  82. nextCallback(callback) {
  83. let valid = true
  84. this.setState({ formSubmitted: true }, () => {
  85. this.state.targetCloud.cloudRef["import_" + this.state.migrationType].fields.forEach(field => {
  86. if (!this.isValid(field)) {
  87. valid = false
  88. }
  89. })
  90. if (callback && valid) {
  91. callback()
  92. }
  93. if (!valid) {
  94. NotificationActions.notify("Please fill all required fields", "error")
  95. }
  96. })
  97. }
  98. toggleAdvancedOptions() {
  99. let showAdvancedOptions = !this.state.showAdvancedOptions
  100. this.setState({ showAdvancedOptions: showAdvancedOptions })
  101. WizardActions.updateWizardState({ showAdvancedOptions: showAdvancedOptions })
  102. }
  103. handleOptionsFieldChange(e, field) {
  104. let destinationEnvironment = this.state.destination_environment
  105. if (field.type == 'dropdown') {
  106. destinationEnvironment[field.name] = e
  107. } else {
  108. destinationEnvironment[field.name] = e.target.value
  109. }
  110. WizardActions.updateWizardState({ destination_environment: destinationEnvironment })
  111. }
  112. renderField(field) {
  113. let returnValue
  114. let extraClasses = ""
  115. if (field.required) {
  116. extraClasses += "required"
  117. }
  118. if (this.state.showAdvancedOptions) {
  119. extraClasses += " showAdvanced"
  120. }
  121. if (!this.isValid(field)) {
  122. extraClasses += " error"
  123. }
  124. switch (field.type) {
  125. case "text":
  126. returnValue = (
  127. <div
  128. className={"form-group " + extraClasses}
  129. key={"cloudField_" + field.name}
  130. >
  131. <h3>{field.label + (field.required ? " *" : "")}</h3>
  132. <input
  133. type="text"
  134. placeholder={field.label + (field.required ? " *" : "")}
  135. onChange={(e) => this.handleOptionsFieldChange(e, field)}
  136. value={this.state.destination_environment[field.name]}
  137. />
  138. </div>
  139. )
  140. break;
  141. case "password":
  142. returnValue = (
  143. <div
  144. className={"form-group " + extraClasses}
  145. key={"cloudField_" + field.name}
  146. >
  147. <h3>{field.label + (field.required ? " *" : "")}</h3>
  148. <input
  149. type="password"
  150. placeholder={field.label + (field.required ? " *" : "")}
  151. onChange={(e) => this.handleOptionsFieldChange(e, field)}
  152. value={this.state.destination_environment[field.name]}
  153. />
  154. </div>
  155. )
  156. break;
  157. case "dropdown":
  158. returnValue = (
  159. <div
  160. className={"form-group " + extraClasses}
  161. key={"cloudField_" + field.name}
  162. >
  163. <h3>{field.label + (field.required ? " *" : "")}</h3>
  164. <Dropdown
  165. options={field.options}
  166. onChange={(e) => this.handleOptionsFieldChange(e, field)}
  167. placeholder={field.label + (field.required ? " *" : "")}
  168. value={this.state.destination_environment[field.name]}
  169. />
  170. </div>
  171. )
  172. break;
  173. case "switch-radio":
  174. let fields = ""
  175. field.options.forEach((option) => {
  176. if (option.value == this.state.currentCloudData[field.name]) {
  177. fields = option.fields.map((optionField) => this.renderField(optionField))
  178. }
  179. })
  180. let radioOptions = field.options.map((option, key) => (
  181. <div key={"radio_option_" + key} className={s.radioOption}>
  182. <input
  183. type="radio"
  184. value={option.value}
  185. id={option.name}
  186. checked={option.value == this.state.destination_environment[field.name]}
  187. onChange={(e) => this.handleOptionsFieldChange(e, field)}
  188. /> <label htmlFor={option.name}>{option.label}</label>
  189. </div>
  190. )
  191. )
  192. returnValue = (
  193. <div key={"cloudField_" + field.name}>
  194. <div className="form-group switch-radio" key={"cloudField_" + field.name}>
  195. { radioOptions }
  196. </div>
  197. <div></div>
  198. {fields}
  199. </div>
  200. )
  201. break;
  202. default:
  203. break
  204. }
  205. return returnValue
  206. }
  207. renderOptionsFields(fields) {
  208. if (this.state.currentCloudData == null) {
  209. this.setState({ currentCloudData: {} })
  210. }
  211. if (!this.state.isConnecting) {
  212. let optionFields = fields.map(field => this.renderField(field), this)
  213. return (
  214. <div className={s.optionsFieldsContainer}>
  215. {optionFields}
  216. </div>
  217. )
  218. } else {
  219. return (
  220. <div className={s.connecting}>
  221. <div className={s.loadingImg}></div>
  222. <div className={s.text}>Connecting ...</div>
  223. </div>)
  224. }
  225. }
  226. render() {
  227. let toggleAdvancedBtn = (<button
  228. onClick={(e) => this.toggleAdvancedOptions(e)}
  229. className={s.toggleAdvancedBtn + " wire"}
  230. >
  231. {this.state.showAdvancedOptions ? "Hide" : "Show"} Advanced Options
  232. </button>)
  233. return (
  234. <div className={s.root}>
  235. <div className={s.container}>
  236. <div className={s.containerCenter}>
  237. {this.renderOptionsFields(this.state.targetCloud.cloudRef["import_" + this.state.migrationType].fields)}
  238. </div>
  239. {toggleAdvancedBtn}
  240. </div>
  241. </div>
  242. );
  243. }
  244. }
  245. export default withStyles(WizardOptions, s);