http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/stackVersionPage.html ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/stackVersionPage.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/stackVersionPage.html index f3f2d86..6134535 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/stackVersionPage.html +++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/stackVersionPage.html @@ -19,193 +19,194 @@ <div class="clearfix"> <ol class="breadcrumb pull-left"> <li><a href="#/stackVersions">{{'common.versions' | translate}}</a></li> - <li class="active" ng-if="editController">{{displayName}} <span class="sub-text">({{repoVersionFullName}})</span></li> + <li class="active" ng-if="editController">{{displayName}} <span + class="sub-text">({{repoVersionFullName}})</span></li> <li class="active" ng-if="createController">{{'versions.register' | translate}}</li> </ol> - <div class="pull-right top-margin-4" ng-if="editController"> - <a href="#/stackVersions/create" class="btn btn-primary"> - <span class="glyphicon glyphicon-plus"></span> - {{'versions.register' | translate}} - </a> + <div class="pull-right deregister-button" ng-switch="deleteEnabled" ng-if="editController"> + <button ng-switch-when="false" class="btn disabled btn-default" tooltip="Cannot delete version already installed.">{{'versions.deregister' | translate}}</button> + <button ng-switch-when="true" class="btn btn-danger" ng-click="delete()">{{'versions.deregister' | translate}}</button> </div> </div> <hr> -<div id="upload-definition-file-panel" ng-if="createController"> +<!-- left tabs begins -->⨠+<div class="col-sm-2" id="list-stack-id" ng-if="createController">⨠+ <ul class="nav nav-tabs tabs-left"> ⨠+ <li ng-repeat="stack in stackIds" ng-click="onStackIdChange()" ng-class="{'active' : stack.isSelected}"> + <a href="javascript:void(0);">{{stack.stackNameVersion}}</a> + </li>⨠+ </ul>⨠+</div>⨠- <div class="col-sm-12 option-radio clearfix"> - <input type="radio" ng-model="selectedOption.index" value="1" ng-change="togglePublicLocalOptionSelect()"> {{'versions.usePublic' | translate}} - </div> +<div ng-class="{'col-sm-10': createController}"> + <div class="tab-content"> + <div class="panel panel-default details-panel"> + <div class="panel-body"> + <div class="col-sm-3 .pull-left" id="current-stack-details" ng-if="editController">⨠+ <table class='table table-borderless alert alert-info'> + <tr> + <td>{{'common.stack' | translate}}</td> + <td><strong>{{activeStackVersion.stackNameVersion}}</strong></td> + </tr> + <tr> + <td>{{'common.name' | translate}}</td> + <td><strong>{{activeStackVersion.displayName}}</strong></td> + </tr> + <tr> + <td>{{'common.version' | translate}}</td> + <td><strong>{{activeStackVersion.actualVersion}}</strong></td> + </tr> + </table> + </div> - <div class="clearfix stack-version-selection"> - <div class="col-sm-3 select-version-label" ng-class="{'disabled': selectedOption.index==2}"> - {{'versions.selectVersion' | translate}} - </div> - <div class="col-sm-7 right-stack-info"> - <div class="repo-list-button btn-group" dropdown> - <button class="btn btn-primary dropdown-toggle" data-toggle="dropdown" ng-disabled="(selectedOption.index==2)">{{selectedPublicRepoVersion.displayNameFull}} <span class="caret"></span></button> - <ul class="dropdown-menu available-repos-dropdown" ng-if="availableStackRepoList"> - <li ng-repeat="version in availableStackRepoList" class="" ng-if="version.displayNameFull !== selectedPublicRepoVersion.displayNameFull"> - <a ng-click="selectRepoInList()">{{version.displayNameFull}}</a></li> - </ul> - <ul class="dropdown-menu available-repos-dropdown" ng-if="!availableStackRepoList || availableStackRepoList.length == 0"> - <li class="disabled"><a>{{'versions.selectVersionEmpty' | translate}}</a></li> - </ul> + <div class="version-info" ng-if="createController"> + <div class="btn-group" dropdown> + <button type="button" data-toggle="dropdown" class="btn dropdown-toggle btn-info"> + {{activeStackVersion.stackNameRepositoryVersion}} + <span class="caret"></span> + </button> + <ul class="dropdown-menu"> + <li ng-repeat="version in allVersions" ng-click="setActiveVersion()" ng-if="version.visible"> + <a href="javascript:void(0);"> + {{version.stackNameRepositoryVersion}} + <span ng-if="version.stackDefault">{{'versions.defaultVersion' | translate}}</span> + </a> + </li> + <li> + <a href="javascript:void(0);" ng-click="addVersion()"> + {{'versions.addVersion' | translate}} ... + </a> + </li> + </ul> + </div> + </div> + <div class="version-contents-section" ng-class="{'version-contents-section-register-version': createController}"> + <table class="table table-striped table-condensed"> + <tr ng-repeat="service in activeStackVersion.services"> + <td class="col-sm-4">{{service.displayName}}</td> + <td class="col-sm-8">{{service.version}}</td> + </tr> + </table> + </div> </div> </div> </div> +</div> - <div class="col-sm-12 option-radio clearfix"> - <input type="radio" ng-model="selectedOption.index" value="2" ng-change="togglePublicLocalOptionSelect()"> {{'versions.useLocal' | translate}} - </div> +<div id="upload-definition-file-panel" ng-if="createController"> - <div class="clearfix register-version-options"> - <div class="col-sm-5 option-radio-button"> - <label class="option-label"> - <input type="radio" ng-model="selectedLocalOption.index" value="3" ng-change="toggleOptionSelect()" ng-disabled="(selectedOption.index==1)"> {{'versions.uploadFile' | translate}} - </label> - </div> - <div class="col-sm-7"> - <input type="file" class="choose-file-input" ng-model="option1.file" ng-disabled="(selectedOption.index==1) || !(selectedLocalOption.index==3)" - onchange="angular.element(this).scope().onFileSelect(this)"/> - </div> + <div class="col-sm-12 big-radio clearfix"> + <input type="radio" ng-model="selectedOption.index" value="1" ng-change="togglePublicLocalOptionSelect()" ng-disabled="networkLost || useRedhatSatellite"> + {{'versions.usePublic' | translate}} + <a id="public-disabled-link" href="javascript:void(0);" ng-if="networkLost" ng-click="showPublicRepoDisabledDialog()">{{'versions.networkIssues.networkLost'| translate}}</a> </div> - <div class="clearfix register-version-options bottom-margin"> - <div class="col-sm-5 option-radio-button"> - <label class="option-label"> - <input type="radio" ng-model="selectedLocalOption.index" value="4" ng-change="toggleOptionSelect()" ng-disabled="(selectedOption.index==1)"> {{'versions.enterURL' | translate}} - </label> - </div> - <div class="col-sm-7"> - <div class="form-group {{option2.name}}" ng-class="{'has-error': option2.url.hasError }"> - <div class=""><input type="text" class="form-control" ng-model="option2.url" ng-change="clearOptionsError()" ng-disabled="(selectedOption.index==1) || !(selectedLocalOption.index==4)"></div> - </div> - </div> - <div class="col-sm-12 read-info-button"> - <button class="btn btn-primary pull-right" ng-model="button" ng-click="readVersionInfo()" - ng-disabled="readInfoButtonDisabled()">{{'versions.readInfo' | translate}}</button> - </div> + <div class="col-sm-12 big-radio clearfix"> + <input type="radio" ng-model="selectedOption.index" value="2" ng-change="togglePublicLocalOptionSelect()"> + {{'versions.useLocal' | translate}} </div> </div> -<accordion close-others="false" class="col-sm-2 left-menu-all-repos" ng-if="editController"> - <accordion-group ng-repeat="stackVersion in stackVersions" is-open="stackVersion.isOpened"> - <accordion-heading> - <div class="row stack-version-title"> - <i class="glyphicon glyphicon-chevron-right" ng-class="{'opened': stackVersion.isOpened}"></i> - {{stackVersion.name}} - </div> - </accordion-heading> - <table class="table repos-table"> - <tbody> - <tr ng-repeat="repo in stackVersion.repos"> - <td class="repos-td" ng-class="{'active': repo.isActive}"> - <a href="#/stackVersions/{{repo.stack_name}}/{{repo.repository_version}}/edit">{{repo.repository_version}}</a> - </td> - </tr> - </tbody> - </table> - </accordion-group> - <div class="alert alert-info" ng-show="stackVersions && !stackVersions.length"> - {{'versions.contents.empty' | translate}} - </div> -</accordion> +<div class="clearfix bottom-margin"></div> -<form ng-class="{'col-sm-10': editController, 'visible': !allInfoCategoriesBlank()}" class="form-horizontal register-version-form hide-soft" role="form" name="repoRegForm" novalidate> - <div class="panel panel-default details-panel"> - <div class="panel-heading"> - <h3 class="panel-title">{{'common.details' | translate}}</h3> - <div class="pull-right deregister-button" ng-switch="deleteEnabled" ng-if="editController"> - <button ng-switch-when="false" class="btn disabled btn-default" tooltip="Cannot delete version already installed.">{{'versions.deregister' | translate}}</button> - <button ng-switch-when="true" class="btn btn-danger" ng-click="delete()">{{'versions.deregister' | translate}}</button> - </div> - </div> - <div class="panel-body"> - <div class="col-sm-5 version-info-section"> - <div class="clearfix"> - <label class="control-label col-sm-7">{{'versions.details.stackName' | translate}}</label> - <div class="version-info col-sm-3">{{stackNameVersion}}</div> - <div class="col-sm-2 patch-icon" ng-if="isPatch"><span class="glyphicon glyphicon-tree-deciduous"></span>{{'versions.patch' | translate}}</div> - </div> - <div class="clearfix"> - <label class="control-label col-sm-7">{{'versions.details.displayName' | translate}}</label> - <div class="version-info col-sm-5">{{displayName}}</div> - </div> - <div class="clearfix"> - <label class="control-label col-sm-7">{{'versions.details.version' | translate}}</label> - <div class="version-info col-sm-5">{{actualVersion}}</div> - </div> - </div> - <div class="col-sm-6 version-contents-section"> - <div class="alert alert-info hide-soft" ng-class="{'visible' : !services || !services.length}" role="alert">{{'versions.contents.empty' | translate}}</div> - <div class="clearfix" ng-repeat="service in services"> - <div class="version-info col-sm-9">{{service.displayName}} ({{service.version}})</div> - </div> - </div> - </div> - </div> +<form ng-class="{'visible': !allInfoCategoriesBlank()}" class="form-horizontal register-version-form hide-soft" + role="form" name="repoRegForm" novalidate> <div class="panel panel-default repos-panel"> <div class="panel-heading"> <h3 class="panel-title"> - {{'versions.repos' | translate}} - <button ng-show="supports.addingNewRepository" class="btn btn-primary pull-right btn-xs pull-up" ng-click="addRepository()"> - <span class="glyphicon glyphicon-plus"></span> - {{'common.add' | translate:'{ term: "Repository" }'}} - </button> + {{'versions.repos' | translate}} + <button ng-show="supports.addingNewRepository" class="btn btn-primary pull-right btn-xs pull-up" + ng-click="addRepository()"> + <span class="glyphicon glyphicon-plus"></span> + {{'common.add' | translate:'{ term: "Repository" }'}} + </button> </h3> </div> <div class="panel-body"> - <div class="alert alert-info" role="alert">{{'versions.alerts.baseURLs' | translate}}</div> - <div class="alert alert-warning hide-soft" ng-class="{'visible' : hasValidationErrors()}" role="alert">{{'versions.alerts.validationFailed' | translate}}</div> - <div class="border-bottom bottom-margin clearfix"> - <div class="col-sm-2"><h5><label>{{'versions.os' | translate}}</label></h5></div> - <div class="name-label-adjust col-sm-2"><h5><label>{{'common.name' | translate}}</label></h5></div> - <div class="col-sm-7"><h5><label >{{'versions.baseURL' | translate}}</label></h5></div> - </div> - <div class="alert alert-info hide-soft" ng-class="{'visible' : !osList || !osList.length}" role="alert">{{'versions.contents.empty' | translate}}</div> - <div class="" ng-repeat="os in osList"> - <div ng-if="os.selected==true"> - <div class="clearfix border-bottom bottom-margin"> - <!-- show selected os in list table--> - <div class="col-sm-2 os-type-label"> - <label>{{os.OperatingSystems.os_type}}</label> - </div> - <div class="col-sm-9"> - <div class="form-group {{repository.Repositories.repo_name}}" ng-class="{'has-error': repository.hasError }" ng-repeat="repository in os.repositories"> - <label class="repo-name-label control-label col-sm-3">{{repository.Repositories.repo_name}}</label> - <div class="col-sm-9"><input type="text" class="form-control" ng-model="repository.Repositories.base_url" - ng-change="clearError()" ng-disabled="useRedhatSatellite"></div> - </div> - </div> - <div class="col-sm-1 remove-icon" ng-click="removeOS()" ng-class="{'disabled' : useRedhatSatellite}"><span class="glyphicon glyphicon-minus"></span>{{'common.controls.remove' | translate}}</div> + <div class="panel-inner"> + <div class="alert alert-info" role="alert">{{'versions.alerts.baseURLs' | translate}}</div> + <div class="alert alert-warning hide-soft" ng-class="{'visible' : hasValidationErrors()}" role="alert"> + {{'versions.alerts.validationFailed' | translate}} + </div> + <div class="clearfix repo-table-title row-fluid"> + <div class="col-sm-2" id="os-label"><label>{{'versions.os' | translate}}</label></div> + <div class="col-sm-2" id="name-label-adjust"><label>{{'common.name' | translate}}</label></div> + <div class="col-sm-6" id="repo-base-url-label"><label>{{'versions.baseURL' | translate}} </label></div> + <div class="btn-group pull-right tooltip-wrapper" + tooltip="{{(isAddOsButtonDisabled() && !useRedhatSatellite)? ('versions.alerts.allOsAdded' | translate) : ''}}" + dropdown> + <button class="btn add-os-button dropdown-toggle" ng-disabled="isAddOsButtonDisabled()"> + <i class="fa fa-plus" aria-hidden="true"></i> {{'common.add' | translate}} <span + class="caret"></span></button> + <ul class="dropdown-menu" ng-class="{'hidden': hasNotDeletedRepo()}"> + <li ng-repeat="os in osList"><a ng-if="os.selected==false" ng-click="addOS($event)">{{os.OperatingSystems.os_type}}</a> + </li> + </ul> </div> + </div> - </div> - <div class="btn-group pull-right" dropdown> - <button class="btn dropdown-toggle" ng-disabled="isAddOsButtonDisabled()"> - <span class="glyphicon glyphicon-plus"></span> {{'common.add' | translate: '{term: constants.os}'}} <span class="caret"></span></button> - <ul class="dropdown-menu" ng-class="{'hidden': hasNotDeletedRepo()}"> - <li ng-repeat="os in osList"><a ng-if="os.selected==false" ng-click="addOS()">{{os.OperatingSystems.os_type}}</a></li> - </ul> + <div class="alert alert-info hide-soft" ng-class="{'visible' : !osList || !osList.length}" role="alert"> + {{'versions.contents.empty' | translate}} </div> - <div class="clearfix"> - <div class="col-sm-9" id="skip-validation"> - <div class="checkbox"> - <label> - <input type="checkbox" ng-model="skipValidation" ng-change="clearErrors()" ng-disabled="useRedhatSatellite"> - {{'versions.skipValidation' | translate}} <span class="glyphicon glyphicon-question-sign" tooltip-html-unsafe="{{'versions.alerts.skipValidationWarning' | translate}}"></span> - </label> + <div class="" ng-repeat="os in osList"> + <div ng-if="os.selected==true"> + <div class="clearfix border-bottom"> + <!-- show selected os in list table--> + <div class="col-sm-2 os-type-label"> + <label>{{os.OperatingSystems.os_type}}</label> + </div> + <div class="col-sm-9"> + <div class="form-group repo-name-url {{repository.Repositories.repo_name}}" + ng-class="{'has-error': repository.hasError }" ng-repeat="repository in os.repositories"> + <span class="repo-name-label control-label col-sm-3">{{repository.Repositories.repo_id}}</span> + <div class="col-sm-7 repo-url"> + <input type="text" class="form-control" + placeholder="{{(repository.Repositories.repo_name.indexOf('UTILS') < 0 )?('versions.repository.placeholder' | translate) : ''}}" + ng-model="repository.Repositories.base_url" + ng-change="onRepoUrlChange(repository)" ng-disabled="useRedhatSatellite"> + </div> + <i class="fa fa-undo orange-icon cursor-pointer" + ng-if="selectedOption.index == 1 && repository.Repositories.base_url != repository.Repositories.initial_base_url + || selectedOption.index == 2 && repository.Repositories.base_url != '' + || editController && repository.Repositories.base_url != repository.Repositories.initial_base_url" + ng-click="undoChange(repository)" + tooltip-html-unsafe="{{'common.undo' | translate}}" + aria-hidden="true"></i> + </div> + </div> + <div class="col-sm-1 remove-icon" ng-click="removeOS()" ng-class="{'disabled' : useRedhatSatellite}"><i + class="fa fa-minus" aria-hidden="true"></i>{{'common.controls.remove' | translate}} + </div> + </div> </div> </div> - <div class="col-sm-9" id="use-redhat"> - <div class="checkbox"> - <label> - <input type="checkbox" ng-model="useRedhatSatellite" ng-change="clearErrors()"> - {{'versions.useRedhatSatellite.title' | translate}} <span class="glyphicon glyphicon-question-sign" tooltip-html-unsafe="{{'versions.alerts.useRedhatSatelliteWarning' | translate}}"></span> - </label> + <div class="clearfix advanced-radio-buttons"> + <div class="col-sm-9" id="skip-validation"> + <div class="checkbox"> + <label> + <input type="checkbox" ng-model="skipValidation" ng-change="clearErrors()" + ng-disabled="useRedhatSatellite"> + <span ng-class="{'disabled' : useRedhatSatellite}">{{'versions.skipValidation' | translate}}</span> + <i class="fa fa-question-circle" + tooltip-html-unsafe="{{'versions.alerts.skipValidationWarning' | translate}}" aria-hidden="true"></i> + </label> + </div> + </div> + <div class="col-sm-9" id="use-redhat"> + <div class="checkbox"> + <label> + <input type="checkbox" ng-model="useRedhatSatellite" ng-change="clearErrors()" + ng-disabled="isPublicRepoSelected()"> + <span ng-class="{'disabled' : isPublicRepoSelected()}" + tooltip="{{(isPublicRepoSelected())? ('versions.useRedhatSatellite.disabledMsg' | translate) : ''}}">{{'versions.useRedhatSatellite.title' | translate}}</span> + <i class="fa fa-question-circle" + tooltip-html-unsafe="{{'versions.alerts.useRedhatSatelliteWarning' | translate}}" + aria-hidden="true"></i> + </label> + </div> </div> </div> </div> @@ -213,7 +214,8 @@ </div> <div class="col-sm-12"> <button class="btn btn-primary pull-right left-margin" ng-click="save()" - ng-disabled="isSaveButtonDisabled()">{{'common.controls.save' | translate}}</button> + ng-disabled="isSaveButtonDisabled()">{{'common.controls.save' | translate}} + </button> <button class="btn btn-default pull-right" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button> </div> </form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/assets/test/tests.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js index c654dac..005c97b 100644 --- a/ambari-web/app/assets/test/tests.js +++ b/ambari-web/app/assets/test/tests.js @@ -119,6 +119,7 @@ var files = [ 'test/controllers/experimental_test', 'test/controllers/wizard_test', 'test/controllers/wizard/step0_test', + 'test/controllers/wizard/step1_test', 'test/controllers/wizard/step2_test', 'test/controllers/wizard/step3_test', 'test/controllers/wizard/step4_test', http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/controllers/installer.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/installer.js b/ambari-web/app/controllers/installer.js index 43a5e4a..3792d8a 100644 --- a/ambari-web/app/controllers/installer.js +++ b/ambari-web/app/controllers/installer.js @@ -322,10 +322,12 @@ App.InstallerController = App.WizardController.extend({ }, mergeChanges: function (repos, stacks) { - repos.forEach(function (repo) { + var _repos = repos || []; + var _stacks = stacks || []; + _repos.forEach(function (repo) { App.Repository.find().findProperty('id', repo.id).set('baseUrl', repo.base_url); }); - stacks.forEach(function (_stack) { + _stacks.forEach(function (_stack) { var stack = App.Stack.find().findProperty('id', _stack.id); if (stack) { stack.set('useRedhatSatellite', _stack.use_redhat_satellite); @@ -335,12 +337,9 @@ App.InstallerController = App.WizardController.extend({ setSelected: function (isStacksExistInDb) { if (!isStacksExistInDb) { - var defaultStackVersion = App.Stack.find().findProperty('stackNameVersion', App.defaultStackVersion); - if (defaultStackVersion) { - defaultStackVersion.set('isSelected', true) - } else { - App.Stack.find().objectAt(0).set('isSelected', true); - } + var stacks = App.Stack.find(); + stacks.setEach('isSelected', false); + stacks.sortProperty('id').set('lastObject.isSelected', true); } this.set('content.stacks', App.Stack.find()); App.set('currentStackVersion', App.Stack.find().findProperty('isSelected').get('stackNameVersion')); @@ -414,11 +413,11 @@ App.InstallerController = App.WizardController.extend({ }, getServerVersionSuccessCallback: function (data) { var clientVersion = App.get('version'); - var serverVersion = (data.RootServiceComponents.component_version).toString(); + var serverVersion = data.RootServiceComponents.component_version.toString(); this.set('ambariServerVersion', serverVersion); if (clientVersion) { this.set('versionConflictAlertBody', Em.I18n.t('app.versionMismatchAlert.body').format(serverVersion, clientVersion)); - this.set('isServerClientVersionMismatch', clientVersion != serverVersion); + this.set('isServerClientVersionMismatch', clientVersion !== serverVersion); } else { this.set('isServerClientVersionMismatch', false); } @@ -435,10 +434,6 @@ App.InstallerController = App.WizardController.extend({ Em.assert('Stack model is not populated', stacks.get('length')); App.db.setStacks(stacks.slice()); this.set('content.stacks', stacks); - - App.OperatingSystem.find().filterProperty('isSelected', false).forEach(function (os) { - App.serviceMapper.deleteRecord(os); - }); var repos = App.Repository.find() || []; App.db.setRepos(repos.slice()); }, @@ -495,15 +490,15 @@ App.InstallerController = App.WizardController.extend({ var props = this.getDBProperties(['masterComponentHosts', 'hosts']); var masterComponentHosts = props.masterComponentHosts, hosts = props.hosts || {}, - host_names = Em.keys(hosts); + hostNames = Em.keys(hosts); if (Em.isNone(masterComponentHosts)) { masterComponentHosts = []; } else { masterComponentHosts.forEach(function (component) { - for (var i = 0; i < host_names.length; i++) { - if (hosts[host_names[i]].id === component.host_id) { - component.hostName = host_names[i]; + for (var i = 0; i < hostNames.length; i++) { + if (hosts[hostNames[i]].id === component.host_id) { + component.hostName = hostNames[i]; break; } } @@ -527,13 +522,13 @@ App.InstallerController = App.WizardController.extend({ var props = this.getDBProperties(['slaveComponentHosts', 'hosts']); var slaveComponentHosts = props.slaveComponentHosts, hosts = props.hosts || {}, - host_names = Em.keys(hosts); + hostNames = Em.keys(hosts); if (!Em.isNone(slaveComponentHosts)) { slaveComponentHosts.forEach(function (component) { component.hosts.forEach(function (host) { - for (var i = 0; i < host_names.length; i++) { - if (hosts[host_names[i]].id === host.host_id) { - host.hostName = host_names[i]; + for (var i = 0; i < hostNames.length; i++) { + if (hosts[hostNames[i]].id === host.host_id) { + host.hostName = hostNames[i]; break; } } @@ -596,9 +591,8 @@ App.InstallerController = App.WizardController.extend({ postVersionDefinitionFileSuccessCallback: function (_data, request, dataInfo) { if (_data.resources.length && _data.resources[0].VersionDefinition) { var data = _data.resources[0]; - var self = this; // load the data info to display for details and contents panel - data.VersionDefinition.id = dataInfo.data.VersionDefinition.available; + data.VersionDefinition.id = Em.get(dataInfo, 'data.VersionDefinition.available') || data.VersionDefinition.id; var response = { id : data.VersionDefinition.id, stackVersion : data.VersionDefinition.stack_version, @@ -670,19 +664,20 @@ App.InstallerController = App.WizardController.extend({ postVersionDefinitionFileErrorCallback: function (request, ajaxOptions, error, data, params) { params.dfd.reject(data); var header = Em.I18n.t('installer.step1.useLocalRepo.uploadFile.error.title'); - var body = ""; - if(request && request.responseText){ + var body = ''; + if(request && request.responseText) { try { var json = $.parseJSON(request.responseText); body = json.message; } catch (err) {} } + App.db.setLocalRepoVDFData(undefined); App.showAlertPopup(header, body); }, getSupportedOSList: function (versionDefinition, stackInfo) { this.incrementProperty('loadStacksRequestsCounter'); - return App.ajax.send({ + return App.ajax.send({ name: 'wizard.step1.get_supported_os_types', sender: this, data: { @@ -727,9 +722,11 @@ App.InstallerController = App.WizardController.extend({ this.postVersionDefinitionFile(versionData.isXMLdata, versionData.data).done(function (versionInfo) { self.mergeChanges(data.stackInfo.repos, data.stackInfo.stacks); App.Stack.find().setEach('isSelected', false); - var stackId = versionData.data.VersionDefinition.available || versionInfo.stackNameVersion + "-" + versionInfo.actualVersion; + var stackId = Em.get(versionData, 'data.VersionDefinition.available') || versionInfo.stackNameVersion + "-" + versionInfo.actualVersion; App.Stack.find().findProperty('id', stackId).set('isSelected', true); self.setSelected(data.stackInfo.isStacksExistInDb); + }).fail(function () { + self.setSelected(data.stackInfo.isStacksExistInDb); }); } else { this.setSelected(data.stackInfo.isStacksExistInDb); @@ -781,12 +778,12 @@ App.InstallerController = App.WizardController.extend({ */ prepareRepoForSaving: function(repo) { var repoVersion = { "operating_systems": [] }; - var ambari_managed_repositories = !repo.get('useRedhatSatellite'); + var ambariManagedRepositories = !repo.get('useRedhatSatellite'); repo.get('operatingSystems').forEach(function (os, k) { repoVersion.operating_systems.push({ "OperatingSystems": { "os_type": os.get("osType"), - "ambari_managed_repositories": ambari_managed_repositories + "ambari_managed_repositories": ambariManagedRepositories }, "repositories": [] }); @@ -822,7 +819,7 @@ App.InstallerController = App.WizardController.extend({ repo.setProperties({ errorTitle: '', errorContent: '', - validation: App.Repository.validation['INPROGRESS'] + validation: App.Repository.validation.INPROGRESS }); this.set('content.isCheckInProgress', true); App.ajax.send({ @@ -860,7 +857,7 @@ App.InstallerController = App.WizardController.extend({ var os = selectedStack.get('operatingSystems').findProperty('id', data.osId); var repo = os.get('repositories').findProperty('repoId', data.repoId); if (repo) { - repo.set('validation', App.Repository.validation['OK']); + repo.set('validation', App.Repository.validation.OK); } } this.set('validationCnt', this.get('validationCnt') - 1); @@ -880,7 +877,7 @@ App.InstallerController = App.WizardController.extend({ var repo = os.get('repositories').findProperty('repoId', params.repoId); if (repo) { repo.setProperties({ - validation: App.Repository.validation['INVALID'], + validation: App.Repository.validation.INVALID, errorTitle: request.status + ":" + request.statusText, errorContent: $.parseJSON(request.responseText) ? $.parseJSON(request.responseText).message : "" }); @@ -1055,9 +1052,9 @@ App.InstallerController = App.WizardController.extend({ if (stringUtils.compareVersions(currentJDKVersion, minJDKVersion) < 0 || stringUtils.compareVersions(maxJDKVersion, currentJDKVersion) < 0) { // checks and process only minor part for now - var versionDistance = parseInt(maxJDKVersion.split('.')[1]) - parseInt(minJDKVersion.split('.')[1]); + var versionDistance = parseInt(maxJDKVersion.split('.')[1], 10) - parseInt(minJDKVersion.split('.')[1], 10); var versionsList = [minJDKVersion]; - for (var i = 1; i < (versionDistance + 1); i++) { + for (var i = 1; i < versionDistance + 1; i++) { versionsList.push("" + minJDKVersion.split('.')[0] + '.' + (+minJDKVersion.split('.')[1] + i)); } var versionsString = stringUtils.getFormattedStringFromArray(versionsList, t('or')); http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/controllers/wizard/step0_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step0_controller.js b/ambari-web/app/controllers/wizard/step0_controller.js index aa3541a..b816bd0 100644 --- a/ambari-web/app/controllers/wizard/step0_controller.js +++ b/ambari-web/app/controllers/wizard/step0_controller.js @@ -70,7 +70,7 @@ App.WizardStep0Controller = Em.Controller.extend({ * @method submit */ submit: function () { - if(App.router.nextBtnClickInProgress){ + if(App.get('router.nextBtnClickInProgress')){ return; } this.set('hasSubmitted', true); @@ -78,7 +78,7 @@ App.WizardStep0Controller = Em.Controller.extend({ App.clusterStatus.set('clusterName', this.get('content.cluster.name')); this.set('content.cluster.status', 'PENDING'); this.set('content.cluster.isCompleted', false); - App.router.nextBtnClickInProgress = true; + App.set('router.nextBtnClickInProgress', true); App.router.send('next'); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/controllers/wizard/step1_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step1_controller.js b/ambari-web/app/controllers/wizard/step1_controller.js index 3eb5d1b..b648b82 100644 --- a/ambari-web/app/controllers/wizard/step1_controller.js +++ b/ambari-web/app/controllers/wizard/step1_controller.js @@ -17,19 +17,57 @@ */ var App = require('app'); +var arrayUtils = require('utils/array_utils'); + +/** + * @typedef {Em.Object} StackType + * @property {string} stackName + * @property {App.Stack[]} stacks + * @property {boolean} isSelected + * @property {boolean} defaultStackAllowedToSelect + */ + +/** + * @type {Em.Object} + */ +var StackType = Em.Object.extend({ + stackName: '', + stacks: [], + isSelected: Em.computed.someBy('stacks', 'isSelected', true), + defaultStackAllowedToSelect: Em.computed.equal('stacks.length', 1), + visibleStacks: function () { + var stacks = this.get('stacks'); + return this.get('defaultStackAllowedToSelect') ? stacks : stacks.filterProperty('stackDefault', false); + }.property('defaultStackAllowedToSelect', 'stacks.[]') +}); App.WizardStep1Controller = Em.Controller.extend({ name: 'wizardStep1Controller', + /** * Skip repo-validation + * * @type {bool} */ skipValidationChecked: false, - selectedStack: function() { - return App.Stack.find().findProperty('isSelected'); - }.property('[email protected]'), + /** + * @type {App.Stack} + */ + selectedStack: Em.computed.findBy('content.stacks', 'isSelected', true), + + /** + * @type {App.ServiceSimple[]} + */ + servicesForSelectedStack: Em.computed.filterBy('selectedStack.stackServices', 'isHidden', false), + + /** + * Some network issues exist if there is no stack with <code>stackDefault</code> = false + * + * @type {boolean} + */ + networkIssuesExist: Em.computed.everyBy('content.stacks', 'stackDefault', true), optionsToSelect: { 'usePublicRepo': { @@ -50,7 +88,7 @@ App.WizardStep1Controller = Em.Controller.extend({ index: 1, name: 'enterUrl', url: '', - placeholder: 'Enter URL to Version Definition File', + placeholder: Em.I18n.t('installer.step1.useLocalRepo.enterUrl.placeholder'), hasError: false, isSelected: false } @@ -58,53 +96,75 @@ App.WizardStep1Controller = Em.Controller.extend({ }, /** - * Used to set version definition file from FileUploader - * @method setVDFFile - * @param {string} vdf + * Checks if user selected to input url or upload file but didn't do it + * true - url-radio is checked but url-field is empty + * - file-radio is checked but file is not selected + * false - otherwise + * + * @type {boolean} */ - setVDFFile: function (vdf) { - this.set("optionsToSelect.useLocalRepo.uploadFile.file", vdf); - }, + readInfoIsNotProvided: function () { + var useLocalRepo = this.get('optionsToSelect.useLocalRepo'); + if(Em.get(useLocalRepo, 'uploadFile.isSelected')) { + return !Em.get(useLocalRepo, 'uploadFile.file'); + } + if (Em.get(useLocalRepo, 'enterUrl.isSelected')) { + return !Em.get(useLocalRepo, 'enterUrl.url'); + } + return false; + }.property('optionsToSelect.useLocalRepo.isSelected', 'optionsToSelect.useLocalRepo.uploadFile.isSelected', + 'optionsToSelect.useLocalRepo.uploadFile.file', 'optionsToSelect.useLocalRepo.enterUrl.url'), + + /** + * List of stacks grouped by <code>stackNameVersion</code> + * + * @type {StackType[]} + */ + availableStackTypes: function () { + var stacks = this.get('content.stacks'); + return stacks ? stacks.mapProperty('stackNameVersion').uniq().sort().reverse().map(function (stackName) { + return StackType.create({ + stackName: stackName, + stacks: stacks.filterProperty('stackNameVersion', stackName).sort(arrayUtils.sortByIdAsVersion).reverse() + }) + }) : []; + }.property('[email protected]'), + + /** + * @type {StackType} + */ + selectedStackType: Em.computed.findBy('availableStackTypes', 'isSelected', true), /** * Load selected file to current page content */ - readVersionInfo: function(){ + readVersionInfo: function () { var data = {}; var isXMLdata = false; - if (this.get("optionsToSelect.usePublicRepo.isSelected")) return; - if (this.get("optionsToSelect.useLocalRepo.isSelected") && this.get("optionsToSelect.useLocalRepo.enterUrl.isSelected")) { + if (this.get("optionsToSelect.useLocalRepo.enterUrl.isSelected")) { var url = this.get("optionsToSelect.useLocalRepo.enterUrl.url"); data = { - "VersionDefinition": { - "version_url": url + VersionDefinition: { + version_url: url } }; App.db.setLocalRepoVDFData(url); - } else if (this.get("optionsToSelect.useLocalRepo.uploadFile.isSelected")) { - isXMLdata = true; - // load from file browser - data = this.get("optionsToSelect.useLocalRepo.uploadFile.file"); - App.db.setLocalRepoVDFData(data); } - var installerController = App.router.get('installerController'); - var self = this; - installerController.postVersionDefinitionFile(isXMLdata, data).done(function (response) { - self.set('latestSelectedLocalRepoId', response.stackNameVersion + "-" + response.actualVersion); - // load successfully, so make this local stack repo as selectedStack - self.get('content.stacks').setEach('isSelected', false); - self.get('content.stacks').findProperty('id', response.stackNameVersion + "-" + response.actualVersion).set('isSelected', true); - Ember.run.next(function () { - $("[rel=skip-validation-tooltip]").tooltip({ placement: 'right'}); - $("[rel=use-redhat-tooltip]").tooltip({ placement: 'right'}); - }); - }); + else { + if (this.get("optionsToSelect.useLocalRepo.uploadFile.isSelected")) { + isXMLdata = true; + // load from file browser + data = this.get("optionsToSelect.useLocalRepo.uploadFile.file"); + App.db.setLocalRepoVDFData(data); + } + } + return App.router.get('installerController').postVersionDefinitionFile(isXMLdata, data); }, /** * On click handler for removing OS */ - removeOS: function(event) { + removeOS: function (event) { if (this.get('selectedStack.useRedhatSatellite')) { return; } @@ -115,23 +175,290 @@ App.WizardStep1Controller = Em.Controller.extend({ /** * On click handler for adding new OS */ - addOS: function(event) { + addOS: function (event) { var osToAdd = event.context; Em.set(osToAdd, 'isSelected', true); }, - changeUseRedhatSatellite: function () { - if (App.router.get('installerController.currentStep') !== "1") { - return; + /** + * Use Local Repo if some network issues exist + */ + onNetworkIssuesExist: function() { + if (this.get('networkIssuesExist')) { + this.useLocalRepo(); } - if (this.get('selectedStack.useRedhatSatellite')) { - return App.ModalPopup.show({ - header: Em.I18n.t('common.important'), - secondary: false, - bodyClass: Ember.View.extend({ - template: Ember.Handlebars.compile(Em.I18n.t('installer.step1.advancedRepo.useRedhatSatellite.warning')) - }) + }.observes('networkIssuesExist'), + + /** + * Select stack with field equal to the value + * Example: + * <pre> + * selectStackBy('id', 'HDP-2.5-2.5.0.0'); // select stack with id = 'HDP-2.5-2.5.0.0' + * selectStackBy('stackNameVersion', 'HDP-2.5'); // select first stack with stackNameVersion = 'HDP-2.5' + * </pre> + * + * @param {string} field + * @param {string} value + */ + selectStackBy: function (field, value) { + this.get('content.stacks').setEach('isSelected', false); + this.get('content.stacks').findProperty(field, value).set('isSelected', true); + }, + + /** + * Restore base urls for selected stack when user select to use public repository + */ + usePublicRepo: function () { + var selectedStack = this.get('selectedStack'); + if (selectedStack) { + selectedStack.setProperties({ + useRedhatSatellite: false, + usePublicRepo: true, + useLocalRepo: false + }); + selectedStack.restoreReposBaseUrls(); + } + }, + + /** + * Clean base urls for selected stack when user select to use local repository + */ + useLocalRepo: function () { + var selectedStack = this.get('selectedStack'); + if (selectedStack) { + selectedStack.setProperties({ + usePublicRepo: false, + useLocalRepo: true }); + selectedStack.cleanReposBaseUrls(); } - }.observes('selectedStack.useRedhatSatellite') + }, + + /** + * Restores url value to be its default value. + * @method doRestoreDefaultValue + */ + doRestoreDefaultValue: function (event) { + var repo = event.contexts[0]; + repo.set('baseUrl', repo.get('latestBaseUrl')); + }, + + /** + * Restores url value to empty string. + * @method doRestoreToEmpty + */ + doRestoreToEmpty: function (event) { + var repo = event.contexts[0]; + repo.set('baseUrl', ''); + }, + + /** + * Click-handler for left-tabs with stack types + * Select first available stack with stackName equal to chosen + * + * @param {{context: StackType}} event + */ + selectRepoInList: function (event) { + var id = this.get('availableStackTypes').findProperty('stackName', event.context.stackName).get('stacks.firstObject.id'); + this.selectStackBy('id', id); + }, + + /** + * Click-handler for StackVersion-tabs + * + * @param {{context: App.Stack}} event + */ + changeVersion: function (event) { + this.selectStackBy('id', event.context.get('id')); + }, + + /** + * Show popup with options to upload new version + * + * @returns {App.ModalPopup} + */ + uploadVdf: function () { + return App.ModalPopup.show({ + + controller: this, + + header: Em.I18n.t('installer.step1.changeVersion.title'), + + primary: Em.I18n.t('installer.step1.useLocalRepo.readButton'), + + disablePrimary: Em.computed.alias('controller.readInfoIsNotProvided'), + + /** + * Try to read version info from the url or file (if provided) + */ + onPrimary: function () { + var controller = this.get('controller'); + controller.readVersionInfo().done(function (response) { + // load successfully, so make this local stack repo as selectedStack + var newStackId = response.stackNameVersion + '-' + response.actualVersion; + var oldStackNameVersion = controller.get('selectedStack.stackNameVersion'); + controller.selectStackBy('id', newStackId); + if (oldStackNameVersion && oldStackNameVersion !== response.stackNameVersion) { + App.showAlertPopup(Em.I18n.t('common.warning'), Em.I18n.t('installer.step1.addVersion.stackChanged.popup.body').format(oldStackNameVersion, response.stackNameVersion)); + } + Ember.run.next(function () { + $("[rel=skip-validation-tooltip]").tooltip({placement: 'right'}); + $("[rel=use-redhat-tooltip]").tooltip({placement: 'right'}); + }); + }); + this.restoreUploadOptions(); + this._super(); + }, + + /** + * Disable url/file fields on popup-close + */ + onSecondary: function () { + this.restoreUploadOptions(); + this._super(); + }, + + /** + * Disable url/file fields on popup-close + */ + onClose: function () { + this.restoreUploadOptions(); + this._super(); + }, + + /** + * Deselect file/url radio + */ + restoreUploadOptions: function () { + this.set('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected', false); + this.set('controller.optionsToSelect.useLocalRepo.enterUrl.url', ''); + this.set('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected', true); + this.set('controller.optionsToSelect.useLocalRepo.uploadFile.file', ''); + }, + + bodyClass: Em.View.extend({ + + controller: this, + + templateName: require('templates/wizard/step1/vdf_upload'), + + /** + * Wrapper for 'upload-file' elements + * + * @type {Em.View} + */ + uploadFileView: Em.View.extend({ + + classNames: ['clearfix'], + + /** + * Checkbox for Use local Repo > Upload VDF file + * + * @type {Ember.Checkbox} + */ + uploadFileRadioButton: Em.Checkbox.extend({ + attributeBindings: ['type', 'checked'], + checked: Em.computed.alias('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected'), + type: 'radio' + }), + + /** + * Is File API available + * + * @type {bool} + */ + isFileApi: window.File && window.FileReader && window.FileList, + + /** + * Upload file is disabled when some stack is selected or url-field is selected + * + * @type {boolean} + */ + fileBrowserDisabled: Em.computed.alias('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected'), + + /** + * Input to select vdf-file + * + * @type {Em.View} + */ + fileInputView: Em.View.extend({ + template: Em.Handlebars.compile('<input type="file" {{bindAttr class="controller.optionsToSelect.useLocalRepo.enterUrl.isSelected:disabled"}} />'), + + classNames: ['vdf-input-indentation'], + + change: function (e) { + var self = this; + if (e.target.files && e.target.files.length === 1) { + var file = e.target.files[0]; + var reader = new FileReader(); + + reader.onload = (function () { + return function (event) { + self.set('controller.optionsToSelect.useLocalRepo.uploadFile.file', event.target.result); + }; + })(file); + reader.readAsText(file); + } + } + + }), + + click: function () { + if (!this.set('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected')) { + this.set('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected', false); + this.set('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected', true); + this.set('controller.optionsToSelect.useLocalRepo.enterUrl.hasError', false); + this.set('controller.optionsToSelect.useLocalRepo.uploadFile.hasError', false); + } + } + }), + + /** + * Wrapper for 'enter-url' elements + * + * @type {Em.View} + */ + enterUrlView: Em.View.extend({ + + /** + * Url-field is disable when some stack is selected or upload file is selected + * + * @type {boolean} + */ + enterUrlFieldDisabled: Em.computed.alias('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected'), + + /** + * Input for file upload + * + * @type {Em.TextField} + */ + enterUrlField: Em.TextField.extend({ + classNameBindings: [':input-block-level', 'controller.optionsToSelect.useLocalRepo.uploadFile.isSelected:disabled'] + }), + + /** + * Checkbox for Use local Repo > Enter Url of VDF file + * + * @type {Ember.Checkbox} + */ + enterUrlRadioButton: Em.Checkbox.extend({ + attributeBindings: [ 'type', 'checked' ], + checked: Em.computed.alias('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected'), + type: 'radio', + }), + + click: function () { + if (!this.set('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected')) { + this.set('controller.optionsToSelect.useLocalRepo.enterUrl.isSelected', true); + this.set('controller.optionsToSelect.useLocalRepo.uploadFile.isSelected', false); + this.set('controller.optionsToSelect.useLocalRepo.enterUrl.hasError', false); + this.set('controller.optionsToSelect.useLocalRepo.uploadFile.hasError', false); + } + } + }) + + }) + }); + } + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/controllers/wizard/step3_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step3_controller.js b/ambari-web/app/controllers/wizard/step3_controller.js index 38bb5d7..e8108ef 100644 --- a/ambari-web/app/controllers/wizard/step3_controller.js +++ b/ambari-web/app/controllers/wizard/step3_controller.js @@ -1668,7 +1668,8 @@ App.WizardStep3Controller = Em.Controller.extend(App.ReloadPopupMixin, { */ submit: function () { var self = this; - if(App.router.nextBtnClickInProgress){ + + if(App.get('router.nextBtnClickInProgress')){ return; } if (this.get('isHostHaveWarnings')) { http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/controllers/wizard/step4_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step4_controller.js b/ambari-web/app/controllers/wizard/step4_controller.js index 0575f07..3513a1a 100644 --- a/ambari-web/app/controllers/wizard/step4_controller.js +++ b/ambari-web/app/controllers/wizard/step4_controller.js @@ -137,7 +137,7 @@ App.WizardStep4Controller = Em.ArrayController.extend({ * @method submit */ submit: function () { - if(App.router.nextBtnClickInProgress){ + if(App.get('router.nextBtnClickInProgress')){ return; } if (!this.get('isSubmitDisabled')) { http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/controllers/wizard/step7_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step7_controller.js b/ambari-web/app/controllers/wizard/step7_controller.js index c3b98b5..33c19e3 100644 --- a/ambari-web/app/controllers/wizard/step7_controller.js +++ b/ambari-web/app/controllers/wizard/step7_controller.js @@ -1475,7 +1475,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E * @method submit */ submit: function () { - if (this.get('isSubmitDisabled') || App.router.nextBtnClickInProgress) { + if (this.get('isSubmitDisabled') || App.get('router.nextBtnClickInProgress')) { return false; } App.set('router.nextBtnClickInProgress', true); http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/mappers/stack_mapper.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers/stack_mapper.js b/ambari-web/app/mappers/stack_mapper.js index ab1d6a8..e421e2e 100644 --- a/ambari-web/app/mappers/stack_mapper.js +++ b/ambari-web/app/mappers/stack_mapper.js @@ -27,6 +27,7 @@ App.stackMapper = App.QuickDataMapper.create({ id: 'id', stack_name: 'stack_name', stack_version: 'stack_version', + stack_default: 'stack_default', show_available: 'show_available', type: 'type', repository_version: 'repository_version', @@ -96,12 +97,11 @@ App.stackMapper = App.QuickDataMapper.create({ var item = json; var stack = item.VersionDefinition; - var operatingSystemsArray = []; - var servicesArray = []; - if (!stack.id) { - stack.id = stack.stack_name + "-" + stack.stack_version + "-" + stack.repository_version; //HDP-2.5-2.5.0.0 + stack.id = stack.stack_name + '-' + stack.stack_version + '-' + stack.repository_version; //HDP-2.5-2.5.0.0 } + var operatingSystemsArray = []; + var servicesArray = []; item.operating_systems.forEach(function(ops) { var operatingSystems = ops.OperatingSystems; @@ -110,7 +110,7 @@ App.stackMapper = App.QuickDataMapper.create({ ops.repositories.forEach(function(repo) { repo.Repositories.id = [stack.id, repo.Repositories.os_type, repo.Repositories.repo_id].join('-'); repo.Repositories.os_id = [stack.id, repo.Repositories.os_type].join('-'); - if (!repo.Repositories.latest_base_url) repo.Repositories.latest_base_url = repo.Repositories.base_url; + if (!repo.Repositories.latest_base_url) repo.Repositories.latest_base_url = repo.Repositories.base_url; resultRepo.push(this.parseIt(repo.Repositories, this.get('configRepository'))); repositoriesArray.pushObject(repo.Repositories); }, this); http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index 29ca44c..a40ab0a 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -554,6 +554,8 @@ Em.I18n.translations = { 'installer.step1.header':'Select Version', 'installer.step1.body':'Select the software version and method of delivery for your cluster. Using a Public Repository requires Internet connectivity. Using a Local Repository requires you have configured the software in a repository available in your network.', + 'installer.step1.changeVersion.title':'Change Version', + 'installer.step1.changeVersion.defaultVersion':'Default Version Definition', 'installer.step1.selectUseRepoOptions.public':'Use Public Repository', 'installer.step1.selectUseRepoOptions.public.networkLost.button':'Not Available', 'installer.step1.selectUseRepoOptions.public.networkLost':'Why is this disabled?', @@ -568,9 +570,12 @@ Em.I18n.translations = { 'installer.step1.usePublicRepo.viewRepos':'View Repositories', 'installer.step1.useLocalRepo.uploadFile': 'Upload Version Definition File', 'installer.step1.useLocalRepo.uploadFile.error.title': 'Upload Version Definition File Error', - 'installer.step1.useLocalRepo.getSurpottedOs.error.title': 'Cannot get supportted OS types', + 'installer.step1.useLocalRepo.getSurpottedOs.error.title': 'Cannot get supported OS types', 'installer.step1.useLocalRepo.addRepo.button': 'Add Repository', + 'installer.step1.addVersion': 'Add Version', + 'installer.step1.addVersion.stackChanged.popup.body': 'Stack is changed from {0} to {1}.', 'installer.step1.useLocalRepo.enterUrl': 'Version Definition File URL', + 'installer.step1.useLocalRepo.enterUrl.placeholder': 'Enter URL to Version Definition File', 'installer.step1.useLocalRepo.readButton': 'Read Version Info', 'installer.step1.useLocalRepo.infoForm.details.title': 'Details', 'installer.step1.useLocalRepo.infoForm.details.stackName': 'Stack Name', @@ -591,14 +596,17 @@ Em.I18n.translations = { 'installer.step1.advancedRepo.localRepo.label.os':'Operating System', 'installer.step1.advancedRepo.localRepo.label.baseUrl':'Repository Base URL', 'installer.step1.advancedRepo.localRepo.label.stack':'Stack', + 'installer.step1.advancedRepo.localRepo.placeholder': 'Enter Base URL or remove this OS', 'installer.step1.advancedRepo.skipValidation.tooltip':'<b>Warning:</b> This is for advanced users only. Use this option if you want to skip validation for Repository Base URLs.', 'installer.step1.advancedRepo.useRedhatSatellite.tooltip':'Disable distributed repositories and use RedHat Satellite/Spacewalk channels instead', + 'installer.step1.advancedRepo.useRedhatSatellite.disabled.tooltip':'Use of RedHat Satellite/Spacewalk is not available when is using Public Repositories', 'installer.step1.advancedRepo.skipValidation.message':'Skip Repository Base URL validation (Advanced)', 'installer.step1.advancedRepo.useRedhatSatellite.message': 'Use RedHat Satellite/Spacewalk', 'installer.step1.advancedRepo.useRedhatSatellite.warning': 'By selecting to <b>âUse RedHat Satellite/Spacewalkâ</b> for the software repositories, ' + 'you are responsible for configuring the repository channel in Satellite/Spacewalk and confirming the repositories for the selected <b>stack version</b> are available on the hosts in the cluster. ' + 'Refer to the Ambari documentation for more information.', - 'installer.step1.attentionNeeded':'<b>Attention:</b> Repository URLs are REQUIRED before you can proceed.', + 'installer.step1.addOs.disabled.tooltip':'All Operating Systems have been added', + 'installer.step1.attentionNeeded':'<b>Attention:</b> Repository Base URLs are REQUIRED before you can proceed.', 'installer.step1.invalidURLAttention': '<b>Attention:</b> Please make sure all repository URLs are valid before proceeding.', 'installer.step1.checkAtLeastOneAttention': '<b>Attention:</b> Please check at least one repository.', 'installer.step1.retryRepoUrls': 'Click <b>here</b> to retry.', http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/models/repository.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/repository.js b/ambari-web/app/models/repository.js index 8ad20ce..37ef0b3 100644 --- a/ambari-web/app/models/repository.js +++ b/ambari-web/app/models/repository.js @@ -43,12 +43,26 @@ App.Repository = DS.Model.extend({ }.property('baseUrl'), invalidError: function() { - return this.get('validation') == App.Repository.validation['INVALID']; + return this.get('validation') === App.Repository.validation.INVALID; }.property('validation'), + /** + * @type {boolean} + */ + isUtils: function () { + return this.get('repoName').contains('UTILS'); + }.property('repoName'), + undo: Em.computed.notEqualProperties('baseUrl', 'latestBaseUrl'), - clearAll: Em.computed.alias('baseUrl') + notEmpty: Em.computed.notEqual('baseUrl', ''), + + clearAll: Em.computed.alias('baseUrl'), + + /** + * @type {string} + */ + placeholder: Em.computed.ifThenElse('isUtils', '', Em.I18n.t('installer.step1.advancedRepo.localRepo.placeholder')), }); http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/models/stack.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/stack.js b/ambari-web/app/models/stack.js index 6023566..df217f2 100644 --- a/ambari-web/app/models/stack.js +++ b/ambari-web/app/models/stack.js @@ -19,9 +19,10 @@ var App = require('app'); App.Stack = DS.Model.extend({ - id: DS.attr('string'), // ${stackName}-${stackVersion}-${repoVersion}. + id: DS.attr('string'), // ${stackName}-${stackVersion}-${repositoryVersion}. stackName: DS.attr('string'), stackVersion: DS.attr('string'), + stackDefault: DS.attr('boolean'), repositoryVersion: DS.attr('string'), showAvailable: DS.attr('boolean'), // All of the instances should have this value to true. We should map only those stacks that has this flag set to true type: DS.attr('string'), // ["PATCH", "STANDARD"] @@ -30,18 +31,21 @@ App.Stack = DS.Model.extend({ operatingSystems: DS.hasMany('App.OperatingSystem'), isSelected: DS.attr('boolean', {defaultValue: false}), - stackNameVersion: function () { - //${stackName}-${stackVersion}. - return this.get('stackName') + '-' + this.get('stackVersion'); - }.property('stackName', 'stackVersion'), + stackNameVersion: Em.computed.concat('-', 'stackName', 'stackVersion'), - isPatch: function () { - return this.get('type') == "PATCH"; - }.property('type'), - displayName: function () { - //${stackName}-${repositoryVersion}. - return this.get('stackName') + '-' + this.get('repositoryVersion'); - }.property('stackName', 'repositoryVersion'), + isPatch: Em.computed.equal('type', 'PATCH'), + + displayName: Em.computed.concat('-', 'stackName', 'repositoryVersion'), + + /** + * @type {boolean} + */ + usePublicRepo: true, + + /** + * @type {boolean} + */ + useLocalRepo: false, /** * @return: {Array} returns supported repositories for all OperatingSystem's supported by a stack instance @@ -49,13 +53,28 @@ App.Stack = DS.Model.extend({ repositories: function () { var operatingSystems = this.get('operatingSystems'); var repositories = []; - operatingSystems.forEach(function (os) { + operatingSystems.filterProperty('isSelected', true).forEach(function (os) { os.get('repositories').forEach(function (repository) { repositories.pushObject(repository); }, this); }, this); return repositories; - }.property('id') + }.property('[email protected]'), + + cleanReposBaseUrls: function () { + this.get('operatingSystems').forEach(function (os) { + os.get('repositories').setEach('baseUrl', ''); + }); + }, + + restoreReposBaseUrls: function () { + this.get('operatingSystems').forEach(function (os) { + os.get('repositories').forEach(function (repo) { + repo.set('baseUrl', repo.get('latestBaseUrl')); + }); + }); + } + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/models/stack_version/service_simple.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/stack_version/service_simple.js b/ambari-web/app/models/stack_version/service_simple.js index 13ca381..f693cc8 100644 --- a/ambari-web/app/models/stack_version/service_simple.js +++ b/ambari-web/app/models/stack_version/service_simple.js @@ -29,7 +29,7 @@ App.ServiceSimple = DS.Model.extend({ }.property('name'), doNotShowAndInstall: function () { - var skipServices = []; + var skipServices = ['KERBEROS']; if(!App.supports.installGanglia) { skipServices.push('GANGLIA'); } http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/routes/installer.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/routes/installer.js b/ambari-web/app/routes/installer.js index b8b9532..9a4534b 100644 --- a/ambari-web/app/routes/installer.js +++ b/ambari-web/app/routes/installer.js @@ -131,7 +131,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, { index: 1, name: 'enterUrl', url: '', - placeholder: 'Enter URL to Version Definition File', + placeholder: Em.I18n.t('installer.step1.useLocalRepo.enterUrl.placeholder'), hasError: false, isSelected: false } @@ -156,7 +156,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, { back: Em.Router.transitionTo('step0'), next: function (router) { console.time('step1 next'); - if(App.router.nextBtnClickInProgress || router.transitionInProgress){ + if(router.get('nextBtnClickInProgress') || router.transitionInProgress){ return; } var wizardStep1Controller = router.get('wizardStep1Controller'); http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/styles/application.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less index 32c88fd..8a76dfb 100644 --- a/ambari-web/app/styles/application.less +++ b/ambari-web/app/styles/application.less @@ -6197,6 +6197,10 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox { } } +.icon-undo { + color: rgb(243, 178, 11); +} + .view-permission-header th { padding-top: 40px; } @@ -6248,30 +6252,21 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox { font-weight: normal; cursor: pointer; } - #upload-definition-file-panel { - .register-version-options { - padding: 5px 0px; - .local-option-label { - margin-left: 20px; - padding-top: 4px; - } - } - .vdf-url { - input { - width: 80%; - } - } - .read-info-button { - margin: 10px 0px; - } - } #upload-definition-file-panel.disabled { .local-option-label { color: #999999; } } } -#select-stack #repoVersionInfoForm { +.register-version-options { + input.disabled { + background-color: #eee; + } + input[type="file"] { + margin-bottom: 10px; + } +} +#select-stack { .accordion-heading { background-color: #f0f0f0; font-weight: bold; @@ -6281,6 +6276,9 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox { padding: 8px 15px; } } + .accordion-inner { + border-top: none; + } .accordion-body { .version-info-section { padding: 10px; @@ -6290,7 +6288,6 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox { line-height: 14px; } .version-info { - font-weight: bold; padding-top: 5px; line-height: 14px; } @@ -6302,14 +6299,19 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox { border: 1px solid #ddd; max-height: 200px; overflow: auto; - padding: 8px 25px; - margin: 8px; + margin: 8px 0; + .table { + margin-bottom: 0; + tr:first-child td { + border-top: none; + } + } } .repos-panel { .remove-icon { color: red; - margin: 20px 0px; - padding: 0px; + margin: 20px 0 0 0; + padding: 0; text-align: center; cursor: pointer; &.disabled { @@ -6321,9 +6323,11 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox { } .repo-table-title { padding-left: 5px; + padding-bottom: 10px; border-bottom: 1px solid #ebebeb; label { font-weight: bold; + margin-top: 5px; } } .os-type-label { @@ -6338,26 +6342,37 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox { padding-top: 10px; } .repo-name-url { - padding: 8px 0px; + padding-top: 8px; + .repo-name-url-inner { + margin-bottom: 8px; + } } .repo-url input { width: 90%; height: 24px; } .add-os-button { - margin-top:10px; button.disabled { cursor: not-allowed; } } #skip-validation { margin-top: 13px; + span.disabled { + opacity: 0.7; + } } #use-redhat, #skip-validation { input{ margin: 0px 10px; } } + #use-redhat span.disabled { + opacity: 0.7; + } + } + #repoVersionInfoForm { + } } #combo_search_box { http://git-wip-us.apache.org/repos/asf/ambari/blob/9f93ea6b/ambari-web/app/styles/common.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/common.less b/ambari-web/app/styles/common.less index 326d404..738edce 100644 --- a/ambari-web/app/styles/common.less +++ b/ambari-web/app/styles/common.less @@ -414,4 +414,47 @@ -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; +} + +.tabs-left, .tabs-right { + border-bottom: none; + padding-top: 2px; +} +.tabs-left { + border-right: 1px solid #ddd; +} +.tabs-right { + border-left: 1px solid #ddd; +} +.tabs-left>li, .tabs-right>li { + float: none; + margin-bottom: 2px; +} +.tabs-left>li { + margin-right: -1px; +} +.tabs-right>li { + margin-left: -1px; +} +.tabs-left>li.active>a, +.tabs-left>li.active>a:hover, +.tabs-left>li.active>a:focus { + border-bottom-color: #ddd; + border-right-color: transparent; +} + +.tabs-right>li.active>a, +.tabs-right>li.active>a:hover, +.tabs-right>li.active>a:focus { + border-bottom: 1px solid #ddd; + border-left-color: transparent; +} +.tabs-left>li>a { + border-radius: 4px 0 0 4px; + margin-right: 0; + display:block; +} +.tabs-right>li>a { + border-radius: 0 4px 4px 0; + margin-right: 0; } \ No newline at end of file
