step1_controller.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. var arrayUtils = require('utils/array_utils');
  20. /**
  21. * @typedef {Em.Object} StackType
  22. * @property {string} stackName
  23. * @property {App.Stack[]} stacks
  24. * @property {boolean} isSelected
  25. * @property {boolean} defaultStackAllowedToSelect
  26. */
  27. /**
  28. * @type {Em.Object}
  29. */
  30. var StackType = Em.Object.extend({
  31. stackName: '',
  32. stacks: [],
  33. isSelected: Em.computed.someBy('stacks', 'isSelected', true),
  34. defaultStackAllowedToSelect: Em.computed.equal('stacks.length', 1),
  35. visibleStacks: function () {
  36. var stacks = this.get('stacks');
  37. return this.get('defaultStackAllowedToSelect') ? stacks : stacks.filterProperty('stackDefault', false);
  38. }.property('defaultStackAllowedToSelect', 'stacks.[]')
  39. });
  40. App.WizardStep1Controller = Em.Controller.extend({
  41. name: 'wizardStep1Controller',
  42. /**
  43. * Skip repo-validation
  44. *
  45. * @type {bool}
  46. */
  47. skipValidationChecked: false,
  48. /**
  49. * @type {App.Stack}
  50. */
  51. selectedStack: Em.computed.findBy('content.stacks', 'isSelected', true),
  52. /**
  53. * @type {App.ServiceSimple[]}
  54. */
  55. servicesForSelectedStack: Em.computed.filterBy('selectedStack.stackServices', 'isHidden', false),
  56. /**
  57. * Some network issues exist if there is no stack with <code>stackDefault</code> = false
  58. *
  59. * @type {boolean}
  60. */
  61. networkIssuesExist: Em.computed.everyBy('content.stacks', 'stackDefault', true),
  62. optionsToSelect: {
  63. 'usePublicRepo': {
  64. index: 0,
  65. isSelected: true
  66. },
  67. 'useLocalRepo': {
  68. index: 1,
  69. isSelected: false,
  70. 'uploadFile': {
  71. index: 0,
  72. name: 'uploadFile',
  73. file: '',
  74. hasError: false,
  75. isSelected: true
  76. },
  77. 'enterUrl': {
  78. index: 1,
  79. name: 'enterUrl',
  80. url: '',
  81. placeholder: Em.I18n.t('installer.step1.useLocalRepo.enterUrl.placeholder'),
  82. hasError: false,
  83. isSelected: false
  84. }
  85. }
  86. },
  87. /**
  88. * Checks if user selected to input url or upload file but didn't do it
  89. * true - url-radio is checked but url-field is empty
  90. * - file-radio is checked but file is not selected
  91. * false - otherwise
  92. *
  93. * @type {boolean}
  94. */
  95. readInfoIsNotProvided: function () {
  96. var useLocalRepo = this.get('optionsToSelect.useLocalRepo');
  97. if(Em.get(useLocalRepo, 'uploadFile.isSelected')) {
  98. return !Em.get(useLocalRepo, 'uploadFile.file');
  99. }
  100. if (Em.get(useLocalRepo, 'enterUrl.isSelected')) {
  101. return !Em.get(useLocalRepo, 'enterUrl.url');
  102. }
  103. return false;
  104. }.property('optionsToSelect.useLocalRepo.isSelected', 'optionsToSelect.useLocalRepo.uploadFile.isSelected',
  105. 'optionsToSelect.useLocalRepo.uploadFile.file', 'optionsToSelect.useLocalRepo.enterUrl.url'),
  106. /**
  107. * List of stacks grouped by <code>stackNameVersion</code>
  108. *
  109. * @type {StackType[]}
  110. */
  111. availableStackTypes: function () {
  112. var stacks = this.get('content.stacks');
  113. return stacks ? stacks.mapProperty('stackNameVersion').uniq().sort().reverse().map(function (stackName) {
  114. return StackType.create({
  115. stackName: stackName,
  116. stacks: stacks.filterProperty('stackNameVersion', stackName).sort(arrayUtils.sortByIdAsVersion).reverse()
  117. })
  118. }) : [];
  119. }.property('content.stacks.@each.stackNameVersion'),
  120. /**
  121. * @type {StackType}
  122. */
  123. selectedStackType: Em.computed.findBy('availableStackTypes', 'isSelected', true),
  124. /**
  125. * Load selected file to current page content
  126. */
  127. readVersionInfo: function () {
  128. var data = {};
  129. var isXMLdata = false;
  130. if (this.get("optionsToSelect.useLocalRepo.enterUrl.isSelected")) {
  131. var url = this.get("optionsToSelect.useLocalRepo.enterUrl.url");
  132. data = {
  133. VersionDefinition: {
  134. version_url: url
  135. }
  136. };
  137. App.db.setLocalRepoVDFData(url);
  138. }
  139. else {
  140. if (this.get("optionsToSelect.useLocalRepo.uploadFile.isSelected")) {
  141. isXMLdata = true;
  142. // load from file browser
  143. data = this.get("optionsToSelect.useLocalRepo.uploadFile.file");
  144. App.db.setLocalRepoVDFData(data);
  145. }
  146. }
  147. return App.router.get('installerController').postVersionDefinitionFile(isXMLdata, data);
  148. },
  149. /**
  150. * On click handler for removing OS
  151. */
  152. removeOS: function (event) {
  153. if (this.get('selectedStack.useRedhatSatellite')) {
  154. return;
  155. }
  156. var osToRemove = event.context;
  157. Em.set(osToRemove, 'isSelected', false);
  158. },
  159. /**
  160. * On click handler for adding new OS
  161. */
  162. addOS: function (event) {
  163. var osToAdd = event.context;
  164. Em.set(osToAdd, 'isSelected', true);
  165. },
  166. /**
  167. * Use Local Repo if some network issues exist
  168. */
  169. onNetworkIssuesExist: function() {
  170. if (this.get('networkIssuesExist')) {
  171. this.get('content.stacks').forEach(function (stack) {
  172. stack.setProperties({
  173. usePublicRepo: false,
  174. useLocalRepo: true
  175. });
  176. stack.cleanReposBaseUrls();
  177. });
  178. }
  179. }.observes('networkIssuesExist'),
  180. /**
  181. * Select stack with field equal to the value
  182. * Example:
  183. * <pre>
  184. * selectStackBy('id', 'HDP-2.5-2.5.0.0'); // select stack with id = 'HDP-2.5-2.5.0.0'
  185. * selectStackBy('stackNameVersion', 'HDP-2.5'); // select first stack with stackNameVersion = 'HDP-2.5'
  186. * </pre>
  187. *
  188. * @param {string} field
  189. * @param {string} value
  190. */
  191. selectStackBy: function (field, value) {
  192. this.get('content.stacks').setEach('isSelected', false);
  193. this.get('content.stacks').findProperty(field, value).set('isSelected', true);
  194. },
  195. /**
  196. * Restore base urls for selected stack when user select to use public repository
  197. */
  198. usePublicRepo: function () {
  199. var selectedStack = this.get('selectedStack');
  200. if (selectedStack) {
  201. selectedStack.setProperties({
  202. useRedhatSatellite: false,
  203. usePublicRepo: true,
  204. useLocalRepo: false
  205. });
  206. selectedStack.restoreReposBaseUrls();
  207. }
  208. },
  209. /**
  210. * Clean base urls for selected stack when user select to use local repository
  211. */
  212. useLocalRepo: function () {
  213. var selectedStack = this.get('selectedStack');
  214. if (selectedStack) {
  215. selectedStack.setProperties({
  216. usePublicRepo: false,
  217. useLocalRepo: true
  218. });
  219. selectedStack.cleanReposBaseUrls();
  220. }
  221. },
  222. /**
  223. * Restores url value to be its default value.
  224. * @method doRestoreDefaultValue
  225. */
  226. doRestoreDefaultValue: function (event) {
  227. var repo = event.contexts[0];
  228. repo.set('baseUrl', repo.get('latestBaseUrl'));
  229. },
  230. /**
  231. * Restores url value to empty string.
  232. * @method doRestoreToEmpty
  233. */
  234. doRestoreToEmpty: function (event) {
  235. var repo = event.contexts[0];
  236. repo.set('baseUrl', '');
  237. },
  238. /**
  239. * Click-handler for left-tabs with stack types
  240. * Select first available stack with stackName equal to chosen
  241. *
  242. * @param {{context: StackType}} event
  243. */
  244. selectRepoInList: function (event) {
  245. var id = this.get('availableStackTypes').findProperty('stackName', event.context.stackName).get('stacks.firstObject.id');
  246. this.selectStackBy('id', id);
  247. },
  248. /**
  249. * Click-handler for StackVersion-tabs
  250. *
  251. * @param {{context: App.Stack}} event
  252. */
  253. changeVersion: function (event) {
  254. this.selectStackBy('id', event.context.get('id'));
  255. },
  256. /**
  257. * Show popup with options to upload new version
  258. *
  259. * @returns {App.ModalPopup}
  260. */
  261. uploadVdf: function () {
  262. return App.ModalPopup.show({
  263. controller: this,
  264. header: Em.I18n.t('installer.step1.addVersion.title'),
  265. primary: Em.I18n.t('installer.step1.useLocalRepo.readButton'),
  266. disablePrimary: Em.computed.alias('controller.readInfoIsNotProvided'),
  267. /**
  268. * Try to read version info from the url or file (if provided)
  269. */
  270. onPrimary: function () {
  271. var controller = this.get('controller');
  272. controller.readVersionInfo().done(function (response) {
  273. // load successfully, so make this local stack repo as selectedStack
  274. var newStackId = response.stackNameVersion + '-' + response.actualVersion;
  275. var oldStackNameVersion = controller.get('selectedStack.stackNameVersion');
  276. controller.selectStackBy('id', newStackId);
  277. if (oldStackNameVersion && oldStackNameVersion !== response.stackNameVersion) {
  278. App.showAlertPopup(Em.I18n.t('common.warning'), Em.I18n.t('installer.step1.addVersion.stackChanged.popup.body').format(oldStackNameVersion, response.stackNameVersion));
  279. }
  280. Ember.run.next(function () {
  281. $("[rel=skip-validation-tooltip]").tooltip({placement: 'right'});
  282. $("[rel=use-redhat-tooltip]").tooltip({placement: 'right'});
  283. });
  284. });
  285. this.restoreUploadOptions();
  286. this._super();
  287. },
  288. /**
  289. * Disable url/file fields on popup-close
  290. */
  291. onSecondary: function () {
  292. this.restoreUploadOptions();
  293. this._super();
  294. },
  295. /**
  296. * Disable url/file fields on popup-close
  297. */
  298. onClose: function () {
  299. this.restoreUploadOptions();
  300. this._super();
  301. },
  302. /**
  303. * Deselect file/url radio
  304. */
  305. restoreUploadOptions: function () {
  306. this.set('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected', false);
  307. this.set('controller.optionsToSelect.useLocalRepo.enterUrl.url', '');
  308. this.set('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected', true);
  309. this.set('controller.optionsToSelect.useLocalRepo.uploadFile.file', '');
  310. },
  311. bodyClass: Em.View.extend({
  312. controller: this,
  313. templateName: require('templates/wizard/step1/vdf_upload'),
  314. /**
  315. * Wrapper for 'upload-file' elements
  316. *
  317. * @type {Em.View}
  318. */
  319. uploadFileView: Em.View.extend({
  320. classNames: ['clearfix'],
  321. /**
  322. * Checkbox for Use local Repo > Upload VDF file
  323. *
  324. * @type {Ember.Checkbox}
  325. */
  326. uploadFileRadioButton: Em.Checkbox.extend({
  327. attributeBindings: ['type', 'checked'],
  328. checked: Em.computed.alias('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected'),
  329. type: 'radio'
  330. }),
  331. /**
  332. * Is File API available
  333. *
  334. * @type {bool}
  335. */
  336. isFileApi: window.File && window.FileReader && window.FileList,
  337. /**
  338. * Upload file is disabled when some stack is selected or url-field is selected
  339. *
  340. * @type {boolean}
  341. */
  342. fileBrowserDisabled: Em.computed.alias('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected'),
  343. /**
  344. * Input to select vdf-file
  345. *
  346. * @type {Em.View}
  347. */
  348. fileInputView: Em.View.extend({
  349. template: Em.Handlebars.compile('<input type="file" {{bindAttr class="controller.optionsToSelect.useLocalRepo.enterUrl.isSelected:disabled"}} />'),
  350. classNames: ['vdf-input-indentation'],
  351. change: function (e) {
  352. var self = this;
  353. if (e.target.files && e.target.files.length === 1) {
  354. var file = e.target.files[0];
  355. var reader = new FileReader();
  356. reader.onload = (function () {
  357. return function (event) {
  358. self.set('controller.optionsToSelect.useLocalRepo.uploadFile.file', event.target.result);
  359. };
  360. })(file);
  361. reader.readAsText(file);
  362. }
  363. }
  364. }),
  365. click: function () {
  366. if (!this.set('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected')) {
  367. this.set('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected', false);
  368. this.set('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected', true);
  369. this.set('controller.optionsToSelect.useLocalRepo.enterUrl.hasError', false);
  370. this.set('controller.optionsToSelect.useLocalRepo.uploadFile.hasError', false);
  371. }
  372. }
  373. }),
  374. /**
  375. * Wrapper for 'enter-url' elements
  376. *
  377. * @type {Em.View}
  378. */
  379. enterUrlView: Em.View.extend({
  380. /**
  381. * Url-field is disable when some stack is selected or upload file is selected
  382. *
  383. * @type {boolean}
  384. */
  385. enterUrlFieldDisabled: Em.computed.alias('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected'),
  386. /**
  387. * Input for file upload
  388. *
  389. * @type {Em.TextField}
  390. */
  391. enterUrlField: Em.TextField.extend({
  392. classNameBindings: [':input-block-level', 'controller.optionsToSelect.useLocalRepo.uploadFile.isSelected:disabled']
  393. }),
  394. /**
  395. * Checkbox for Use local Repo > Enter Url of VDF file
  396. *
  397. * @type {Ember.Checkbox}
  398. */
  399. enterUrlRadioButton: Em.Checkbox.extend({
  400. attributeBindings: [ 'type', 'checked' ],
  401. checked: Em.computed.alias('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected'),
  402. type: 'radio',
  403. }),
  404. click: function () {
  405. if (!this.set('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected')) {
  406. this.set('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected', true);
  407. this.set('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected', false);
  408. this.set('controller.optionsToSelect.useLocalRepo.enterUrl.hasError', false);
  409. this.set('controller.optionsToSelect.useLocalRepo.uploadFile.hasError', false);
  410. }
  411. }
  412. })
  413. })
  414. });
  415. }
  416. });