ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jai...@apache.org
Subject [2/3] ambari git commit: AMBARI-16940. VDF: support for selecting enabled + default Stacks. (Oleg, Joe, Andrii and Jaimin)
Date Sat, 28 May 2016 00:31:37 GMT
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}}&nbsp;<span class="sub-text">({{repoVersionFullName}})</span></li>
+    <li class="active" ng-if="editController">{{displayName}}&nbsp;<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}} &nbsp;<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}} &nbsp;<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}'}} &nbsp;<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('content.stacks.@each.isSelected'),
+  /**
+   * @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('content.stacks.@each.stackNameVersion'),
+
+  /**
+   * @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('operatingSystems.@each.isSelected'),
+
+  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


Mime
View raw message