Repository: ambari Updated Branches: refs/heads/trunk 23f7428a0 -> 68c68a6f0
AMBARI-10544. Views: FE work for adding the ability for a view instance to be associated to a cluster for configuration (alexantonenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/68c68a6f Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/68c68a6f Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/68c68a6f Branch: refs/heads/trunk Commit: 68c68a6f0eb09f0bbdd530c9c9e1baa8dbfa9828 Parents: 23f7428 Author: Alex Antonenko <hiv...@gmail.com> Authored: Fri Apr 17 06:17:28 2015 +0300 Committer: Alex Antonenko <hiv...@gmail.com> Committed: Fri Apr 17 06:17:28 2015 +0300 ---------------------------------------------------------------------- .../ambariViews/CreateViewInstanceCtrl.js | 37 ++++- .../controllers/ambariViews/ViewsEditCtrl.js | 149 +++++++++++++------ .../ui/admin-web/app/scripts/services/View.js | 37 +++-- .../resources/ui/admin-web/app/styles/main.css | 28 +++- .../admin-web/app/views/ambariViews/create.html | 68 ++++++--- .../admin-web/app/views/ambariViews/edit.html | 63 ++++++-- 6 files changed, 284 insertions(+), 98 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/68c68a6f/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CreateViewInstanceCtrl.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CreateViewInstanceCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CreateViewInstanceCtrl.js index 2492c91..e6c047b 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CreateViewInstanceCtrl.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CreateViewInstanceCtrl.js @@ -18,22 +18,28 @@ 'use strict'; angular.module('ambariAdminConsole') -.controller('CreateViewInstanceCtrl',['$scope', 'View', 'Alert', '$routeParams', '$location', 'UnsavedDialog', function($scope, View, Alert, $routeParams, $location, UnsavedDialog) { +.controller('CreateViewInstanceCtrl',['$scope', 'View', 'Alert', 'Cluster', '$routeParams', '$location', 'UnsavedDialog', function($scope, View, Alert, Cluster, $routeParams, $location, UnsavedDialog) { $scope.form = {}; var targetUrl = ''; function loadMeta(){ View.getMeta($routeParams.viewId, $scope.version).then(function(data) { - var viewVersion = data.data; - $scope.view = viewVersion; + var viewVersion = data.data, + parameters; - var parameters = viewVersion.ViewVersionInfo.parameters; + $scope.view = viewVersion; + parameters = viewVersion.ViewVersionInfo.parameters; angular.forEach(parameters, function (item) { item.value = item['defaultValue']; + item.clusterConfig = !!item.clusterConfig; item.displayName = item.name.replace(/\./g, '\.\u200B'); + $scope.numberOfClusterConfigs = item.clusterConfig ? $scope.numberOfClusterConfigs+1 : $scope.numberOfClusterConfigs; }); + $scope.clusterConfigurable = viewVersion.ViewVersionInfo.cluster_configurable; + $scope.clusterConfigurableErrorMsg = $scope.clusterConfigurable ? "" : "This view cannot use this option"; + $scope.instance = { view_name: viewVersion.ViewVersionInfo.view_name, version: viewVersion.ViewVersionInfo.version, @@ -43,7 +49,8 @@ angular.module('ambariAdminConsole') icon_path: '', icon64_path: '', properties: parameters, - description: '' + description: '', + isLocalCluster: false }; }); } @@ -61,6 +68,25 @@ angular.module('ambariAdminConsole') $scope.isAdvancedClosed = true; $scope.instanceExists = false; + $scope.clusterConfigurable = false; + $scope.clusterConfigurableErrorMsg = ""; + $scope.clusters = []; + $scope.noClusterAvailible = true; + $scope.cluster = null; + $scope.numberOfClusterConfigs = 0; + + Cluster.getAllClusters().then(function (clusters) { + if(clusters.length >0){ + clusters.forEach(function(cluster) { + $scope.clusters.push(cluster.Clusters.cluster_name) + }); + $scope.noClusterAvailible = false; + }else{ + $scope.clusters.push("No Clusters"); + } + $scope.cluster = $scope.clusters[0]; + }); + $scope.versions = []; $scope.version = null; @@ -77,6 +103,7 @@ angular.module('ambariAdminConsole') $scope.form.instanceCreateForm.submitted = true; if($scope.form.instanceCreateForm.$valid){ $scope.form.instanceCreateForm.isSaving = true; + $scope.instance.clusterName = $scope.cluster; View.createInstance($scope.instance) .then(function(data) { Alert.success('Created View Instance ' + $scope.instance.instance_name); http://git-wip-us.apache.org/repos/asf/ambari/blob/68c68a6f/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js index cbf3b0c..ab1d948 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsEditCtrl.js @@ -18,7 +18,7 @@ 'use strict'; angular.module('ambariAdminConsole') -.controller('ViewsEditCtrl', ['$scope', '$routeParams' , 'View', 'Alert', 'PermissionLoader', 'PermissionSaver', 'ConfirmationModal', '$location', 'UnsavedDialog', function($scope, $routeParams, View, Alert, PermissionLoader, PermissionSaver, ConfirmationModal, $location, UnsavedDialog) { +.controller('ViewsEditCtrl', ['$scope', '$routeParams' , 'Cluster', 'View', 'Alert', 'PermissionLoader', 'PermissionSaver', 'ConfirmationModal', '$location', 'UnsavedDialog', function($scope, $routeParams, Cluster, View, Alert, PermissionLoader, PermissionSaver, ConfirmationModal, $location, UnsavedDialog) { $scope.identity = angular.identity; $scope.isConfigurationEmpty = true; function reloadViewInfo(){ @@ -33,8 +33,15 @@ angular.module('ambariAdminConsole') 'description': $scope.instance.ViewInstanceInfo.description }; - initConfigurations(); - $scope.isConfigurationEmpty = angular.equals({}, $scope.configuration); + initConfigurations(); + if(instance.ViewInstanceInfo.cluster_handle) { + $scope.isLocalCluster = true; + $scope.cluster = instance.ViewInstanceInfo.cluster_handle; + }else{ + $scope.isLocalCluster = false; + $scope.cluster = $scope.clusters.length > 0 ? $scope.clusters[0] : "No Clusters"; + } + $scope.isConfigurationEmpty = !$scope.numberOfClusterConfigs; }) .catch(function(data) { Alert.error('Cannot load instance info', data.data.message); @@ -53,8 +60,12 @@ angular.module('ambariAdminConsole') // Get META for properties View.getMeta($routeParams.viewId, $routeParams.version).then(function(data) { $scope.configurationMeta = data.data.ViewVersionInfo.parameters; + $scope.clusterConfigurable = data.data.ViewVersionInfo.cluster_configurable; + $scope.clusterConfigurableErrorMsg = $scope.clusterConfigurable ? "" : "This view cannot use this option"; angular.forEach($scope.configurationMeta, function (item) { item.displayName = item.name.replace(/\./g, '\.\u200B'); + item.clusterConfig = !!item.clusterConfig; + $scope.numberOfClusterConfigs = $scope.numberOfClusterConfigs + !!item.clusterConfig; }); reloadViewInfo(); }); @@ -80,20 +91,57 @@ angular.module('ambariAdminConsole') reloadViewPrivileges(); - $scope.editSettingsDisabled = true; + $scope.clusterConfigurable = false; + $scope.clusterConfigurableErrorMsg = ""; + $scope.clusters = []; + $scope.cluster = null; + $scope.noClusterAvailible = true; + + + $scope.editSettingsDisabled = true; + $scope.numberOfClusterConfigs = 0; + $scope.toggleSettingsEdit = function() { $scope.editSettingsDisabled = !$scope.editSettingsDisabled; + $scope.settingsBeforeEdit = angular.copy($scope.configuration); + $scope.configurationMeta.forEach(function (element) { + if (element.masked && !$scope.editSettingsDisabled && !element.clusterConfig) { + $scope.configuration[element.name] = ''; + } + if(element.clusterConfig) { + delete $scope.settingsBeforeEdit[element.name]; + } + }); }; + Cluster.getAllClusters().then(function (clusters) { + if(clusters.length >0){ + clusters.forEach(function(cluster) { + $scope.clusters.push(cluster.Clusters.cluster_name) + }); + $scope.noClusterAvailible = false; + }else{ + $scope.clusters.push("No Clusters"); + } + $scope.cluster = $scope.clusters[0]; + }); + $scope.saveSettings = function(callback) { if( $scope.settingsForm.$valid ){ - return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, { + var data = { 'ViewInstanceInfo':{ 'visible': $scope.settings.visible, 'label': $scope.settings.label, - 'description': $scope.settings.description + 'description': $scope.settings.description, + 'properties':{} } - }) + }; + $scope.configurationMeta.forEach(function (element) { + if(!element.clusterConfig) { + data.ViewInstanceInfo.properties[element.name] = $scope.configuration[element.name]; + } + }); + return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, data) .success(function() { if( callback ){ callback(); @@ -114,6 +162,7 @@ angular.module('ambariAdminConsole') 'label': $scope.instance.ViewInstanceInfo.label, 'description': $scope.instance.ViewInstanceInfo.description }; + angular.extend($scope.configuration, $scope.settingsBeforeEdit); $scope.editSettingsDisabled = true; $scope.settingsForm.$setPristine(); }; @@ -123,50 +172,62 @@ angular.module('ambariAdminConsole') $scope.togglePropertiesEditing = function () { $scope.editConfigurationDisabled = !$scope.editConfigurationDisabled; $scope.configurationBeforeEdit = angular.copy($scope.configuration); - if (!$scope.editConfigurationDisabled) { + $scope.configurationMeta.forEach(function (element) { + if (element.masked && !$scope.editConfigurationDisabled && element.clusterConfig) { + $scope.configuration[element.name] = ''; + } + if(!element.clusterConfig) { + delete $scope.configurationBeforeEdit[element.name]; + } + }); + }; + $scope.saveConfiguration = function() { + var data = { + 'ViewInstanceInfo':{ + 'properties':{} + } + }; + if($scope.isLocalCluster) { + data.ViewInstanceInfo.cluster_handle = $scope.cluster; + } else { + data.ViewInstanceInfo.cluster_handle = null; $scope.configurationMeta.forEach(function (element) { - if (element.masked) { - $scope.configuration[element.name] = ''; + if(element.clusterConfig) { + data.ViewInstanceInfo.properties[element.name] = $scope.configuration[element.name]; } }); } - }; - $scope.saveConfiguration = function() { - return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, { - 'ViewInstanceInfo':{ - 'properties': $scope.configuration - } - }) - .success(function() { - $scope.editConfigurationDisabled = true; - $scope.propertiesForm.$setPristine(); - }) - .catch(function(data) { - var errorMessage = data.data.message; - - //TODO: maybe the BackEnd should sanitize the string beforehand? - errorMessage = errorMessage.substr(errorMessage.indexOf("\{")); - - if (data.status >= 400) { - try { - var errorObject = JSON.parse(errorMessage); - errorMessage = errorObject.detail; - angular.forEach(errorObject.propertyResults, function (item, key) { - $scope.propertiesForm[key].validationError = !item.valid; - if (!item.valid) { - $scope.propertiesForm[key].validationMessage = item.detail; - } - }); - } catch (e) { - console.error('Unable to parse error message:', data.message); - } + return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, data) + .success(function() { + $scope.editConfigurationDisabled = true; + $scope.propertiesForm.$setPristine(); + }) + .catch(function(data) { + var errorMessage = data.data.message; + + //TODO: maybe the BackEnd should sanitize the string beforehand? + errorMessage = errorMessage.substr(errorMessage.indexOf("\{")); + + if (data.status >= 400) { + try { + var errorObject = JSON.parse(errorMessage); + errorMessage = errorObject.detail; + angular.forEach(errorObject.propertyResults, function (item, key) { + $scope.propertiesForm[key].validationError = !item.valid; + if (!item.valid) { + $scope.propertiesForm[key].validationMessage = item.detail; + } + }); + } catch (e) { + console.error('Unable to parse error message:', data.message); } - Alert.error('Cannot save properties', errorMessage); - }); - }; + } + Alert.error('Cannot save properties', errorMessage); + }); + }; $scope.cancelConfiguration = function() { - $scope.configuration = angular.copy($scope.configurationBeforeEdit); + angular.extend($scope.configuration, $scope.configurationBeforeEdit); $scope.editConfigurationDisabled = true; $scope.propertiesForm.$setPristine(); }; http://git-wip-us.apache.org/repos/asf/ambari/blob/68c68a6f/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js index 06a9e8f..7bf1672 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/View.js @@ -159,26 +159,39 @@ angular.module('ambariAdminConsole') }; View.createInstance = function(instanceInfo) { - var deferred = $q.defer(); - var properties = {}; + var deferred = $q.defer(), + properties = {}, + settings = {}, + data = { + instance_name: instanceInfo.instance_name, + label: instanceInfo.label, + visible: instanceInfo.visible, + icon_path: instanceInfo.icon_path, + icon64_path: instanceInfo.icon64_path, + description: instanceInfo.description + }; angular.forEach(instanceInfo.properties, function(property) { - properties[property.name] = property.value + if(property.clusterConfig) { + properties[property.name] = property.value + }else { + settings[property.name] = property.value + } }); + data.properties = settings; + + if(instanceInfo.isLocalCluster) { + data.cluster_handle = instanceInfo.clusterName; + } else { + angular.extend(data.properties, properties); + } + $http({ method: 'POST', url: Settings.baseUrl + '/views/' + instanceInfo.view_name +'/versions/'+instanceInfo.version + '/instances/'+instanceInfo.instance_name, data:{ - 'ViewInstanceInfo' : { - instance_name: instanceInfo.instance_name, - label: instanceInfo.label, - visible: instanceInfo.visible, - icon_path: instanceInfo.icon_path, - icon64_path: instanceInfo.icon64_path, - properties: properties, - description: instanceInfo.description - } + 'ViewInstanceInfo' : data } }) .success(function(data) { http://git-wip-us.apache.org/repos/asf/ambari/blob/68c68a6f/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 5b82129..d273d07 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 @@ -127,7 +127,7 @@ display: block; color: #888; text-align: center; - padding: 10px 0px; + padding: 10px 0; cursor: default; } @@ -239,7 +239,7 @@ margin-left: 20px; margin-right: 10px; border: none; - border-radius: 0px; + border-radius: 0; } .mainpage .panel-body #main-operations-boxes .thumbnail .title, .mainpage .panel-body #main-operations-boxes .thumbnail .description, @@ -533,7 +533,7 @@ a.gotoinstance{ padding-left: 33px; padding-top: 8px; padding-bottom: 8px; - margin: 0px; + margin: 0; } .left-navbar .panel-body li.active a{ background: #666; @@ -657,7 +657,7 @@ table.no-border tr td{ } .property-form label{ - width: 214px; + width: 254px; word-wrap: break-word; text-overflow: ellipsis; overflow: hidden; @@ -1178,7 +1178,6 @@ button.btn.btn-xs{ border-radius: 50%; vertical-align: middle; position: relative; - border-radius: 50%; } .viewstatus.pending:before, .viewstatus.pending:after{ @@ -1319,4 +1318,23 @@ accordion .panel-group .panel{ } .verison-label-row .label { font-size: 100%; +} + +.panel-body .sub-group { + margin-left: 10px; +} +.clusters-name-dropdown { + margin-top: 7px; + margin-left: 16px; + width: 200px; +} +.cluster-configurable-form { + width: 350px; + margin-top: 15px; + margin-bottom: 15px; + padding: 0 15px; +} +.edit-view-custom-wrap { + padding-top: 0; + margin-top: -28px; } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/68c68a6f/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/create.html ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/create.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/create.html index 772abae..08e4f26 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/create.html +++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/create.html @@ -23,14 +23,14 @@ <form class="form-horizontal create-view-form" role="form" name="form.instanceCreateForm" novalidate> <div class="view-header"> <div class="form-group"> - <div class="col-sm-2"> + <div class="col-sm-3"> <label for="" class="control-label">View</label> </div> <div class="col-sm-10"><label for="" class="control-label">{{view.ViewVersionInfo.view_name}}</label></div> </div> <div class="form-group"> - <div class="col-sm-2"><label for="" class="control-label">Version</label></div> - <div class="col-sm-2"> + <div class="col-sm-3"><label for="" class="control-label">Version</label></div> + <div class="col-sm-3"> <select ng-model="version" class="instanceversion-input form-control" ng-change="versionChanged()" ng-options="o as o for o in versions"></select> </div> </div> @@ -38,14 +38,14 @@ <div class="panel panel-default"> <div class="panel-heading"> - <h3 class="panel-title">Details</h3> + <h3 class="panel-title">Settings</h3> </div> <div class="panel-body"> <div class="form-group" ng-class="{'has-error' : ( (form.instanceCreateForm.instanceNameInput.$error.required || form.instanceCreateForm.instanceNameInput.$error.pattern) && form.instanceCreateForm.submitted) || instanceExists }" > - <label for="" class="control-label col-sm-2">Instance Name</label> - <div class="col-sm-10"> + <label for="" class="control-label col-sm-3">Instance Name</label> + <div class="col-sm-9"> <input type="text" class="form-control instancename-input" name="instanceNameInput" ng-pattern="nameValidationPattern" required ng-model="instance.instance_name" autocomplete="off"> <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm.instanceNameInput.$error.required && form.instanceCreateForm.submitted'> @@ -61,8 +61,8 @@ </div> <div class="form-group" ng-class="{'has-error' : ( (form.instanceCreateForm.displayLabel.$error.required || form.instanceCreateForm.displayLabel.$error.pattern) && form.instanceCreateForm.submitted)}"> - <label for="" class="control-label col-sm-2">Display Name</label> - <div class="col-sm-10"> + <label for="" class="control-label col-sm-3">Display Name</label> + <div class="col-sm-9"> <input type="text" class="form-control instancelabel-input" name="displayLabel" ng-model="instance.label" required ng-pattern="/^([a-zA-Z0-9._\s]+)$/" autocomplete="off"> <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm.displayLabel.$error.required && form.instanceCreateForm.submitted'> @@ -74,16 +74,34 @@ </div> </div> <div class="form-group" ng-class="{'has-error' : form.instanceCreateForm.description.$error.required && form.instanceCreateForm.submitted }"> - <label for="" class="control-label col-sm-2">Description</label> - <div class="col-sm-10"> + <label for="" class="control-label col-sm-3">Description</label> + <div class="col-sm-9"> <input type="text" class="form-control" name="description" ng-model="instance.description" maxlength="140" required> <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm.description.$error.required && form.instanceCreateForm.submitted'> This field is required. </div> </div> </div> + <div class="form-group" ng-repeat="parameter in instance.properties | filter:{clusterConfig:false}" + ng-class="{'has-error' : ((form.instanceCreateForm[parameter.name].$error.required && form.instanceCreateForm.submitted) || form.instanceCreateForm[parameter.name].validationError)}" > + <label for="" class="col-sm-3 control-label" ng-class="{'not-required': !parameter.required}">{{parameter.label || parameter.displayName}}{{parameter.required ? '*' : ''}}</label> + <div ng-switch="parameter.type"> + <div class="col-sm-9 checkbox" ng-switch-when="boolean"> + <input type="checkbox" class="viewproperty-input" name="{{parameter.name}}" ng-required="parameter.required" ng-model="parameter.value" popover="{{parameter.description}}" popover-title="{{parameter.name}}" popover-trigger="mouseenter"> + </div> + <div class="col-sm-9" ng-switch-default> + <input type="{{parameter.masked ? 'password' : 'text'}}" class="form-control viewproperty-input" name="{{parameter.name}}" ng-change="form.instanceCreateForm[parameter.name].validationError=''" ng-required="parameter.required" ng-model="parameter.value" autocomplete="off" popover="{{parameter.description}}" popover-title="{{parameter.name}}" popover-trigger="mouseenter" placeholder="{{parameter.placeholder}}"> + <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm[parameter.name].$error.required && form.instanceCreateForm.submitted'> + This field is required. + </div> + <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm[parameter.name].validationError'> + {{form.instanceCreateForm[parameter.name].validationMessage}} + </div> + </div> + </div> + </div> <div class="form-group"> - <div class="col-sm-10 col-sm-offset-2"> + <div class="col-sm-10 col-sm-offset-3"> <div class="checkbox"> <label> <input type="checkbox" ng-model='instance.visible' class="visibilityCheckbox"> Visible @@ -93,24 +111,40 @@ </div> </div> </div> - <div class="panel panel-default"> + <div class="panel panel-default" ng-hide="!numberOfClusterConfigs"> <div class="panel-heading"> - <h3 class="panel-title">Properties</h3> + <h3 class="panel-title">Cluster Configuration</h3> + </div> + + <div class="panel-body property-form cluster-configurable-form" popover="{{clusterConfigurableErrorMsg}}" popover-trigger="mouseenter"> + <div class="checkbox"> + <label> + <input type="radio" ng-disabled="!clusterConfigurable || noClusterAvailible" ng-model="instance.isLocalCluster" ng-value="true" class="visibilityCheckbox"> Local Ambari Managed Cluster + </label> + </div> + <div class="form-group sub-group"> + <select ng-model="cluster" ng-disabled="!instance.isLocalCluster" ng-change="onClusterChange()" class="clusters-name-dropdown form-control" ng-options="o as o for o in clusters"></select> + </div> </div> <div class="panel-body property-form"> + <div class="checkbox"> + <label> + <input type="radio" ng-model="instance.isLocalCluster" ng-value="false" class="visibilityCheckbox"> Custom + </label> + </div> <div class="alert alert-danger bottom-margin top-margin" ng-show='form.instanceCreateForm.generalValidationError'> {{form.instanceCreateForm.generalValidationError}} </div> - <div class="form-group" ng-repeat="parameter in instance.properties" + <div class="form-group sub-group" ng-repeat="parameter in instance.properties | filter:{clusterConfig:true}" ng-class="{'has-error' : ((form.instanceCreateForm[parameter.name].$error.required && form.instanceCreateForm.submitted) || form.instanceCreateForm[parameter.name].validationError)}" > <label for="" class="col-sm-3 control-label" ng-class="{'not-required': !parameter.required}">{{parameter.label || parameter.displayName}}{{parameter.required ? '*' : ''}}</label> <div ng-switch="parameter.type"> <div class="col-sm-9 checkbox" ng-switch-when="boolean"> - <input type="checkbox" class="viewproperty-input" name="{{parameter.name}}" ng-required="parameter.required" ng-model="parameter.value" popover="{{parameter.description}}" popover-title="{{parameter.name}}" popover-trigger="mouseenter"> + <input type="checkbox" class="viewproperty-input" name="{{parameter.name}}" ng-disabled="instance.isLocalCluster" ng-required="parameter.required && instance.isLocalCluster" ng-model="parameter.value" popover="{{parameter.description}}" popover-title="{{parameter.name}}" popover-trigger="mouseenter"> </div> <div class="col-sm-9" ng-switch-default> - <input type="{{parameter.masked ? 'password' : 'text'}}" class="form-control viewproperty-input" name="{{parameter.name}}" ng-change="form.instanceCreateForm[parameter.name].validationError=''" ng-required="parameter.required" ng-model="parameter.value" autocomplete="off" popover="{{parameter.description}}" popover-title="{{parameter.name}}" popover-trigger="mouseenter" placeholder="{{parameter.placeholder}}"> - <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm[parameter.name].$error.required && form.instanceCreateForm.submitted'> + <input type="{{parameter.masked ? 'password' : 'text'}}" class="form-control viewproperty-input" name="{{parameter.name}}" ng-disabled="instance.isLocalCluster" ng-change="form.instanceCreateForm[parameter.name].validationError=''" ng-required="parameter.required && !instance.isLocalCluster" ng-model="parameter.value" autocomplete="off" popover="{{parameter.description}}" popover-title="{{parameter.name}}" popover-trigger="mouseenter" placeholder="{{parameter.placeholder}}"> + <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm[parameter.name].$error.required && form.instanceCreateForm.submitted && !instance.isLocalCluster'> This field is required. </div> <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm[parameter.name].validationError'> http://git-wip-us.apache.org/repos/asf/ambari/blob/68c68a6f/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html index 910b2ad..960222d 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html +++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/edit.html @@ -37,21 +37,21 @@ <div class="panel-body"> <form class="form-horizontal" name="settingsForm" novalidate> <div class="form-group"> - <label for="" class="col-sm-2 control-label">View Name</label> - <div class="col-sm-10"><input disabled="disabled" type="text" class="form-control instancename-input" placeholder="Display Name" value="{{instance.ViewInstanceInfo.view_name}}"></div> + <label for="" class="col-sm-3 control-label">View Name</label> + <div class="col-sm-9"><input disabled="disabled" type="text" class="form-control instancename-input" placeholder="Display Name" value="{{instance.ViewInstanceInfo.view_name}}"></div> </div> <div class="form-group"> - <label for="" class="col-sm-2 control-label">View Version</label> - <div class="col-sm-10"><input disabled="disabled" type="text" class="form-control instancename-input" placeholder="Display Name" value="{{instance.ViewInstanceInfo.version}}"></div> + <label for="" class="col-sm-3 control-label">View Version</label> + <div class="col-sm-9"><input disabled="disabled" type="text" class="form-control instancename-input" placeholder="Display Name" value="{{instance.ViewInstanceInfo.version}}"></div> </div> <fieldset ng-disabled="editSettingsDisabled"> <div class="form-group"> - <label for="" class="col-sm-2 control-label">Instance Name</label> - <div class="col-sm-10"><input disabled="disabled" type="text" class="form-control instancename-input" placeholder="Display Name" value="{{instance.ViewInstanceInfo.instance_name}}"></div> + <label for="" class="col-sm-3 control-label">Instance Name</label> + <div class="col-sm-9"><input disabled="disabled" type="text" class="form-control instancename-input" placeholder="Display Name" value="{{instance.ViewInstanceInfo.instance_name}}"></div> </div> <div class="form-group" ng-class="{'has-error' : (settingsForm.displayName.$error.required || settingsForm.displayName.$error.pattern) && !editSettingsDisabled}"> - <label for="" class="col-sm-2 control-label">Display Name</label> - <div class="col-sm-10"> + <label for="" class="col-sm-3 control-label">Display Name</label> + <div class="col-sm-9"> <input type="text" class="form-control instancename-input" placeholder="Display Name" name="displayName" required ng-model="settings.label" ng-pattern="/^([a-zA-Z0-9._\s]+)$/"> <div class="alert alert-danger no-margin-bottom top-margin" ng-show='settingsForm.displayName.$error.required && !editSettingsDisabled'> This field is required. @@ -62,16 +62,33 @@ </div> </div> <div class="form-group" ng-class="{'has-error' : settingsForm.description.$error.required && !editSettingsDisabled}"> - <label for="" class="control-label col-sm-2">Description</label> - <div class="col-sm-10"> + <label for="" class="control-label col-sm-3">Description</label> + <div class="col-sm-9"> <input type="text" class="form-control" ng-model="settings.description" name="description" placeholder="Instance Description" required> <div class="alert alert-danger no-margin-bottom top-margin" ng-show='settingsForm.description.$error.required && !editSettingsDisabled'> This field is required. </div> </div> </div> + <div class="form-group" ng-repeat="property in configurationMeta | filter:{clusterConfig:false}" ng-class="{'has-error' : (!editSettingsDisabled && ((property.required && settingsForm[property.name].$error.required && !editSettingsDisabled) || settingsForm[property.name].validationError))}"> + <label for="" class="control-label col-sm-3" ng-class="{'not-required': !property.required}">{{property.label || property.displayName}}{{property.required ? '*' : ''}}</label> + <div ng-switch="property.type"> + <div class="col-sm-9 checkbox" ng-switch-when="boolean"> + <input type="checkbox" class="propertie-input" ng-disabled="editSettingsDisabled" name="{{property.name}}" ng-model="configuration[property.name]" ng-true-value="true" ng-false-value="false" popover="{{property.description}}" popover-title="{{property.name}}" popover-trigger="mouseenter"> + </div> + <div class="col-sm-9" ng-switch-default> + <input type="{{property.masked ? 'password' : 'text'}}" class="form-control propertie-input" ng-required="property.required" ng-change="settingsForm[property.name].validationError=''" ng-disabled="editSettingsDisabled" name="{{property.name}}" ng-model="configuration[property.name]" popover="{{property.description}}" popover-title="{{property.name}}" popover-trigger="mouseenter" placeholder="{{property.placeholder}}"> + <div class="alert alert-danger no-margin-bottom top-margin" ng-show='property.required && settingsForm[property.name].$error.required && !editSettingsDisabled'> + This field is required. + </div> + <div class="alert alert-danger no-margin-bottom top-margin" ng-show='property.required && settingsForm[property.name].validationError && !editSettingsDisabled'> + {{propertiesForm[property.name].validationMessage}} + </div> + </div> + </div> + </div> <div class="form-group"> - <div class="col-sm-offset-2 col-sm-10"> + <div class="col-sm-offset-3 col-sm-10"> <div class="checkbox"> <label> <input type="checkbox" ng-model="settings.visible" ng-class="instancevisibility-input"> Visible @@ -125,18 +142,34 @@ </div> </div> -<div class="panel panel-default"> +<div class="panel panel-default" ng-hide="isConfigurationEmpty"> <div class="panel-heading clearfix"> - <h3 class="panel-title pull-left">Properties</h3> + <h3 class="panel-title pull-left">Cluster Configuration</h3> <div class="pull-right" ng-switch="instance.ViewInstanceInfo.static"> <a href ng-switch-when="false" ng-hide="isConfigurationEmpty" ng-click="togglePropertiesEditing()" ng-show="editConfigurationDisabled" class="properties-toggle"> <span class="glyphicon glyphicon-pencil"></span> Edit</a> <a href ng-switch-when="true" ng-hide="isConfigurationEmpty" class="properties-toggle disabled"> <span class="glyphicon glyphicon-pencil"></span> Edit</a> </div> </div> - <div class="panel-body"> + <div class="panel-body property-form cluster-configurable-form" popover="{{clusterConfigurableErrorMsg}}" popover-trigger="mouseenter"> + <div class="checkbox"> + <label> + <input type="radio" ng-model="$parent.isLocalCluster" ng-disabled="!clusterConfigurable || editConfigurationDisabled || noClusterAvailible" ng-value="true" class="visibilityCheckbox"> Local Ambari Managed Cluster + </label> + </div> + <div class="form-group sub-group"> + <select ng-model="cluster" ng-disabled="!$parent.isLocalCluster || editConfigurationDisabled" ng-change="onClusterChange()" class="clusters-name-dropdown form-control" ng-options="o as o for o in clusters"></select> + </div> + <p> </p> + <div class="checkbox"> + <label> + <input type="radio" ng-model="$parent.isLocalCluster" ng-disabled="editConfigurationDisabled" ng-value="false" class="visibilityCheckbox"> Custom + </label> + </div> + </div> + <div class="panel-body edit-view-custom-wrap"> <form name="propertiesForm" class="form-horizontal property-form" ng-hide="isConfigurationEmpty" novalidate> <fieldset> - <div class="form-group" ng-repeat="property in configurationMeta" ng-class="{'has-error' : (!editConfigurationDisabled && ((property.required && propertiesForm[property.name].$error.required && !editConfigurationDisabled) || propertiesForm[property.name].validationError))}"> + <div class="form-group sub-group" ng-repeat="property in configurationMeta | filter:{clusterConfig:true}" ng-class="{'has-error' : (!editConfigurationDisabled && ((property.required && propertiesForm[property.name].$error.required && !editConfigurationDisabled) || propertiesForm[property.name].validationError))}"> <label for="" class="control-label col-sm-3" ng-class="{'not-required': !property.required}">{{property.label || property.displayName}}{{property.required ? '*' : ''}}</label> <div ng-switch="property.type"> <div class="col-sm-9 checkbox" ng-switch-when="boolean">