AMBARI-16940. VDF: support for selecting enabled + default Stacks. (Oleg, Joe, Andrii and Jaimin)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/03600fa7 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/03600fa7 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/03600fa7 Branch: refs/heads/trunk Commit: 03600fa75274c82cc89b025c51bb5d622d474711 Parents: c552633 Author: Jaimin Jetly <[email protected]> Authored: Fri May 27 17:28:43 2016 -0700 Committer: Jaimin Jetly <[email protected]> Committed: Fri May 27 17:33:03 2016 -0700 ---------------------------------------------------------------------- .../main/resources/ui/admin-web/app/index.html | 2 + .../stackVersions/StackVersionsCreateCtrl.js | 305 +++++++++++--- .../stackVersions/StackVersionsEditCtrl.js | 13 +- .../stackVersions/StackVersionsListCtrl.js | 205 ++++++--- .../ui/admin-web/app/scripts/i18n.config.js | 19 +- .../app/scripts/services/AddVersionModal.js | 172 ++++++++ .../app/scripts/services/ConfirmationModal.js | 3 +- .../ui/admin-web/app/scripts/services/Stack.js | 65 ++- .../admin-web/app/scripts/services/Utility.js | 70 ++++ .../resources/ui/admin-web/app/styles/main.css | 191 ++++++++- .../app/views/modals/AddVersionModal.html | 52 +++ .../app/views/modals/ConfirmationModal.html | 2 +- .../app/views/modals/publicRepoDisabled.html | 23 + .../admin-web/app/views/stackVersions/list.html | 123 ++++-- .../views/stackVersions/stackVersionPage.html | 314 +++++++------- ambari-web/app/assets/test/tests.js | 1 + ambari-web/app/controllers/installer.js | 67 ++- .../app/controllers/wizard/step0_controller.js | 4 +- .../app/controllers/wizard/step1_controller.js | 417 +++++++++++++++++-- .../app/controllers/wizard/step3_controller.js | 3 +- .../app/controllers/wizard/step4_controller.js | 2 +- .../app/controllers/wizard/step7_controller.js | 2 +- ambari-web/app/mappers/stack_mapper.js | 10 +- ambari-web/app/messages.js | 12 +- ambari-web/app/models/repository.js | 18 +- ambari-web/app/models/stack.js | 47 ++- .../app/models/stack_version/service_simple.js | 2 +- ambari-web/app/routes/installer.js | 4 +- ambari-web/app/styles/application.less | 65 +-- ambari-web/app/styles/common.less | 43 ++ ambari-web/app/templates/wizard/step1.hbs | 326 ++++++++------- .../public_option_disabled_window_body.hbs | 25 ++ .../app/templates/wizard/step1/vdf_upload.hbs | 44 ++ ambari-web/app/utils/array_utils.js | 32 ++ ambari-web/app/views/wizard/step1_view.js | 293 +++++-------- ambari-web/karma.conf.js | 8 +- ambari-web/test/controllers/installer_test.js | 19 + .../test/controllers/wizard/step1_test.js | 212 ++++++++++ .../config_recommendation_parser_test.js | 4 +- ambari-web/test/utils/array_utils_test.js | 43 ++ .../host_progress_popup_body_view_test.js | 43 +- ambari-web/test/views/wizard/step1_view_test.js | 201 +-------- 42 files changed, 2468 insertions(+), 1038 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/index.html ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/index.html b/ambari-admin/src/main/resources/ui/admin-web/app/index.html index 9344f15..11e0a2e 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/index.html +++ b/ambari-admin/src/main/resources/ui/admin-web/app/index.html @@ -155,6 +155,7 @@ <script src="scripts/directives/PasswordVerify.js"></script> <script src="scripts/directives/disabledTooltip.js"></script> <script src="scripts/directives/editableList.js"></script> +<script src="scripts/services/Utility.js"></script> <script src="scripts/services/UserConstants.js"></script> <script src="scripts/services/User.js"></script> <script src="scripts/services/Group.js"></script> @@ -171,6 +172,7 @@ <script src="scripts/services/UnsavedDialog.js"></script> <script src="scripts/services/Stack.js"></script> <script src="scripts/services/AddRepositoryModal.js"></script> +<script src="scripts/services/AddVersionModal.js"></script> <script src="scripts/services/RoleDetailsModal.js"></script> <!-- endbuild --> </body> http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsCreateCtrl.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsCreateCtrl.js index 47b72e6..5433bd6 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsCreateCtrl.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsCreateCtrl.js @@ -18,13 +18,17 @@ 'use strict'; angular.module('ambariAdminConsole') -.controller('StackVersionsCreateCtrl', ['$scope', 'Stack', '$routeParams', '$location', 'Alert', '$translate', 'Cluster', 'AddRepositoryModal', 'ConfirmationModal', function($scope, Stack, $routeParams, $location, Alert, $translate, Cluster, AddRepositoryModal, ConfirmationModal) { +.controller('StackVersionsCreateCtrl', ['$scope', 'Stack', 'Utility', '$routeParams', '$location', '$timeout' ,'Alert', '$translate', 'Cluster', 'AddRepositoryModal', 'AddVersionModal', 'ConfirmationModal', + function($scope, Stack, Utility, $routeParams, $location, $timeout, Alert, $translate, Cluster, AddRepositoryModal, AddVersionModal, ConfirmationModal) { var $t = $translate.instant; $scope.constants = { os: $t('versions.os') }; $scope.createController = true; $scope.osList = []; + $scope.stackIds = []; + $scope.allVersions = []; + $scope.networkLost = false; $scope.skipValidation = false; $scope.useRedhatSatellite = false; @@ -66,18 +70,34 @@ angular.module('ambariAdminConsole') /** * User can select ONLY one option to upload version definition file */ - $scope.togglePublicLocalOptionSelect = function () { - $scope.option1.hasError = false; - $scope.option2.hasError = false; - }; $scope.toggleOptionSelect = function () { $scope.option1.hasError = false; $scope.option2.hasError = false; }; + $scope.isPublicRepoSelected = function () { + if ($scope.selectedOption.index == $scope.publicOption.index) return true; + }; $scope.togglePublicLocalOptionSelect = function () { - if ($scope.selectedOption.index == $scope.publicOption.index && $scope.selectedPublicRepoVersion) { - $scope.setVersionSelected($scope.selectedPublicRepoVersion); + if ($scope.selectedOption.index == $scope.publicOption.index) { + $scope.setInitialPublicRepoVersions(); + } else { + $scope.clearRepoVersions(); } + $scope.validateRepoUrl(); + }; + $scope.setInitialPublicRepoVersions = function () { + angular.forEach($scope.osList, function (os) { + os.repositories.forEach(function(repo) { + repo.Repositories.base_url = repo.Repositories.initial_base_url; + }); + }); + }; + $scope.clearRepoVersions = function () { + angular.forEach($scope.osList, function (os) { + os.repositories.forEach(function(repo) { + repo.Repositories.base_url = ''; + }); + }); }; $scope.clearOptionsError = function () { $scope.option1.hasError = false; @@ -117,6 +137,13 @@ angular.module('ambariAdminConsole') }; /** + * On click handler for adding a new version + */ + $scope.addVersion = function() { + AddVersionModal.show($scope); + }; + + /** * Load selected file to current page content */ $scope.readVersionInfo = function(){ @@ -154,21 +181,30 @@ angular.module('ambariAdminConsole') $scope.afterStackVersionRead = function () { Stack.getSupportedOSList($scope.upgradeStack.stack_name, $scope.upgradeStack.stack_version) .then(function (data) { + var existingOSHash = {}; + angular.forEach($scope.osList, function (os) { + if (angular.isUndefined(os.selected)) { + os.selected = true; + } + existingOSHash[os.OperatingSystems.os_type] = os; + + }); var operatingSystems = data.operating_systems; - operatingSystems.map(function (os) { - var existingOSHash = {}; - angular.forEach($scope.osList, function (os) { - existingOSHash[os.OperatingSystems.os_type] = os; - }); + angular.forEach(operatingSystems, function (stackOs) { // if os not in the list, mark as un-selected, add this to the osList - if (!existingOSHash[os.OperatingSystems.os_type]) { - os.selected = false; - os.repositories.forEach(function(repo) { + if (!existingOSHash[stackOs.OperatingSystems.os_type]) { + stackOs.selected = false; + stackOs.repositories.forEach(function(repo) { repo.Repositories.base_url = ''; + repo.Repositories.initial_base_url = ''; }); - $scope.osList.push(os); + $scope.osList.push(stackOs); } }); + if ($scope.selectedOption.index == $scope.localOption.index) { + $scope.clearRepoVersions(); + $scope.validateRepoUrl(); + } }) .catch(function (data) { Alert.error($t('versions.alerts.osListError'), data.message); @@ -192,7 +228,13 @@ angular.module('ambariAdminConsole') /** * On click handler for adding new OS */ - $scope.addOS = function() { + $scope.addOS = function($event) { + var dropdownEl = $event.target.parentElement.parentElement; + // close the dopdown when an OS is added. + $timeout(function () { + dropdownEl.click(); + }); + this.os.selected = true; if (this.os.repositories) { this.os.repositories.forEach(function(repo) { @@ -208,6 +250,23 @@ angular.module('ambariAdminConsole') AddRepositoryModal.show($scope.osList, $scope.upgradeStack.stack_name, $scope.upgradeStack.stack_version, $scope.id); }; + $scope.validBaseUrlsExist = function () { + var validBaseUrlsExist = true; + if ($scope.osList) { + $scope.osList.forEach(function(os) { + if (os.repositories && os.selected) { + os.repositories.forEach(function(repo) { + if (repo.invalidBaseUrl) { + validBaseUrlsExist = false; + } + }) + } + }); + } + return validBaseUrlsExist; + }; + + $scope.isSaveButtonDisabled = function() { var enabled = false; $scope.osList.forEach(function(os) { @@ -215,7 +274,8 @@ angular.module('ambariAdminConsole') enabled = true } }); - return !enabled; + var isRedhatSatelliteSelected = $scope.useRedhatSatellite; + return !(isRedhatSatelliteSelected || (enabled && $scope.validBaseUrlsExist())); }; $scope.defaulfOSRepos = {}; @@ -239,42 +299,47 @@ angular.module('ambariAdminConsole') updateRepoUrl = true; } }); - if ($scope.isPublicVersion) { - var skip = $scope.skipValidation || $scope.useRedhatSatellite; - return Stack.validateBaseUrls(skip, $scope.osList, $scope.upgradeStack).then(function (invalidUrls) { - if (invalidUrls.length === 0) { + + var skip = $scope.skipValidation || $scope.useRedhatSatellite; + return Stack.validateBaseUrls(skip, $scope.osList, $scope.upgradeStack).then(function (invalidUrls) { + if (invalidUrls.length === 0) { + if ($scope.isPublicVersion) { var data = { "VersionDefinition": { "available": $scope.id } }; - var repoUpdate = { - operating_systems: $scope.updateObj.operating_systems - }; - Stack.postVersionDefinitionFile(false, data).then(function (versionInfo) { - if (versionInfo.id && versionInfo.stackName && versionInfo.stackVersion) { - Stack.updateRepo(versionInfo.stackName, versionInfo.stackVersion, versionInfo.id, repoUpdate).then(function () { - Alert.success($t('versions.alerts.versionEdited', { - stackName: $scope.upgradeStack.stack_name, - versionName: $scope.actualVersion, - displayName: $scope.displayName - })); - $location.path('/stackVersions'); - }).catch(function (data) { - Alert.error($t('versions.alerts.versionUpdateError'), data.message); - }); - } - }) - .catch(function (data) { - Alert.error($t('versions.alerts.readVersionInfoError'), data.message); - }); + var isXMLdata = false; } else { - Stack.highlightInvalidUrls(invalidUrls); + var data = $scope.data; + var isXMLdata = $scope.isXMLdata; } - }); - } else { - $scope.updateRepoVersions(); - } + + var repoUpdate = { + operating_systems: $scope.updateObj.operating_systems + }; + Stack.postVersionDefinitionFile(isXMLdata, data, false).then(function (response) { + var versionInfo = response.resources[0].VersionDefinition; + if (versionInfo.id && versionInfo.stack_name && versionInfo.stack_version) { + Stack.updateRepo(versionInfo.stack_name, versionInfo.stack_version, versionInfo.id, repoUpdate).then(function () { + Alert.success($t('versions.alerts.versionEdited', { + stackName: $scope.upgradeStack.stack_name, + versionName: $scope.actualVersion, + displayName: $scope.displayName + })); + $location.path('/stackVersions'); + }).catch(function (data) { + Alert.error($t('versions.alerts.versionUpdateError'), data.message); + }); + } + }) + .catch(function (data) { + Alert.error($t('versions.alerts.readVersionInfoError'), data.message); + }); + } else { + Stack.highlightInvalidUrls(invalidUrls); + } + }); }; $scope.updateRepoVersions = function () { @@ -324,8 +389,47 @@ angular.module('ambariAdminConsole') } }; - $scope.clearError = function() { - this.repository.hasError = false; + $scope.showPublicRepoDisabledDialog = function() { + ConfirmationModal.show( + $t('versions.networkIssues.publicDisabledHeader'), + { + "url": 'views/modals/publicRepoDisabled.html' + }, + $t('common.controls.ok'), + $t('common.controls.cancel'), + true + ) + }; + + $scope.onRepoUrlChange = function (repository) { + $scope.clearError(repository); + $scope.setInvalidUrlError(repository); + }; + + $scope.undoChange = function(repo) { + if ($scope.selectedOption.index == 1) { + repo.Repositories.base_url = repo.Repositories.initial_base_url; + } else { + repo.Repositories.base_url = ''; + } + }; + + $scope.clearError = function(repository) { + repository.hasError = false; + }; + + $scope.setInvalidUrlError = function (repository) { + repository.invalidBaseUrl = !$scope.isValidRepoBaseUrl(repository.Repositories.base_url); + }; + /** + * Validate base URL + * @param {string} value + * @returns {boolean} + */ + $scope.isValidRepoBaseUrl = function (value) { + var remotePattern = /^(?:(?:https?|ftp):\/{2})(?:\S+(?::\S*)?@)?(?:(?:(?:[\w\-.]))*)(?::[0-9]+)?(?:\/\S*)?$/, + localPattern = /^file:\/{2,3}([a-zA-Z][:|]\/){0,1}[\w~!*'();@&=\/\\\-+$,?%#.\[\]]+$/; + return remotePattern.test(value) || localPattern.test(value); }; $scope.hasValidationErrors = function() { @@ -372,10 +476,8 @@ angular.module('ambariAdminConsole') }; }); $scope.repoVersionFullName = response.repoVersionFullName; - angular.forEach(response.osList, function (os) { - os.selected = true; - }); $scope.osList = response.osList; + // load supported os type base on stack version $scope.afterStackVersionRead(); }; @@ -385,11 +487,106 @@ angular.module('ambariAdminConsole') $scope.setVersionSelected(this.version); }; + $scope.onStackIdChange = function () { + $scope.setStackIdActive(this.stack); + $scope.setVisibleStackVersions($scope.allVersions); + $scope.setVersionSelected($scope.activeStackVersion); + }; + + $scope.setStackIdActive = function (stack) { + angular.forEach($scope.stackIds, function(_stack){ + _stack.isSelected = false; + }); + stack.isSelected = true; + }; + + $scope.setStackIds = function(stacks) { + var stackIds = []; + // sort stacks as per per {stack_name}-{stack_version} + stacks.sort(function(a,b){ + if (a.stackName === b.stackName) { + var aStackVersion = parseFloat(a.stackVersion); + var bStackVersion = parseFloat(b.stackVersion); + if (aStackVersion === bStackVersion) { + // sort numerically as per per {repository_version} + return Utility.compareVersions(a.repositoryVersion, b.repositoryVersion); + } else { + //sort numerically as per per {stack_version} + return aStackVersion > bStackVersion; + } + } else { + //sort lexicographically as per per {stack_name} + return (a.stackName > b.stackName); + } + }).reverse(); + angular.forEach(stacks, function (stack) { + stackIds.push(stack.stackNameVersion); + }); + $scope.stackIds = stackIds.filter(function(item, index, self){ + return self.indexOf(item) === index; + }).map(function(item){ + return { + stackNameVersion: item, + isSelected: false + }; + }); + $scope.stackIds[0].isSelected = true; + }; + + $scope.setActiveVersion = function () { + $scope.activeStackVersion = this.version; + $scope.setVersionSelected($scope.activeStackVersion); + }; + + $scope.setVisibleStackVersions = function (versions) { + var activeStackId = $scope.stackIds.find(function(item){ + return item.isSelected === true; + }); + angular.forEach(versions, function (item, index) { + var isPublicVersionsExist = false; + // If public VDF exists for a stack then default base stack version should be hidden + if (item.stackDefault) { + isPublicVersionsExist = versions.find(function(_version){ + return (item.stackNameVersion === _version.stackNameVersion && !_version.stackDefault); + }); + } + item.visible = (item.stackNameVersion === activeStackId.stackNameVersion) && !isPublicVersionsExist; + }); + $scope.activeStackVersion = versions.filter(function(item){ + return item.visible; + })[0]; + }; + + $scope.setNetworkIssues = function (versions) { + $scope.networkLost = !versions.find(function(_version){ + return !_version.stackDefault; + }); + if ($scope.networkLost) { + $scope.selectedOption.index = 2; + $scope.clearRepoVersions(); + } + }; + + $scope.validateRepoUrl = function () { + angular.forEach($scope.osList,function(os){ + if (os.repositories) { + os.repositories.forEach(function(repo) { + $scope.onRepoUrlChange(repo); + }); + } + }); + }; + $scope.fetchPublicVersions = function () { return Stack.allPublicStackVersions().then(function (versions) { if (versions && versions.length) { - $scope.selectedPublicRepoVersion = versions[0]; - $scope.setVersionSelected(versions[0]); + $scope.setStackIds(versions); + $scope.setVisibleStackVersions(versions); + $scope.allVersions = versions; + $scope.selectedPublicRepoVersion = $scope.activeStackVersion; + $scope.setVersionSelected($scope.activeStackVersion); + $scope.setNetworkIssues(versions); + $scope.validateRepoUrl(); $scope.availableStackRepoList = versions.length == 1 ? [] : versions; } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsEditCtrl.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsEditCtrl.js index 22ec5ae..ae9850b 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsEditCtrl.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsEditCtrl.js @@ -36,6 +36,7 @@ angular.module('ambariAdminConsole') $scope.loadStackVersionInfo = function () { return Stack.getRepo($routeParams.versionId, $routeParams.stackName).then(function (response) { + $scope.activeStackVersion = response; $scope.id = response.id; $scope.isPatch = response.type == 'PATCH'; $scope.stackNameVersion = response.stackNameVersion || $t('common.NA'); @@ -98,6 +99,9 @@ angular.module('ambariAdminConsole') operatingSystems.map(function (os) { var existingOSHash = {}; angular.forEach($scope.osList, function (os) { + os.repositories.forEach(function(repo) { + repo.Repositories.initial_base_url = repo.Repositories.base_url; + }); existingOSHash[os.OperatingSystems.os_type] = os; }); // if os not in the list, mark as un-selected, add this to the osList @@ -215,7 +219,6 @@ angular.module('ambariAdminConsole') }); }); }; - $scope.loadStackVersionInfo(); /** * On click handler for removing OS @@ -281,13 +284,17 @@ angular.module('ambariAdminConsole') } }); return !enabled; - } + }; $scope.cancel = function () { $scope.editVersionDisabled = true; $location.path('/stackVersions'); }; + $scope.undoChange = function(repo) { + repo.Repositories.base_url = repo.Repositories.initial_base_url; + }; + $scope.clearErrors = function() { if ($scope.osList) { $scope.osList.forEach(function(os) { @@ -388,4 +395,6 @@ angular.module('ambariAdminConsole') $scope.stackVersions = stackVersions; }); }; + + $scope.loadStackVersionInfo(); }]); http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsListCtrl.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsListCtrl.js index 3a8233a..b759800 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsListCtrl.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/stackVersions/StackVersionsListCtrl.js @@ -18,66 +18,155 @@ 'use strict'; angular.module('ambariAdminConsole') -.controller('StackVersionsListCtrl', ['$scope', 'Cluster', 'Stack', '$routeParams', '$translate', function ($scope, Cluster, Stack, $routeParams, $translate) { - var $t = $translate.instant; - $scope.getConstant = function (key) { - return $t('common.' + key).toLowerCase(); - } - $scope.clusterName = $routeParams.clusterName; - - $scope.filter = { - version: '', - cluster: { - options: [], - current: null - } - }; - - $scope.pagination = { - totalRepos: 100, - maxVisiblePages: 1, - itemsPerPage: 100, - currentPage: 1 - }; - $scope.allRepos = []; - $scope.stackVersions = []; - - /** - * Formatted object to display all repos: - * - * [{ 'name': 'HDP-2.3', - * 'repos': ['2.3.6.0-2343', '2.3.4.1', '2.3.4.0-56'] - * }, - * { 'name': 'HDP-2.2', - * 'repos': ['2.2.6.0', '2.2.4.5', '2.2.4.0'] - * } - * ] - * - */ - $scope.fetchRepos = function () { - return Stack.allRepos($scope.filter, $scope.pagination).then(function (repos) { - $scope.allRepos = repos.items.sort(function(a, b){return a.repository_version < b.repository_version}); - var existingStackHash = {}; - var stackVersions = []; - angular.forEach($scope.allRepos, function (repo) { - var stackVersionName = repo.stack_name + '-' + repo.stack_version; - if (!existingStackHash[stackVersionName]) { - existingStackHash[stackVersionName] = true; - stackVersions.push({ - 'name': stackVersionName, - 'isOpened': true, - 'repos': [repo] + .controller('StackVersionsListCtrl', ['$scope', 'Cluster', 'Stack', '$routeParams', '$translate', function ($scope, Cluster, Stack, $routeParams, $translate) { + var $t = $translate.instant; + $scope.getConstant = function (key) { + return $t('common.' + key).toLowerCase(); + }; + $scope.clusterName = $routeParams.clusterName; + $scope.filter = { + name: '', + version: '', + cluster: { + options: [], + current: null + }, + stack: { + options: [], + current: null + } + }; + $scope.isNotEmptyFilter = true; + + $scope.pagination = { + totalRepos: 10, + maxVisiblePages: 20, + itemsPerPage: 10, + currentPage: 1 + }; + + $scope.tableInfo = { + total: 0, + showed: 0, + filtered: 0 + }; + + $scope.repos = []; + $scope.dropDownClusters = []; + $scope.selectedCluster = $scope.dropDownClusters[0]; + + $scope.resetPagination = function () { + $scope.pagination.currentPage = 1; + $scope.loadAllData(); + }; + + $scope.pageChanged = function () { + $scope.loadAllData(); + }; + + $scope.goToCluster = function() { + window.location.replace('/#/main/admin/stack/versions'); + }; + + $scope.clearFilters = function () { + $scope.filter.name = ''; + $scope.filter.version = ''; + $scope.filter.cluster.current = $scope.filter.cluster.options[0]; + $scope.filter.stack.current = $scope.filter.stack.options[0]; + $scope.resetPagination(); + }; + + $scope.fetchRepoClusterStatus = function () { + var clusterName = ($scope.clusters && $scope.clusters.length > 0) ? $scope.clusters[0].Clusters.cluster_name : null; // only support one cluster at the moment + if (clusterName) { + angular.forEach($scope.repos, function (repo) { + Cluster.getRepoVersionStatus(clusterName, repo.id).then(function (response) { + repo.status = response.status; + repo.totalHosts = response.totalHosts; + repo.currentHosts = response.currentHosts; + repo.installedHosts = response.installedHosts; + repo.stackVersionId = response.stackVersionId; + repo.cluster = (repo.status == 'current' || repo.status == 'installed') ? clusterName : ''; }); - } else { - if (stackVersions[stackVersions.length -1].repos) { - stackVersions[stackVersions.length -1].repos.push(repo); - } + }); + } + }; + + $scope.fetchRepos = function () { + return Stack.allRepos($scope.filter, $scope.pagination).then(function (repos) { + $scope.pagination.totalRepos = repos.itemTotal; + $scope.repos = repos.items; + $scope.tableInfo.total = repos.itemTotal; + $scope.tableInfo.showed = repos.showed; + }); + }; + + $scope.fillClusters = function (clusters) { + $scope.dropDownClusters = [].concat(clusters); + var options = [{label: $t('common.all'), value: ''}]; + angular.forEach(clusters, function (cluster) { + options.push({ + label: cluster.Clusters.cluster_name, + value: cluster.Clusters.cluster_name + }); + }); + $scope.filter.cluster.options = options; + if (!$scope.filter.cluster.current) { + $scope.filter.cluster.current = options[0]; + } + }; + + $scope.fetchClusters = function () { + return Cluster.getAllClusters().then(function (clusters) { + if (clusters && clusters.length > 0) { + $scope.clusters = clusters; + $scope.fillClusters(clusters); } }); - $scope.stackVersions = stackVersions; - }); - }; + }; + + $scope.fetchStacks = function () { + return Stack.allStackVersions().then(function (clusters) { + if (clusters && clusters.length > 0) { + $scope.stacks = clusters; + $scope.fillStacks(clusters); + } + }); + }; + + $scope.fillStacks = function() { + var options = [{label: $t('common.all'), value: ''}]; + angular.forEach($scope.stacks, function (stack) { + options.push({ + label: stack.displayName, + value: stack.displayName + }); + }); + $scope.filter.stack.options = options; + if (!$scope.filter.stack.current) { + $scope.filter.stack.current = options[0]; + } + }; + + $scope.loadAllData = function () { + $scope.fetchStacks() + .then(function () { + return $scope.fetchClusters(); + }) + .then(function () { + return $scope.fetchRepos(); + }) + .then(function () { + $scope.fetchRepoClusterStatus(); + }); + }; - $scope.fetchRepos(); + $scope.loadAllData(); -}]); + $scope.$watch('filter', function (filter) { + $scope.isNotEmptyFilter = Boolean(filter.name + || filter.version + || (filter.cluster.current && filter.cluster.current.value) + || (filter.stack.current && filter.stack.current.value)); + }, true); + }]); http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js index 2d51ece..7474d5f 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js @@ -38,6 +38,7 @@ angular.module('ambariAdminConsole') 'users': 'Users', 'groups': 'Groups', 'versions': 'Versions', + 'stack': 'Stack', 'details': 'Details', 'goToDashboard': 'Go to Dashboard', 'noClusters': 'No Clusters', @@ -89,6 +90,7 @@ angular.module('ambariAdminConsole') 'listViewLabel': 'LIST', 'rbac': 'Role Based Access Control', 'important': 'Important', + 'undo': 'Undo', 'clusterNameChangeConfirmation': { 'title': 'Confirm Cluster Name Change', @@ -372,9 +374,19 @@ angular.module('ambariAdminConsole') 'versions': { 'current': 'Current', + 'addVersion': 'Add Version', + 'defaultVersion': '(Default Version Definition)', 'inUse': 'In Use', 'installed': 'Installed', 'usePublic': "Use Public Repository", + 'networkIssues': { + 'networkLost': "Why is this disabled?", + 'publicDisabledHeader': "Public Repository Option Disabled", + 'publicRepoDisabledMsg': 'Ambari does not have access to the Internet and cannot use the Public Repository for installing the software. Your Options:', + 'publicRepoDisabledMsg1': 'Configure your hosts for access to the Internet.', + 'publicRepoDisabledMsg2': 'If you are using an Internet Proxy, refer to the Ambari Documentation on how to configure Ambari to use the Internet Proxy.', + 'publicRepoDisabledMsg3': 'Use the Local Repositoy option.' + }, 'selectVersion': "Select Version", 'selectVersionEmpty': "No other repositories", 'useLocal': "Use Local Repository", @@ -406,11 +418,15 @@ angular.module('ambariAdminConsole') 'actualVersion': 'Actual Version', 'releaseNotes': 'Release Notes' }, + 'repository': { + 'placeholder': 'Enter Base URL or remove this OS' + }, 'useRedhatSatellite': { 'title': 'Use RedHat Satellite/Spacewalk', '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.' + 'Refer to the Ambari documentation for more information.', + 'disabledMsg': 'Use of RedHat Satellite/Spacewalk is not available when using Public Repositories' }, 'changeBaseURLConfirmation': { 'title': 'Confirm Base URL Change', @@ -425,6 +441,7 @@ angular.module('ambariAdminConsole') 'filterListError': 'Fetch stack version filter list error', 'versionCreated': 'Created version <a href="#/stackVersions/{{stackName}}/{{versionName}}/edit">{{stackName}}-{{versionName}}</a>', 'versionCreationError': 'Version creation error', + 'allOsAdded': 'All Operating Systems have been added', 'osListError': 'getSupportedOSList error', 'readVersionInfoError': 'Version Definition read error', 'versionEdited': 'Edited version <a href="#/stackVersions/{{stackName}}/{{versionName}}/edit">{{displayName}}</a>', http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/AddVersionModal.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/AddVersionModal.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/AddVersionModal.js new file mode 100644 index 0000000..0af7004 --- /dev/null +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/AddVersionModal.js @@ -0,0 +1,172 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict'; + +angular.module('ambariAdminConsole') + .factory('AddVersionModal', ['$modal', '$q', function($modal, $q) { + var modalObject = {}; + + modalObject.repoExists = function(existingRepos, repoId) { + for(var i = existingRepos.length - 1; i >= 0; --i) { + if (existingRepos[i].Repositories.repo_id === repoId) { + return true; + } + } + return false; + }; + + modalObject.getRepositoriesForOS = function (osList, selectedOS) { + // Get existing list of repositories for selectedOS + for (var i = osList.length - 1; i >= 0; --i) { + if (osList[i].OperatingSystems.os_type === selectedOS) { + osList[i].repositories = osList[i].repositories || []; + return osList[i].repositories; + } + } + return null; + }; + + modalObject.show = function (parentScope) { + var deferred = $q.defer(); + var modalInstance = $modal.open({ + templateUrl: 'views/modals/AddVersionModal.html', + controller: ['$scope', '$modalInstance', '$translate', 'Stack', 'Alert', function ($scope, $modalInstance, $translate, Stack, Alert) { + var $t = $translate.instant; + $scope.selectedLocalOption = { + index: 1 + }; + $scope.option1 = { + index: 1, + displayName: $t('versions.uploadFile'), + file: '' + }; + $scope.option2 = { + index: 2, + displayName: $t('versions.enterURL'), + url: "", + placeholder: "Enter URL to Version Definition File", + }; + $scope.readInfoButtonDisabled = function () { + return $scope.option1.index == $scope.selectedLocalOption.index ? !$scope.option1.file : !$scope.option2.url; + }; + $scope.onFileSelect = function(e){ + if (e.files && e.files.length == 1) { + var file = e.files[0]; + var reader = new FileReader(); + reader.onload = (function () { + return function (e) { + $scope.option1.file = e.target.result; + }; + })(file); + reader.readAsText(file); + } else { + $scope.option1.file = ''; + } + }; + /** + * Load selected file to current page content + */ + $scope.readVersionInfo = function(){ + var data = {}; + var isXMLdata = false; + if ($scope.option2.index == $scope.selectedLocalOption.index) { + var url = $scope.option2.url; + data = { + "VersionDefinition": { + "version_url": url + } + }; + } else if ($scope.option1.index == $scope.selectedLocalOption.index) { + isXMLdata = true; + // load from file browser + data = $scope.option1.file; + } + parentScope.isXMLdata = isXMLdata; + parentScope.data = data; + + return Stack.postVersionDefinitionFile(isXMLdata, data, true).then(function (versionInfo) { + var repo = versionInfo.resources[0]; + var response = { + id : repo.VersionDefinition.id, + stackVersion : repo.VersionDefinition.stack_version, + stackName: repo.VersionDefinition.stack_name, + type: repo.VersionDefinition.release? repo.VersionDefinition.release.type: null, + stackNameVersion: repo.VersionDefinition.stack_name + '-' + repo.VersionDefinition.stack_version, /// HDP-2.3 + stackNameRepositoryVersion: repo.VersionDefinition.stack_name + '-' + repo.VersionDefinition.repository_version, + actualVersion: repo.VersionDefinition.repository_version, /// 2.3.4.0-3846 + version: repo.VersionDefinition.release ? repo.VersionDefinition.release.version: null, /// 2.3.4.0 + releaseNotes: repo.VersionDefinition.release ? repo.VersionDefinition.release.release_notes: null, + displayName: repo.VersionDefinition.stack_name + '-' + repo.VersionDefinition.repository_version, //HDP-2.3.4.0 + repoVersionFullName : repo.VersionDefinition.stack_name + '-' + repo.VersionDefinition.release ? repo.VersionDefinition.release.version: repo.VersionDefinition.repository_version, + ambari_managed_repositories: repo.operating_systems[0].OperatingSystems.ambari_managed_repositories !== false, + osList: repo.operating_systems, + updateObj: repo + }; + var services = []; + angular.forEach(repo.VersionDefinition.stack_services, function (service) { + var servicesToExclude = ['GANGLIA', 'KERBEROS', 'MAPREDUCE2']; + if (servicesToExclude.indexOf(service.name) === -1) { + services.push({ + name: service.name, + version: service.versions[0], + displayName: service.display_name + }); + } + }); + response.services = services.sort(function(a, b){return a.name.localeCompare(b.name)}); + response.osList.forEach(function (os) { + os.repositories.forEach(function(repo) { + repo.Repositories.initial_base_url = repo.Repositories.base_url; + }); + }); + + angular.forEach(parentScope.stackIds, function(stack){ + if (stack.stackNameVersion == response.stackNameVersion) { + parentScope.setStackIdActive(stack); + } + }); + angular.forEach(parentScope.allVersions, function(version) { + version.visible = (version.stackNameVersion === response.stackNameVersion); + }); + parentScope.allVersions.push(response); + parentScope.activeStackVersion = response; + parentScope.selectedPublicRepoVersion = response; + parentScope.setVersionSelected(response); + $modalInstance.close(); + deferred.resolve(); + }).catch(function (data) { + Alert.error($t('versions.alerts.readVersionInfoError'), data.message); + }); + }; + $scope.cancel = function () { + $modalInstance.dismiss(); + deferred.reject(); + }; + }] + }); + modalInstance.result.then(function () { + // Gets triggered on close + }, function () { + // Gets triggered on dismiss + deferred.reject(); + }); + return deferred.promise; + }; + + return modalObject; + }]); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/ConfirmationModal.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/ConfirmationModal.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/ConfirmationModal.js index 4576a40..2e65e0f 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/ConfirmationModal.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/ConfirmationModal.js @@ -23,7 +23,7 @@ angular.module('ambariAdminConsole') var $t = $translate.instant; return { - show: function(header, body, confirmText, cancelText) { + show: function(header, body, confirmText, cancelText, hideCancelButton) { var deferred = $q.defer(); var modalInstance = $modal.open({ @@ -35,6 +35,7 @@ angular.module('ambariAdminConsole') $scope.innerScope = body.scope; $scope.confirmText = confirmText || $t('common.controls.ok'); $scope.cancelText = cancelText || $t('common.controls.cancel'); + $scope.showCancelButton = !hideCancelButton; $scope.ok = function() { $modalInstance.close(); http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Stack.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Stack.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Stack.js index 96f9c9f..7e76859 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Stack.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Stack.js @@ -81,8 +81,8 @@ angular.module('ambariAdminConsole') }, allPublicStackVersions: function() { - var url = '/version_definitions?fields=operating_systems/repositories/Repositories/*,VersionDefinition/stack_services,VersionDefinition/repository_version' + - '&VersionDefinition/show_available=true&VersionDefinition/stack_name=HDP'; + var url = '/version_definitions?fields=VersionDefinition/stack_default,operating_systems/repositories/Repositories/*,VersionDefinition/stack_services,VersionDefinition/repository_version' + + '&VersionDefinition/show_available=true'; var deferred = $q.defer(); $http.get(Settings.baseUrl + url, {mock: 'version/versions.json'}) .success(function (data) { @@ -92,22 +92,34 @@ angular.module('ambariAdminConsole') id: version.VersionDefinition.id, stackName: version.VersionDefinition.stack_name, stackVersion: version.VersionDefinition.stack_version, + stackDefault: version.VersionDefinition.stack_default, stackNameVersion: version.VersionDefinition.stack_name + '-' + version.VersionDefinition.stack_version, displayName: version.VersionDefinition.stack_name + '-' + version.VersionDefinition.repository_version.split('-')[0], //HDP-2.3.4.0 displayNameFull: version.VersionDefinition.stack_name + '-' + version.VersionDefinition.repository_version, //HDP-2.3.4.0-23 repositoryVersion: version.VersionDefinition.repository_version, + stackNameRepositoryVersion: version.VersionDefinition.stack_name + '-' + version.VersionDefinition.repository_version, showAvailable: version.VersionDefinition.show_available, osList: version.operating_systems, updateObj: version }; var services = []; angular.forEach(version.VersionDefinition.stack_services, function (service) { - services.push({ - name: service.name, - version: service.versions[0] + // services that should not be shown on UI + var servicesToExclude = ['GANGLIA', 'KERBEROS', 'MAPREDUCE2']; + if (servicesToExclude.indexOf(service.name) === -1) { + services.push({ + name: service.name, + displayName: service.display_name, + version: service.versions[0] + }); + } + }); + versionObj.services = services.sort(function(a, b){return a.name.localeCompare(b.name)}); + versionObj.osList.forEach(function (os) { + os.repositories.forEach(function(repo) { + repo.Repositories.initial_base_url = repo.Repositories.base_url; }); }); - versionObj.services = services; versions.push(versionObj); }); deferred.resolve(versions) @@ -120,9 +132,21 @@ angular.module('ambariAdminConsole') allRepos: function (filter, pagination) { var versionFilter = filter.version; + var nameFilter = filter.name; + var stackFilter = filter.stack && filter.stack.current && filter.stack.current.value; var url = '/stacks?fields=versions/repository_versions/RepositoryVersions'; if (versionFilter) { - url += '&versions/repository_versions/RepositoryVersions/display_name.matches(.*' + versionFilter + '.*)'; + url += '&versions/repository_versions/RepositoryVersions/repository_version.matches(.*' + versionFilter + '.*)'; + } + if (nameFilter) { + url += '&versions/repository_versions/RepositoryVersions/display_name.matches(.*' + nameFilter + '.*)'; + } + if (stackFilter) { + var stack = filter.stack.current.value.split('-'), + stackNameFilter = stack[0], + stackVersionFilter = stack[1]; + url += '&versions/repository_versions/RepositoryVersions/stack_name=' + stackNameFilter; + url += '&versions/repository_versions/RepositoryVersions/stack_version=' + stackVersionFilter; } var deferred = $q.defer(); $http.get(Settings.baseUrl + url, {mock: 'version/versions.json'}) @@ -213,8 +237,7 @@ angular.module('ambariAdminConsole') actualVersion: data.repository_versions[0].RepositoryVersions.repository_version, /// 2.3.4.0-3846 version: data.repository_versions[0].RepositoryVersions.release ? data.repository_versions[0].RepositoryVersions.release.version: null, /// 2.3.4.0 releaseNotes: data.repository_versions[0].RepositoryVersions.release ? data.repository_versions[0].RepositoryVersions.release.release_notes: null, - displayName: data.repository_versions[0].RepositoryVersions.release ? data.Versions.stack_name + '-' + data.repository_versions[0].RepositoryVersions.release.version : - data.Versions.stack_name + '-' + data.repository_versions[0].RepositoryVersions.repository_version.split('-')[0], //HDP-2.3.4.0 + displayName: data.repository_versions[0].RepositoryVersions.display_name, //HDP-2.3.4.0 repoVersionFullName : data.Versions.stack_name + '-' + data.repository_versions[0].RepositoryVersions.repository_version, ambari_managed_repositories: data.repository_versions[0].operating_systems[0].OperatingSystems.ambari_managed_repositories !== false, osList: data.repository_versions[0].operating_systems, @@ -222,11 +245,14 @@ angular.module('ambariAdminConsole') }; var services = []; angular.forEach(data.repository_versions[0].RepositoryVersions.stack_services, function (service) { - services.push({ - name: service.name, - version: service.versions[0], - displayName: service.display_name - }); + var servicesToExclude = ['GANGLIA', 'KERBEROS', 'MAPREDUCE2']; + if (servicesToExclude.indexOf(service.name) === -1) { + services.push({ + name: service.name, + version: service.versions[0], + displayName: service.display_name + }); + } }); response.services = services.sort(function(a, b){return a.name.localeCompare(b.name)}); deferred.resolve(response); @@ -237,20 +263,15 @@ angular.module('ambariAdminConsole') return deferred.promise; }, - postVersionDefinitionFile: function (isXMLdata, data) { + postVersionDefinitionFile: function (isXMLdata, data, isDryRun) { var deferred = $q.defer(), - url = Settings.baseUrl + '/version_definitions', + url = Settings.baseUrl + '/version_definitions' + (isDryRun ? '?dry_run=true' : ''), configs = isXMLdata? { headers: {'Content-Type': 'text/xml'}} : null; $http.post(url, data, configs) .success(function (response) { if (response.resources.length && response.resources[0].VersionDefinition) { - deferred.resolve( - { - stackName: response.resources[0].VersionDefinition.stack_name, - id: response.resources[0].VersionDefinition.id, - stackVersion: response.resources[0].VersionDefinition.stack_version - }); + deferred.resolve(response); } }) .error(function (data) { http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Utility.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Utility.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Utility.js new file mode 100644 index 0000000..9439ba9 --- /dev/null +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Utility.js @@ -0,0 +1,70 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict'; +/** + * This service should be used to keep all utility functions in one place that can be used in any controller + */ +angular.module('ambariAdminConsole') + .factory('Utility', [function() { + return { + /** + * if version1>= version2 then return true + * version1 < version2 then return false + * @param version1 {String} + * @param version2 {String} + * @return boolean + */ + compareVersions: function(version1, version2) { + version1 = version1 || '0'; + version2 = version2 || '0'; + var version1Arr = version1.split('.').map(function(item){ + return parseInt(item); + }).filter(function(item){ + return !!item || item === 0; + }); + var version2Arr = version2.split('.').map(function(item){ + return parseInt(item); + }).filter(function(item){ + return !!item || item === 0; + }); + var totalLength = Math.max(version1Arr.length, version2Arr.length); + var result = true, i; + for (i = 0; i <=totalLength; i++) { + if (version2Arr[i] === undefined) { + // Example: version1 = "2.3.2.2" and version2 = 2.3.2 + result = true; + break; + } else if (version1Arr[i] === undefined) { + // Example: version1 = "2.3.2" and version2 = "2.3.2.2" + result = false; + break; + } else if (version1Arr[i] > version2Arr[i]) { + // Example: version1 = "2.3.2.2" and version2 = "2.3.2.1" + result = true; + break; + } else if (version1Arr[i] < version2Arr[i]) { + // Example: version1 = "2.3.1.2" and version2 = "2.3.2.1" + result = false; + break; + } + } + return result; + } + }; + } +]); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css index 4434908..abb3c38 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css +++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css @@ -1372,9 +1372,48 @@ accordion .panel-group .panel{ text-align: right; } -.name-label-adjust { +.repo-table-title { + padding-left: 5px; + padding-bottom: 10px; + border-bottom: 1px solid #ebebeb; +} + +.repo-table-title label { + margin-top: 5px; +} + +.repo-table-title #os-label { + padding-left: 7px; +} + +.repo-table-title .add-os-button.disabled { + cursor: not-allowed; +} + +.advanced-radio-buttons { + margin-top: 15px; +} + +.advanced-radio-buttons i { + color: #0572ff; +} + +.advanced-radio-buttons span.disabled { + opacity: 0.7; + cursor: default; +} + +.repo-table-title #name-label-adjust { width: 20.7%; + padding-left:0px; + right:5px; +} + +.repo-table-title #repo-base-url-label { + padding-left:0px; + right:3px; } + .verison-label-row .label { font-size: 100%; } @@ -1477,15 +1516,85 @@ thead.view-permission-header > tr > th { .left-menu-all-repos .repos-table .repos-td.active > a { color: white; } -#upload-definition-file-panel { - padding: 5px 10px 5px 10px; - margin-bottom: 15px; +#list-stack-id { + padding-left: 0px; + padding-right: 0px; + margin-left: 0px; +} +.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; +} + +.public-disabled-option { + padding: 5px; + padding-left: 15px; +} + +#upload-definition-file-panel .big-radio { + font-weight: bold; + padding: 5px 15px; + margin-left: -18px; } -#upload-definition-file-panel .option-radio { - padding: 15px 5px; - font-weight: bold;; +#upload-definition-file-panel .big-radio #public-disabled-link { + margin-left: 10px; + font-weight: normal; + cursor: pointer; } + +#current-stack-details { + bottom: 20px; + padding-left: 0px; +} + +#current-stack-details .table-borderless { + border: transparent; +} + +#current-stack-details .table-borderless tbody tr td, .table-borderless tbody tr th, .table-borderless thead tr th { + border: none; +} + + #upload-definition-file-panel .stack-version-selection { padding-left: 25px; } @@ -1510,9 +1619,9 @@ thead.view-permission-header > tr > th { .register-version-options .option-radio-button label { font-weight: normal; } -.register-version-options .choose-file-input { - padding-top: 6px; - padding-bottom: 20px; +.register-version-options .choose-file-input input { + padding-top: 3px; + padding-bottom: 3px; } .register-version-form .details-panel .patch-icon { color: #ff4500; @@ -1525,9 +1634,43 @@ thead.view-permission-header > tr > th { margin-top: 0; margin-bottom: 0; } + +.details-panel { + border: 1px solid #e5e5e5; +} + +.details-panel .version-contents-section { + border: 1px solid #ddd; + max-height: 200px; + overflow: auto; +} + +.details-panel .version-contents-section-register-version { + margin: 8px 0; +} + +.details-panel .version-contents-section .table { + margin-bottom: 0; +} + +.details-panel .version-contents-section .table tr:first-child td { + border-top: none; +} + .register-version-form .details-panel .version-info-section { margin-top: 10px; } + +.register-version-options .stack-url-input input.disabled { + background-color: #eee; +} + +.register-version-options .choose-file-input input.disabled { + font-weight: normal; + cursor: default; + background-color: #eee; +} + .register-version-form .details-panel .version-contents-section { max-height: 200px; overflow: auto; @@ -1553,6 +1696,7 @@ thead.view-permission-header > tr > th { padding: 0; text-align: center; cursor: pointer; + width: 5.982905982905983%; } .register-version-form .repos-panel .remove-icon.disabled{ color: grey; @@ -1560,11 +1704,32 @@ thead.view-permission-header > tr > th { .register-version-form .repos-panel .repo-name-label { text-align: left; + padding-top: 10px; + padding-left: 0px; +} + +.register-version-form .repos-panel .repo-name-url { + padding: 8px 0px; + margin-bottom: 0px; } .register-version-form .repos-panel .os-type-label { - margin-top: 27px;; + margin-top: 27px; + padding-left: 10px; } + +.register-version-form .repos-panel .repo-url { + padding-right: 5px; +} + +.register-version-form .repos-panel .repo-url input { + padding: 4px; +} + +.register-version-form .repos-panel .fa-undo { + margin-top: 10px; +} + .register-version-form .dropdown-menu li a { cursor: pointer; } @@ -1588,6 +1753,10 @@ thead.view-permission-header > tr > th { color: #5ab400; } +.orange-icon { + color: #f3b20b; +} + .cursor-pointer { cursor: pointer; } http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/AddVersionModal.html ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/AddVersionModal.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/AddVersionModal.html new file mode 100644 index 0000000..993cef5 --- /dev/null +++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/AddVersionModal.html @@ -0,0 +1,52 @@ +<!-- +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +--> +<div class="modal-header"> + <h3 class="modal-title">Add Version</h3> +</div> +<br> +<div class="clearfix register-version-options" ng-click="selectedLocalOption.index=1"> + <div class="option-radio-button"> + <label class="option-label"> + <input type="radio" ng-model="selectedLocalOption.index" value="1"> {{'versions.uploadFile' | translate}} + </label> + </div> + <div class="col-sm-7 choose-file-input"> + <input type="file" ng-model="option1.file" ng-class="selectedLocalOption.index!='1' ? 'disabled' : ''" + onchange="angular.element(this).scope().onFileSelect(this)"/> + </div> +</div> +<div class="clearfix register-version-options bottom-margin" ng-click="selectedLocalOption.index=2"> + <div class="option-radio-button"> + <label class="option-label"> + <input type="radio" ng-model="selectedLocalOption.index" value="2"> {{'versions.enterURL' | translate}} + </label> + </div> + <div class="col-sm-9"> + <div class="form-group {{option2.name}}" ng-class="{'has-error': option2.url.hasError }"> + <div class="stack-url-input"> + <input type="text" class="form-control" ng-model="option2.url" + placeholder="{{option2.placeholder}}" ng-class="selectedLocalOption.index!='2' ? 'disabled' : ''"> + </div> + </div> + </div> +</div> +<div class="modal-footer"> + <button class="btn btn-default" ng-click="cancel()">Cancel</button> + <button class="btn btn-primary" ng-model="button" ng-click="readVersionInfo()" + ng-disabled="readInfoButtonDisabled()">{{'versions.readInfo' | translate}}</button> +</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/ConfirmationModal.html ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/ConfirmationModal.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/ConfirmationModal.html index b11f6bb..95a68b3 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/ConfirmationModal.html +++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/ConfirmationModal.html @@ -23,6 +23,6 @@ <div ng-show="isTempalte" ng-include="body.url"></div> </div> <div class="modal-footer"> - <button class="btn btn-default" ng-click="cancel()">{{cancelText}}</button> + <button class="btn btn-default" ng-if="showCancelButton" ng-click="cancel()">{{cancelText}}</button> <button class="btn btn-primary" ng-click="ok()">{{confirmText}}</button> </div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/publicRepoDisabled.html ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/publicRepoDisabled.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/publicRepoDisabled.html new file mode 100644 index 0000000..6ef53bf --- /dev/null +++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/publicRepoDisabled.html @@ -0,0 +1,23 @@ +<!-- +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +--> +<div class="public-disabled-message" translate="versions.networkIssues.publicRepoDisabledMsg"></div> +<ul> + <li class="public-disabled-option" translate="versions.networkIssues.publicRepoDisabledMsg1"></li> + <li class="public-disabled-option" translate="versions.networkIssues.publicRepoDisabledMsg2"></li> + <li class="public-disabled-option" translate="versions.networkIssues.publicRepoDisabledMsg3"></li> +</ul> http://git-wip-us.apache.org/repos/asf/ambari/blob/03600fa7/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html index 3de92c1..a992898 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html +++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html @@ -29,34 +29,103 @@ </div> </div> <hr/> - - <accordion close-others="false" class="col-sm-2 left-menu-all-repos"> - <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}} + <table class="table table-striped table-hover"> + <thead> + <tr> + <th class="col-small"> + <label>{{'common.stack' | translate}}</label> + <select class="form-control" + ng-change="resetPagination()" + ng-model="filter.stack.current" + ng-options="item.label for item in filter.stack.options track by item.value" + ></select> + </th> + <th class="col-medium"> + <label>{{'common.name' | translate}}</label> + <input type="text" class="form-control" ng-change="resetPagination()" ng-model="filter.name" placeholder="{{'common.any' | translate}}"> + </th> + <th class="col-medium"> + <label>{{'common.version' | translate}}</label> + <input type="text" class="form-control" ng-change="resetPagination()" ng-model="filter.version" placeholder="{{'common.any' | translate}}"> + </th> + <th class="col-small"> + <label>{{'common.cluster' | translate}}</label> + <select class="form-control" + ng-change="resetPagination()" + ng-model="filter.cluster.current" + ng-options="item.label for item in filter.cluster.options track by item.value" + ></select> + </th> + <th></th> + </tr> + </thead> + <tbody> + <tr ng-repeat="repo in repos"> + <td class="col-small"> + <span>{{repo.stack_name}}-{{repo.stack_version}}</span> + </td> + <td class="col-medium"> + <a href="#/stackVersions/{{repo.stack_name}}/{{repo.repository_version}}/edit">{{repo.display_name}}</a> + </td> + <td class="col-medium"> + <span>{{repo.repository_version}}</span> + </td> + <td class="col-small"> + <a href="/#/main/admin/stack/versions" ng-show="repo.cluster"> + {{repo.cluster}} + </a> + <span ng-show="!repo.cluster"> + {{'common.none' | translate}} + </span> + </td> + <td class="verison-label-row"> + <div ng-show="repo.status == 'current'"> + <span class="label {{'status-' + repo.status}}">{{'versions.current' | translate}}: {{repo.currentHosts}}/{{repo.totalHosts}}</span> + </div> + <div ng-show="repo.status == 'installed'"> + <span class="label {{'status-' + repo.status}}">{{'versions.installed' | translate}}: {{repo.installedHosts}}/{{repo.totalHosts}}</span> </div> - </accordion-heading> - <table class="table repos-table"> - <tbody> - <tr ng-repeat="repo in stackVersion.repos"> - <td class="repos-td"> - <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 ng-show="!repo.cluster"> + <div class="btn-group display-inline-block" dropdown is-open="viewsdropdown.isopen" ng-mouseover="viewsdropdown.isopen=true" ng-mouseout="viewsdropdown.isopen=false" ng-init="viewsdropdown.isopen=false"> + <a class="btn dropdown-toggle"> + <span>{{'versions.installOn' | translate}}</span> + </a> + <ul class="dropdown-menu" ng-show="viewsdropdown.isopen"> + <li ng-repeat="cluster in dropDownClusters"> + <a href="javascript:void(null)" ng-click="goToCluster()"> + <span>{{cluster.Clusters.cluster_name}}</span> + </a> + </li> + </ul> + </div> + </div> + </td> + </tr> + </tbody> + </table> + <div class="alert alert-info col-sm-12" ng-show="!repos.length"> + {{'common.alerts.nothingToDisplay' | translate: '{term: getConstant("version")}'}} + </div> + <div class="col-sm-12 table-bar"> + <div class="pull-left filtered-info"> + <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: getConstant("versions")}'}}</span> + <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span> </div> - </accordion> - - <form class="col-sm-10 form-horizontal" role="form"novalidate> - <div class="alert alert-info no-version-alert"> - {{'versions.noVersions' | translate}} + <div class="pull-right left-margin"> + <pagination class="paginator" + total-items="pagination.totalRepos" + max-size="pagination.maxVisiblePages" + items-per-page="pagination.itemsPerPage" + ng-model="pagination.currentPage" + ng-change="pageChanged()" + ></pagination> </div> - </form> - + <div class="pull-right"> + <select class="form-control" + ng-model="pagination.itemsPerPage" + ng-options="item for item in [10, 25, 50, 100]" + ng-change="resetPagination()" + ></select> + </div> + </div> </div>
