You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by at...@apache.org on 2017/11/07 17:52:45 UTC
[2/2] ambari git commit: AMBARI-22377 Ambari 3.0: Implement new
design for Admin View: Views page. (atkach)
AMBARI-22377 Ambari 3.0: Implement new design for Admin View: Views page. (atkach)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/dd0421a2
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/dd0421a2
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/dd0421a2
Branch: refs/heads/trunk
Commit: dd0421a214f2f9b6c2546bad6d2bc5d743094a40
Parents: 654404d
Author: Andrii Tkach <at...@apache.org>
Authored: Tue Nov 7 18:17:20 2017 +0200
Committer: Andrii Tkach <at...@apache.org>
Committed: Tue Nov 7 19:52:10 2017 +0200
----------------------------------------------------------------------
.../main/resources/ui/admin-web/app/index.html | 1 +
.../ambariViews/CloneViewInstanceCtrl.js | 274 ++++++++++++++
.../ambariViews/CreateViewInstanceCtrl.js | 353 +++++++-----------
.../controllers/ambariViews/ViewsListCtrl.js | 360 +++++++------------
.../ui/admin-web/app/scripts/i18n.config.js | 14 +-
.../ui/admin-web/app/scripts/routes.js | 34 +-
.../ui/admin-web/app/scripts/services/View.js | 32 +-
.../resources/ui/admin-web/app/styles/main.css | 45 ++-
.../resources/ui/admin-web/app/styles/views.css | 49 +++
.../app/views/ambariViews/listTable.html | 110 ------
.../app/views/ambariViews/listUrls.html | 117 ------
.../app/views/ambariViews/modals/create.html | 238 +++++++-----
.../app/views/ambariViews/modals/edit.html | 138 -------
.../app/views/ambariViews/viewsList.html | 134 +++++++
.../ui/admin-web/app/views/urls/create.html | 4 +-
.../ui/admin-web/app/views/urls/edit.html | 4 +-
.../unit/controllers/CloneViewInstanceCtrl.js | 135 +++++++
.../unit/controllers/CreateViewInstanceCtrl.js | 135 -------
18 files changed, 1050 insertions(+), 1127 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/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 e9983aa..41cc60f 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
@@ -139,6 +139,7 @@
<script src="scripts/controllers/ambariViews/ViewUrlCtrl.js"></script>
<script src="scripts/controllers/ambariViews/ViewUrlEditCtrl.js"></script>
<script src="scripts/controllers/ambariViews/CreateViewInstanceCtrl.js"></script>
+<script src="scripts/controllers/ambariViews/CloneViewInstanceCtrl.js"></script>
<script src="scripts/controllers/clusters/ClustersManageAccessCtrl.js"></script>
<script src="scripts/controllers/clusters/UserAccessListCtrl.js"></script>
<script src="scripts/controllers/clusters/ExportBlueprintCtrl.js"></script>
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CloneViewInstanceCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CloneViewInstanceCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CloneViewInstanceCtrl.js
new file mode 100644
index 0000000..cb37e63
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/CloneViewInstanceCtrl.js
@@ -0,0 +1,274 @@
+/**
+ * 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')
+.controller('CloneViewInstanceCtrl',['$scope', 'View','RemoteCluster' , 'Alert', 'Cluster', '$routeParams', '$location', 'UnsavedDialog', '$translate', function($scope, View, RemoteCluster, Alert, Cluster, $routeParams, $location, UnsavedDialog, $translate) {
+ var $t = $translate.instant;
+ $scope.form = {};
+ $scope.constants = {
+ props: $t('views.properties')
+ };
+ $scope.isClone = $routeParams.instanceId ? true : false;
+ var targetUrl = '';
+
+ function loadMeta(){
+ View.getMeta($routeParams.viewId, $scope.version).then(function(data) {
+ var viewVersion = data.data,
+ 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');
+ item.clusterConfig ? $scope.numberOfClusterConfigs++ : $scope.numberOfSettingConfigs++;
+ });
+
+ $scope.clusterConfigurable = viewVersion.ViewVersionInfo.cluster_configurable;
+ $scope.clusterConfigurableErrorMsg = $scope.clusterConfigurable ? "" : $t('views.alerts.cannotUseOption');
+
+ $scope.instance = {
+ view_name: viewVersion.ViewVersionInfo.view_name,
+ version: viewVersion.ViewVersionInfo.version,
+ instance_name: '',
+ label: '',
+ visible: true,
+ icon_path: '',
+ icon64_path: '',
+ properties: parameters,
+ description: '',
+ clusterType: 'NONE'
+ };
+
+ //if cloning view instance, then get the instance data and populate settings and properties
+ if($scope.isClone) {
+ View.getInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId)
+ .then(function(instance) {
+ $scope.instanceClone = instance;
+ $scope.instance.version = instance.ViewInstanceInfo.version;
+ $scope.version = instance.ViewInstanceInfo.version;
+ $scope.instance.instance_name = instance.ViewInstanceInfo.instance_name + $t('common.copy');
+ $scope.instance.label = instance.ViewInstanceInfo.label + $t('common.copy');
+ $scope.instance.visible = instance.ViewInstanceInfo.visible;
+ $scope.instance.description = instance.ViewInstanceInfo.description;
+ $scope.instance.clusterType=instance.ViewInstanceInfo.cluster_type;
+
+ initConfigurations(parameters);
+ })
+ .catch(function(data) {
+ Alert.error($t('views.alerts.cannotLoadInstanceInfo'), data.data.message);
+ });
+ }
+
+ loadClusters();
+ loadRemoteClusters();
+
+ });
+ }
+
+ function initConfigurations(parameters) {
+ var configuration = angular.copy($scope.instanceClone.ViewInstanceInfo.properties);
+
+ //iterate through the view parameters and get the values from the instance being cloned
+ for (var i = 0; i < parameters.length; i++) {
+ parameters[i].value = configuration[parameters[i].name];
+ parameters[i].clusterConfig = !!parameters[i].clusterConfig;
+ }
+ }
+
+ $scope.$watch(function(scope) {
+ return scope.version;
+ }, function(version) {
+ if( version ){
+ loadMeta();
+ }
+ });
+
+ $scope.enableLocalCluster = function () {
+ if($scope.errorKeys.length > 0) {
+ $scope.errorKeys.forEach( function (key) {
+ try {
+ $scope.form.instanceCreateForm[key].validationError = false;
+ $scope.form.instanceCreateForm[key].validationMessage = '';
+ } catch (e) {
+ console.log($t('views.alerts.unableToResetErrorMessage', {key: key}));
+ }
+ });
+ $scope.errorKeys = [];
+ }
+ };
+
+ // $scope.view = viewVersion;
+ $scope.isAdvancedClosed = true;
+ $scope.instanceExists = false;
+ $scope.errorKeys = [];
+
+ $scope.clusterConfigurable = false;
+ $scope.clusterConfigurableErrorMsg = "";
+ $scope.clusters = [];
+ $scope.remoteClusters = [];
+ $scope.noLocalClusterAvailible = true;
+ $scope.noRemoteClusterAvailible = true;
+ $scope.cluster = null;
+ $scope.data = {};
+ $scope.data.remoteCluster = null;
+ $scope.numberOfClusterConfigs = 0;
+ $scope.numberOfSettingConfigs = 0;
+
+ function loadClusters() {
+ Cluster.getAllClusters().then(function (clusters) {
+ if(clusters.length >0){
+ clusters.forEach(function(cluster) {
+ $scope.clusters.push({
+ "name" : cluster.Clusters.cluster_name,
+ "id" : cluster.Clusters.cluster_id
+ })
+ });
+ $scope.noLocalClusterAvailible = false;
+ //do not set to default Local Cluster configuration when cloning instance
+ if($scope.clusterConfigurable && !$scope.isClone){
+ $scope.instance.clusterType = "LOCAL_AMBARI";
+ }
+ }else{
+ $scope.clusters.push($t('common.noClusters'));
+ }
+ $scope.cluster = $scope.clusters[0];
+ });
+ }
+
+ function loadRemoteClusters() {
+ RemoteCluster.listAll().then(function (clusters) {
+ if(clusters.length >0){
+ clusters.forEach(function(cluster) {
+ $scope.remoteClusters.push({
+ "name" : cluster.ClusterInfo.name,
+ "id" : cluster.ClusterInfo.cluster_id
+ })
+ });
+ $scope.noRemoteClusterAvailible = false;
+ }else{
+ $scope.remoteClusters.push($t('common.noClusters'));
+ }
+ $scope.data.remoteCluster = $scope.remoteClusters[0];
+ });
+ }
+
+
+ $scope.versions = [];
+ $scope.version = null;
+
+ View.getVersions($routeParams.viewId).then(function(versions) {
+ $scope.versions = versions;
+ $scope.version = $scope.versions[$scope.versions.length-1];
+ });
+
+
+ $scope.nameValidationPattern = /^\s*\w*\s*$/;
+
+ $scope.save = function() {
+ if (!$scope.form.instanceCreateForm.isSaving) {
+ $scope.form.instanceCreateForm.submitted = true;
+ if($scope.form.instanceCreateForm.$valid){
+ $scope.form.instanceCreateForm.isSaving = true;
+
+ switch($scope.instance.clusterType) {
+ case 'LOCAL_AMBARI':
+ console.log($scope.cluster);
+ $scope.instance.clusterId = $scope.cluster.id;
+ break;
+ case 'REMOTE_AMBARI':
+ console.log($scope.data.remoteCluster);
+ $scope.instance.clusterId = $scope.data.remoteCluster.id;
+
+ break;
+ default:
+ $scope.instance.clusterId = null;
+ }
+ console.log($scope.instance.clusterId);
+ View.createInstance($scope.instance)
+ .then(function(data) {
+ Alert.success($t('views.alerts.instanceCreated', {instanceName: $scope.instance.instance_name}));
+ $scope.form.instanceCreateForm.$setPristine();
+ if( targetUrl ){
+ $location.path(targetUrl);
+ } else {
+ $location.path('/views/' + $scope.instance.view_name + '/versions/' + $scope.instance.version + '/instances/' + $scope.instance.instance_name + '/edit');
+ }
+ $scope.form.instanceCreateForm.isSaving = false;
+ $scope.$root.$emit('instancesUpdate');
+ })
+ .catch(function (data) {
+ var errorMessage = data.message;
+ var showGeneralError = true;
+
+ if (data.status >= 400 && $scope.instance.clusterType == 'NONE') {
+ try {
+ var errorObject = JSON.parse(errorMessage);
+ errorMessage = errorObject.detail;
+ angular.forEach(errorObject.propertyResults, function (item, key) {
+ $scope.form.instanceCreateForm[key].validationError = !item.valid;
+ if (!item.valid) {
+ showGeneralError = false;
+ $scope.form.instanceCreateForm[key].validationMessage = item.detail;
+ $scope.errorKeys.push(key);
+ }
+ });
+
+ if (showGeneralError) {
+ $scope.form.instanceCreateForm.generalValidationError = errorMessage;
+ }
+ } catch (e) {
+ console.error($t('views.alerts.unableToParseError', {message: data.message}));
+ }
+ }
+ Alert.error($t('views.alerts.cannotCreateInstance'), errorMessage);
+ $scope.form.instanceCreateForm.isSaving = false;
+ });
+ }
+ }
+ };
+
+ $scope.cancel = function() {
+ $scope.form.instanceCreateForm.$setPristine();
+ $location.path('/views');
+ };
+
+ $scope.$on('$locationChangeStart', function(event, __targetUrl) {
+ if( $scope.form.instanceCreateForm.$dirty ){
+ UnsavedDialog().then(function(action) {
+ targetUrl = __targetUrl.split('#').pop();
+ switch(action){
+ case 'save':
+ $scope.save();
+ break;
+ case 'discard':
+ $scope.form.instanceCreateForm.$setPristine();
+ $location.path(targetUrl);
+ break;
+ case 'cancel':
+ targetUrl = '';
+ break;
+ }
+ });
+ event.preventDefault();
+ }
+ });
+}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/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 94b8cc1..d5e3758 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,263 +18,170 @@
'use strict';
angular.module('ambariAdminConsole')
-.controller('CreateViewInstanceCtrl',['$scope', 'View','RemoteCluster' , 'Alert', 'Cluster', '$routeParams', '$location', 'UnsavedDialog', '$translate', function($scope, View, RemoteCluster, Alert, Cluster, $routeParams, $location, UnsavedDialog, $translate) {
+.controller('CreateViewInstanceCtrl',
+['$scope', 'View','RemoteCluster' , 'Alert', 'Cluster', '$routeParams', '$location', 'UnsavedDialog', '$translate', '$modalInstance', 'views', '$q',
+function($scope, View, RemoteCluster, Alert, Cluster, $routeParams, $location, UnsavedDialog, $translate, $modalInstance, views, $q) {
+
var $t = $translate.instant;
+ var viewToVersionMap = {};
+ var instances = {};
$scope.form = {};
- $scope.constants = {
- props: $t('views.properties')
+ $scope.nameValidationPattern = /^\s*\w*\s*$/;
+ $scope.isLoading = false;
+ $scope.isLocalTypeChosen = true;
+ $scope.views = views;
+ $scope.viewOptions = [];
+ $scope.versionOptions = [];
+ $scope.localClusters = [];
+ $scope.remoteClusters = [];
+ $scope.clusterOptions = [];
+ $scope.isInstanceExists = false;
+ $scope.formData = {
+ view: null,
+ version: null,
+ instanceName: '',
+ displayName: '',
+ description: '',
+ clusterName: null,
+ visible: true
};
- $scope.isClone = $routeParams.instanceId ? true : false;
- var targetUrl = '';
-
- function loadMeta(){
- View.getMeta($routeParams.viewId, $scope.version).then(function(data) {
- var viewVersion = data.data,
- 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');
- item.clusterConfig ? $scope.numberOfClusterConfigs++ : $scope.numberOfSettingConfigs++;
- });
-
- $scope.clusterConfigurable = viewVersion.ViewVersionInfo.cluster_configurable;
- $scope.clusterConfigurableErrorMsg = $scope.clusterConfigurable ? "" : $t('views.alerts.cannotUseOption');
-
- $scope.instance = {
- view_name: viewVersion.ViewVersionInfo.view_name,
- version: viewVersion.ViewVersionInfo.version,
- instance_name: '',
- label: '',
- visible: true,
- icon_path: '',
- icon64_path: '',
- properties: parameters,
- description: '',
- clusterType: 'NONE'
- };
-
- //if cloning view instance, then get the instance data and populate settings and properties
- if($scope.isClone) {
- View.getInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId)
- .then(function(instance) {
- $scope.instanceClone = instance;
- $scope.instance.version = instance.ViewInstanceInfo.version;
- $scope.version = instance.ViewInstanceInfo.version;
- $scope.instance.instance_name = instance.ViewInstanceInfo.instance_name + $t('common.copy');
- $scope.instance.label = instance.ViewInstanceInfo.label + $t('common.copy');
- $scope.instance.visible = instance.ViewInstanceInfo.visible;
- $scope.instance.description = instance.ViewInstanceInfo.description;
- $scope.instance.clusterType=instance.ViewInstanceInfo.cluster_type;
-
- initConfigurations(parameters);
- })
- .catch(function(data) {
- Alert.error($t('views.alerts.cannotLoadInstanceInfo'), data.data.message);
- });
- }
-
- loadClusters();
- loadRemoteClusters();
-
- });
- }
- function initConfigurations(parameters) {
- var configuration = angular.copy($scope.instanceClone.ViewInstanceInfo.properties);
-
- //iterate through the view parameters and get the values from the instance being cloned
- for (var i = 0; i < parameters.length; i++) {
- parameters[i].value = configuration[parameters[i].name];
- parameters[i].clusterConfig = !!parameters[i].clusterConfig;
- }
+ $scope.updateVersionOptions = function () {
+ if (viewToVersionMap[$scope.formData.view.value]) {
+ $scope.versionOptions = viewToVersionMap[$scope.formData.view.value];
+ $scope.formData.version = $scope.versionOptions[0];
}
+ };
- $scope.$watch(function(scope) {
- return scope.version;
- }, function(version) {
- if( version ){
- loadMeta();
- }
- });
-
- $scope.enableLocalCluster = function () {
- if($scope.errorKeys.length > 0) {
- $scope.errorKeys.forEach( function (key) {
- try {
- $scope.form.instanceCreateForm[key].validationError = false;
- $scope.form.instanceCreateForm[key].validationMessage = '';
- } catch (e) {
- console.log($t('views.alerts.unableToResetErrorMessage', {key: key}));
- }
- });
- $scope.errorKeys = [];
+ $scope.switchClusterType = function(bool) {
+ $scope.isLocalTypeChosen = bool;
+ if ($scope.isLocalTypeChosen) {
+ $scope.clusterOptions = $scope.localClusters;
+ } else {
+ $scope.clusterOptions = $scope.remoteClusters;
}
+ $scope.formData.clusterName = $scope.clusterOptions[0];
};
- // $scope.view = viewVersion;
- $scope.isAdvancedClosed = true;
- $scope.instanceExists = false;
- $scope.errorKeys = [];
-
- $scope.clusterConfigurable = false;
- $scope.clusterConfigurableErrorMsg = "";
- $scope.clusters = [];
- $scope.remoteClusters = [];
- $scope.noLocalClusterAvailible = true;
- $scope.noRemoteClusterAvailible = true;
- $scope.cluster = null;
- $scope.data = {};
- $scope.data.remoteCluster = null;
- $scope.numberOfClusterConfigs = 0;
- $scope.numberOfSettingConfigs = 0;
-
- function loadClusters() {
- Cluster.getAllClusters().then(function (clusters) {
- if(clusters.length >0){
- clusters.forEach(function(cluster) {
- $scope.clusters.push({
- "name" : cluster.Clusters.cluster_name,
- "id" : cluster.Clusters.cluster_id
- })
- });
- $scope.noLocalClusterAvailible = false;
- //do not set to default Local Cluster configuration when cloning instance
- if($scope.clusterConfigurable && !$scope.isClone){
- $scope.instance.clusterType = "LOCAL_AMBARI";
- }
- }else{
- $scope.clusters.push($t('common.noClusters'));
- }
- $scope.cluster = $scope.clusters[0];
- });
- }
-
- function loadRemoteClusters() {
- RemoteCluster.listAll().then(function (clusters) {
- if(clusters.length >0){
- clusters.forEach(function(cluster) {
- $scope.remoteClusters.push({
- "name" : cluster.ClusterInfo.name,
- "id" : cluster.ClusterInfo.cluster_id
- })
- });
- $scope.noRemoteClusterAvailible = false;
- }else{
- $scope.remoteClusters.push($t('common.noClusters'));
- }
- $scope.data.remoteCluster = $scope.remoteClusters[0];
- });
- }
-
-
- $scope.versions = [];
- $scope.version = null;
-
- View.getVersions($routeParams.viewId).then(function(versions) {
- $scope.versions = versions;
- $scope.version = $scope.versions[$scope.versions.length-1];
- });
-
-
- $scope.nameValidationPattern = /^\s*\w*\s*$/;
-
- $scope.save = function() {
- if (!$scope.form.instanceCreateForm.isSaving) {
+ $scope.save = function () {
+ var instanceName = $scope.form.instanceCreateForm.instanceName.$viewValue;
$scope.form.instanceCreateForm.submitted = true;
- if($scope.form.instanceCreateForm.$valid){
- $scope.form.instanceCreateForm.isSaving = true;
-
- switch($scope.instance.clusterType) {
- case 'LOCAL_AMBARI':
- console.log($scope.cluster);
- $scope.instance.clusterId = $scope.cluster.id;
- break;
- case 'REMOTE_AMBARI':
- console.log($scope.data.remoteCluster);
- $scope.instance.clusterId = $scope.data.remoteCluster.id;
-
- break;
- default:
- $scope.instance.clusterId = null;
- }
- console.log($scope.instance.clusterId);
- View.createInstance($scope.instance)
- .then(function(data) {
- Alert.success($t('views.alerts.instanceCreated', {instanceName: $scope.instance.instance_name}));
- $scope.form.instanceCreateForm.$setPristine();
- if( targetUrl ){
- $location.path(targetUrl);
- } else {
- $location.path('/views/' + $scope.instance.view_name + '/versions/' + $scope.instance.version + '/instances/' + $scope.instance.instance_name + '/edit');
- }
- $scope.form.instanceCreateForm.isSaving = false;
- $scope.$root.$emit('instancesUpdate');
+ if ($scope.form.instanceCreateForm.$valid) {
+ View.createInstance({
+ instance_name: instanceName,
+ label: $scope.form.instanceCreateForm.displayName.$viewValue,
+ visible: $scope.form.instanceCreateForm.visible.$viewValue,
+ icon_path: '',
+ icon64_path: '',
+ description: $scope.form.instanceCreateForm.description.$viewValue,
+ view_name: $scope.form.instanceCreateForm.view.$viewValue.value,
+ version: $scope.form.instanceCreateForm.version.$viewValue.value,
+ properties: [],
+ clusterId: $scope.form.instanceCreateForm.clusterName.$viewValue.id,
+ clusterType: $scope.isLocalTypeChosen ? 'LOCAL_AMBARI': 'REMOTE_AMBARI'
+ })
+ .then(function () {
+ $modalInstance.dismiss('created');
+ Alert.success($t('views.alerts.instanceCreated', {instanceName: instanceName}));
+ $location.path('/views/' + $scope.form.instanceCreateForm.view.$viewValue.value +
+ '/versions/' + $scope.form.instanceCreateForm.version.$viewValue.value +
+ '/instances/' + instanceName + '/edit');
})
.catch(function (data) {
var errorMessage = data.message;
- var showGeneralError = true;
- if (data.status >= 400 && $scope.instance.clusterType == 'NONE') {
+ if (data.status >= 400) {
try {
- var errorObject = JSON.parse(errorMessage);
- errorMessage = errorObject.detail;
- angular.forEach(errorObject.propertyResults, function (item, key) {
- $scope.form.instanceCreateForm[key].validationError = !item.valid;
- if (!item.valid) {
- showGeneralError = false;
- $scope.form.instanceCreateForm[key].validationMessage = item.detail;
- $scope.errorKeys.push(key);
- }
- });
-
- if (showGeneralError) {
- $scope.form.instanceCreateForm.generalValidationError = errorMessage;
- }
+ errorMessage = JSON.parse(errorMessage).detail;
} catch (e) {
- console.error($t('views.alerts.unableToParseError', {message: data.message}));
+ console.warn(data.message, e);
}
}
Alert.error($t('views.alerts.cannotCreateInstance'), errorMessage);
- $scope.form.instanceCreateForm.isSaving = false;
});
- }
}
};
- $scope.cancel = function() {
- $scope.form.instanceCreateForm.$setPristine();
- $location.path('/views');
+ $scope.cancel = function () {
+ unsavedChangesCheck();
+ };
+
+ $scope.checkIfInstanceExist = function() {
+ $scope.isInstanceExists = Boolean(instances[$scope.formData.instanceName]);
};
- $scope.$on('$locationChangeStart', function(event, __targetUrl) {
- if( $scope.form.instanceCreateForm.$dirty ){
- UnsavedDialog().then(function(action) {
- targetUrl = __targetUrl.split('#').pop();
- switch(action){
+ function initViewAndVersionSelect () {
+ $scope.viewOptions = [];
+ angular.forEach($scope.views, function(view) {
+ $scope.viewOptions.push({
+ label: view.view_name,
+ value: view.view_name
+ });
+ viewToVersionMap[view.view_name] = view.versionsList.map(function(version) {
+ angular.forEach(version.instances, function(instance) {
+ instances[instance.ViewInstanceInfo.instance_name] = true;
+ });
+ return {
+ label: version.ViewVersionInfo.version,
+ value: version.ViewVersionInfo.version
+ }
+ });
+ });
+ $scope.formData.view = $scope.viewOptions[0];
+ $scope.updateVersionOptions();
+ }
+
+ function loadClusters() {
+ return Cluster.getAllClusters().then(function (clusters) {
+ clusters.forEach(function (cluster) {
+ $scope.localClusters.push({
+ label: cluster.Clusters.cluster_name,
+ value: cluster.Clusters.cluster_name,
+ id: cluster.Clusters.cluster_id
+ });
+ });
+ });
+ }
+
+ function loadRemoteClusters() {
+ return RemoteCluster.listAll().then(function (clusters) {
+ clusters.forEach(function (cluster) {
+ $scope.remoteClusters.push({
+ label: cluster.ClusterInfo.name,
+ value: cluster.ClusterInfo.name,
+ id: cluster.ClusterInfo.cluster_id
+ });
+ });
+ });
+ }
+
+ function loadFormData () {
+ $scope.isLoading = true;
+ initViewAndVersionSelect();
+ $q.all(loadClusters(), loadRemoteClusters()).then(function() {
+ $scope.isLoading = false;
+ $scope.switchClusterType(true);
+ });
+ }
+
+ function unsavedChangesCheck() {
+ if ($scope.form.instanceCreateForm.$dirty) {
+ UnsavedDialog().then(function (action) {
+ switch (action) {
case 'save':
$scope.save();
break;
case 'discard':
- $scope.form.instanceCreateForm.$setPristine();
- $location.path(targetUrl);
+ $modalInstance.close('discard');
break;
case 'cancel':
- targetUrl = '';
break;
}
});
- event.preventDefault();
+ } else {
+ $modalInstance.close('discard');
}
- });
-
-
-
-
-
+ }
+ loadFormData();
}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
index 4e7bae3..aba5702 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
@@ -18,272 +18,186 @@
'use strict';
angular.module('ambariAdminConsole')
-.controller('ViewsListCtrl',['$scope', 'View','$modal', 'Alert', 'ConfirmationModal', '$location', '$translate', function($scope, View, $modal, Alert, ConfirmationModal, $location, $translate) {
- var deferredList = [],
- $t = $translate.instant;
- $scope.isLoadingViews = false;
- $scope.isLoadingUrls = false;
- $scope.constants = {
- unable: $t('views.alerts.unableToCreate'),
- views: $t('common.views').toLowerCase()
- };
- $scope.$on('$locationChangeStart', function() {
- deferredList.forEach(function(def) {
- def.reject();
- })
- });
-
- $scope.createUrlDisabled = false;
+.controller('ViewsListCtrl',['$scope', 'View','$modal', 'Alert', 'ConfirmationModal', '$translate', function($scope, View, $modal, Alert, ConfirmationModal, $translate) {
+ var $t = $translate.instant;
+ var VIEWS_VERSION_STATUS_TIMEOUT = 5000;
+ $scope.isLoading = false;
+ $scope.minInstanceForPagination = 10;
- function checkViewVersionStatus(view, versionObj, versionNumber){
+ function checkViewVersionStatus(view, versionObj, versionNumber) {
var deferred = View.checkViewVersionStatus(view.view_name, versionNumber);
- deferredList.push(deferred);
- deferred.promise.then(function(status) {
- deferredList.splice(deferredList.indexOf(deferred), 1);
- if (status !== 'DEPLOYED' && status !== 'ERROR') {
- checkViewVersionStatus(view, versionObj, versionNumber);
+ deferred.promise.then(function (status) {
+ if (versionNeedStatusUpdate(status)) {
+ setTimeout(function() {
+ checkViewVersionStatus(view, versionObj, versionNumber);
+ }, VIEWS_VERSION_STATUS_TIMEOUT);
} else {
- $scope.$evalAsync(function() {
- versionObj.status = status;
- angular.forEach(view.versions, function(version) {
- if(version.status === 'DEPLOYED'){
- view.canCreateInstance = true;
- }
- })
- });
+ versionObj.status = status;
+ angular.forEach(view.versions, function (version) {
+ if (version.status === 'DEPLOYED') {
+ view.canCreateInstance = true;
+ }
+ })
}
});
}
- function loadViews(){
- $scope.isLoadingViews = true;
- View.all().then(function(views) {
- $scope.isLoadingViews = false;
+ function versionNeedStatusUpdate(status) {
+ return status !== 'DEPLOYED' && status !== 'ERROR';
+ }
+
+ function loadViews() {
+ $scope.isLoading = true;
+ View.all().then(function (views) {
+ $scope.isLoading = false;
$scope.views = views;
- $scope.getFilteredViews();
- angular.forEach(views, function(view) {
- angular.forEach(view.versions, function(versionObj, versionNumber) {
- if (versionObj.status !== 'DEPLOYED' || versionObj.status !== 'ERROR'){
- checkViewVersionStatus(view, versionObj, versionNumber);
- }
+ $scope.instances = [];
+ angular.forEach(views, function (view) {
+ // TODO uncomment if view need status update
+ // angular.forEach(view.versions, function (versionObj, versionNumber) {
+ // if (versionNeedStatusUpdate(versionObj.status)) {
+ // checkViewVersionStatus(view, versionObj, versionNumber);
+ // }
+ // });
+ angular.forEach(view.instances, function (instance) {
+ instance.ViewInstanceInfo.short_url_name = instance.ViewInstanceInfo.short_url_name || '';
+ instance.ViewInstanceInfo.short_url = instance.ViewInstanceInfo.short_url || '';
+ $scope.instances.push(instance.ViewInstanceInfo);
});
- })
- }).catch(function(data) {
+ });
+ initTypeFilter();
+ $scope.filterInstances();
+ }).catch(function (data) {
Alert.error($t('views.alerts.cannotLoadViews'), data.data.message);
});
}
- loadViews();
+ function initTypeFilter() {
+ var uniqTypes = $.unique($scope.instances.map(function(instance) {
+ return instance.view_name;
+ }));
+ $scope.typeFilterOptions = [ { label: $t('common.all'), value: '*'} ]
+ .concat(uniqTypes.map(function(type) {
+ return {
+ label: type,
+ value: type
+ };
+ }));
+ $scope.instanceTypeFilter = $scope.typeFilterOptions[0];
+ }
- $scope.createInstance = function(view) {
- var modalInstance = $modal.open({
- templateUrl: 'views/ambariViews/modals/create.html',
- size: 'lg',
- controller: 'CreateViewInstanceCtrl',
- resolve: {
- viewVersion: function(){
- return view.versionsList[ view.versionsList.length-1];
+ function showInstancesOnPage() {
+ var startIndex = ($scope.currentPage - 1) * $scope.instancesPerPage + 1;
+ var endIndex = $scope.currentPage * $scope.instancesPerPage;
+ var showedCount = 0;
+ var filteredCount = 0;
+
+ angular.forEach($scope.instances, function(instance) {
+ instance.isShowed = false;
+ if (instance.isFiltered) {
+ filteredCount++;
+ if (filteredCount >= startIndex && filteredCount <= endIndex) {
+ instance.isShowed = true;
+ showedCount++;
}
}
});
+ $scope.tableInfo.showed = showedCount;
+ }
- modalInstance.result.then(loadViews);
- };
-
- $scope.viewsFilter = '';
- $scope.filteredViews = [];
- $scope.getFilteredViews = function(views) {
- var result = [];
- var filter = $scope.viewsFilter.toLowerCase();
- if(!filter){ // if no filter return all views
- result = $scope.views.map(function(view) {
- view.isOpened = false;
- return view;
- });
- } else {
- result = $scope.views.map(function(view) {
- view.isOpened = true;
- if(view.view_name.toLowerCase().indexOf(filter) >= 0){
- return view; // if filter matched with view name -- return whole view
- } else {
- var instances = [];
- angular.forEach(view.instances, function(instance) {
- if(instance.ViewInstanceInfo.label.toLowerCase().indexOf(filter) >= 0){
- instances.push(instance);
- }
- });
- if( instances.length ){ // If inside view exists instances with matched filter - show only this instances
- var v = angular.copy(view);
- v.instances = instances;
- return v;
- }
- }
- }).filter(function(view) {
- return !!view; // Remove 'undefined'
- });
- }
- $scope.filteredViews = result;
- };
-
- $scope.gotoCreate = function(viewName, isAllowed) {
- if(isAllowed){
- $location.path('/views/'+viewName+'/new');
- }
- };
-
- $scope.deleteInstance = function(instance) {
- ConfirmationModal.show(
- $t('common.delete', {
- term: $t('views.viewInstance')
- }),
- $t('common.deleteConfirmation', {
- instanceType: $t('views.viewInstance'),
- instanceName: instance.ViewInstanceInfo.label
- })
- ).then(function() {
- View.deleteInstance(instance.ViewInstanceInfo.view_name, instance.ViewInstanceInfo.version, instance.ViewInstanceInfo.instance_name)
- .then(function() {
- loadViews();
- })
- .catch(function(data) {
- Alert.error($t('views.alerts.cannotDeleteInstance'), data.data.message);
- });
- });
- };
-
- $scope.reloadViews = function () {
- loadViews();
- };
-
- /**
- * Url listing
- */
-
- $scope.loadedUrls = [];
- $scope.urlsPerPage = 10;
+ $scope.views = [];
+ $scope.instances = [];
+ $scope.instancesPerPage = 10;
$scope.currentPage = 1;
- $scope.totalUrls = 1;
- $scope.urlNameFilter = '';
- $scope.urlSuffixfilter = '';
- $scope.maxVisiblePages=20;
+ $scope.instanceNameFilter = '';
+ $scope.instanceUrlFilter = '';
+ $scope.maxVisiblePages = 10;
+ $scope.isNotEmptyFilter = true;
+ $scope.instanceTypeFilter = '';
$scope.tableInfo = {
- total: 0,
+ filtered: 0,
showed: 0
};
- $scope.isNotEmptyFilter = true;
-
-
- $scope.pageChanged = function() {
- $scope.listViewUrls();
- };
+ loadViews();
- $scope.urlsPerPageChanged = function() {
+ $scope.filterInstances = function() {
+ var filteredCount = 0;
+ angular.forEach($scope.instances, function(instance) {
+ if ($scope.instanceNameFilter && instance.short_url_name.indexOf($scope.instanceNameFilter) === -1) {
+ return instance.isFiltered = false;
+ }
+ if ($scope.instanceUrlFilter && ('/main/view/'+ instance.view_name + '/' + instance.short_url).indexOf($scope.instanceUrlFilter) === -1) {
+ return instance.isFiltered = false;
+ }
+ if ($scope.instanceTypeFilter.value !== '*' && instance.view_name.indexOf($scope.instanceTypeFilter.value) === -1) {
+ return instance.isFiltered = false;
+ }
+ filteredCount++;
+ instance.isFiltered = true;
+ });
+ $scope.tableInfo.filtered = filteredCount;
$scope.resetPagination();
};
+ $scope.pageChanged = function() {
+ showInstancesOnPage();
+ };
$scope.resetPagination = function() {
$scope.currentPage = 1;
- $scope.listViewUrls();
+ showInstancesOnPage();
};
-
- $scope.getVersions = function(instances) {
- var names = [];
-
- instances.map(function(view){
- var name = view.view_name;
- names.push(name);
- });
-
- var output = [],
- keys = [];
-
- angular.forEach(names, function(item) {
- var key = item;
- if(keys.indexOf(key) === -1) {
- keys.push(key);
- output.push(item);
- }
- });
- return output;
- };
-
-
-
$scope.clearFilters = function () {
- $scope.urlNameFilter = '';
- $scope.urlSuffixfilter = '';
+ $scope.instanceNameFilter = '';
+ $scope.instanceUrlFilter = '';
$scope.instanceTypeFilter = $scope.typeFilterOptions[0];
$scope.resetPagination();
};
-
-
$scope.$watch(
- function (scope) {
- return Boolean(scope.urlNameFilter || scope.urlSuffixfilter || (scope.instanceTypeFilter && scope.instanceTypeFilter.value !== '*'));
- },
- function (newValue, oldValue, scope) {
- scope.isNotEmptyFilter = newValue;
- }
+ function (scope) {
+ return Boolean(scope.instanceNameFilter || scope.instanceUrlFilter || (scope.instanceTypeFilter && scope.instanceTypeFilter.value !== '*'));
+ },
+ function (newValue, oldValue, scope) {
+ scope.isNotEmptyFilter = newValue;
+ }
);
-
-
-
- $scope.listViewUrls = function(){
- $scope.isLoadingUrls = true;
- View.allUrls({
- currentPage: $scope.currentPage,
- urlsPerPage: $scope.urlsPerPage,
- searchString: $scope.urlNameFilter,
- suffixSearch: $scope.urlSuffixfilter,
- instanceType: $scope.instanceTypeFilter?$scope.instanceTypeFilter.value:'*'
- }).then(function(urls) {
- $scope.isLoadingUrls = false;
- $scope.urls = urls;
- $scope.ViewNameFilterOptions = urls.items.map(function(url){
- return url.ViewUrlInfo.view_instance_common_name;
- });
-
- $scope.totalUrls = urls.itemTotal;
- $scope.tableInfo.showed = urls.items.length;
- $scope.tableInfo.total = urls.itemTotal;
-
- // get all view instances to enable/disable creation if empty
-
- }).catch(function(data) {
- Alert.error($t('views.alerts.cannotLoadViewUrls'), data.message);
+ $scope.createInstance = function () {
+ var modalInstance = $modal.open({
+ templateUrl: 'views/ambariViews/modals/create.html',
+ controller: 'CreateViewInstanceCtrl',
+ resolve: {
+ views: function() {
+ return $scope.views;
+ }
+ },
+ backdrop: 'static'
});
- };
+ modalInstance.result.then(loadViews);
+ };
- $scope.initViewUrls = function(){
- $scope.listViewUrls();
- View.getAllVisibleInstance().then(function(instances){
- // if no instances then disable the create button
- if(!instances.length){
- $scope.createUrlDisabled = true;
- } else {
- $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
- .concat($scope.getVersions(instances).map(function(key) {
- return {
- label: key,
- value: key
- };
- }));
-
- $scope.instanceTypeFilter = $scope.typeFilterOptions[0];
- }
-
- }).catch(function(data) {
- // Make the create button enabled, and swallow the error
- $scope.createUrlDisabled = false;
+ $scope.deleteInstance = function (instance) {
+ ConfirmationModal.show(
+ $t('common.delete', {
+ term: $t('views.viewInstance')
+ }),
+ $t('common.deleteConfirmation', {
+ instanceType: $t('views.viewInstance'),
+ instanceName: instance.label
+ })
+ ).then(function () {
+ View.deleteInstance(instance.view_name, instance.version, instance.instance_name)
+ .then(function () {
+ loadViews();
+ })
+ .catch(function (data) {
+ Alert.error($t('views.alerts.cannotDeleteInstance'), data.data.message);
+ });
});
-
};
-
-}]);
\ No newline at end of file
+}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/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 cb52df1..73ab064 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
@@ -32,7 +32,6 @@ angular.module('ambariAdminConsole')
'common.register': 'Register',
'common.clusters': 'Clusters',
'common.views': 'Views',
- 'common.viewUrls': 'View URLs',
'common.roles': 'Roles',
'common.users': 'Users',
'common.groups': 'Groups',
@@ -80,6 +79,7 @@ angular.module('ambariAdminConsole')
'common.remoteClusterDelConfirmation': 'Are you sure you want to delete {{instanceType}} {{instanceName}}? This operation cannot be undone.',
'common.messageInstanceAffected': 'The following View Instances are using this Remote Cluster for configuration, and will need to be reconfigured:',
'common.local': 'Local',
+ 'common.remote': 'Remote',
'common.pam': 'PAM',
'common.ldap': 'LDAP',
'common.jwt': 'JWT',
@@ -100,6 +100,7 @@ angular.module('ambariAdminConsole')
'common.clusterManagement': 'Cluster Management',
'common.userManagement': 'User Management',
'common.admin': 'Admin',
+ 'common.actions': 'Actions',
'common.clusterNameChangeConfirmation.title': 'Confirm Cluster Name Change',
'common.clusterNameChangeConfirmation.message': 'Are you sure you want to change the cluster name to {{clusterName}}?',
@@ -191,7 +192,7 @@ angular.module('ambariAdminConsole')
'views.viewInstance': 'View Instance',
'views.create': 'Create Instance',
'views.clone': 'Clone Instance',
- 'views.createViewInstance': 'Create View Instance',
+ 'views.createViewInstance': 'Create Instance',
'views.edit': 'Edit',
'views.viewName': 'View Name',
'views.instances': 'Instances',
@@ -239,7 +240,6 @@ angular.module('ambariAdminConsole')
'views.alerts.cannotEditInstance': 'Cannot Edit Static Instances',
'views.alerts.cannotDeleteStaticInstance': 'Cannot Delete Static Instances',
'views.alerts.deployError': 'Error deploying. Check Ambari Server log.',
- 'views.alerts.unableToCreate': 'Unable to create view instances',
'views.alerts.cannotUseOption': 'This view cannot use this option',
'views.alerts.unableToResetErrorMessage': 'Unable to reset error message for prop: {{key}}',
'views.alerts.instanceCreated': 'Created View Instance {{instanceName}}',
@@ -256,7 +256,12 @@ angular.module('ambariAdminConsole')
'views.alerts.savedRemoteClusterInformation': 'Remote cluster information is saved.',
'views.alerts.credentialsUpdated': 'Credentials Updated.',
- 'urls.name': 'Name',
+ 'views.table.viewType': 'View Type',
+ 'views.emptyTable': 'No Views to display',
+ 'views.createInstance.selectView': 'Select View',
+ 'views.createInstance.selectVersion': 'Select Version',
+ 'views.createInstance.clusterType': 'Cluster Type',
+
'urls.url': 'URL',
'urls.viewUrls': 'View URLs',
'urls.createNewUrl': 'Create New URL',
@@ -267,7 +272,6 @@ angular.module('ambariAdminConsole')
'urls.step1': 'Create URL',
'urls.step2': 'Select instance',
'urls.step3': 'Assign URL',
- 'urls.noUrlsToDisplay': 'No URLs to display.',
'urls.noViewInstances': 'No view instances',
'urls.none': 'None',
'urls.change': 'Change',
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
index d2d8253..2cb077a 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
@@ -93,14 +93,20 @@ angular.module('ambariAdminConsole')
views: {
list: {
url: '/views',
- templateUrl: 'views/ambariViews/listTable.html',
+ templateUrl: 'views/ambariViews/viewsList.html',
controller: 'ViewsListCtrl',
label: 'Views'
},
- listViewUrls: {
- url: '/viewUrls',
- templateUrl: 'views/ambariViews/listUrls.html',
- controller: 'ViewsListCtrl',
+ clone: {
+ url: '/views/:viewId/versions/:version/instances/:instanceId/clone',
+ templateUrl: 'views/ambariViews/create.html',
+ controller: 'CloneViewInstanceCtrl',
+ label: 'Views'
+ },
+ edit: {
+ url: '/views/:viewId/versions/:version/instances/:instanceId/edit',
+ templateUrl: 'views/ambariViews/edit.html',
+ controller: 'ViewsEditCtrl',
label: 'Views'
},
createViewUrl:{
@@ -120,24 +126,6 @@ angular.module('ambariAdminConsole')
templateUrl: 'views/urls/edit.html',
controller: 'ViewUrlEditCtrl',
label: 'Views'
- },
- clone: {
- url: '/views/:viewId/versions/:version/instances/:instanceId/clone',
- templateUrl: 'views/ambariViews/create.html',
- controller: 'CreateViewInstanceCtrl',
- label: 'Views'
- },
- edit: {
- url: '/views/:viewId/versions/:version/instances/:instanceId/edit',
- templateUrl: 'views/ambariViews/edit.html',
- controller: 'ViewsEditCtrl',
- label: 'Views'
- },
- create: {
- url: '/views/:viewId/new',
- templateUrl: 'views/ambariViews/create.html',
- controller: 'CreateViewInstanceCtrl',
- label: 'Views'
}
},
stackVersions: {
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/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 f549b29..b38b0c2 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
@@ -61,32 +61,6 @@ angular.module('ambariAdminConsole')
angular.element(this,item);
}
- ViewUrl.all = function(params) {
- var deferred = $q.defer();
-
- $http({
- method: 'GET',
- dataType: "json",
- url: Settings.baseUrl + '/view/urls?'
- + 'ViewUrlInfo/url_name.matches(.*'+params.searchString+'.*)'
- + '&ViewUrlInfo/url_suffix.matches(.*'+params.suffixSearch+'.*)'
- + '&fields=*'
- + '&from=' + (params.currentPage-1)*params.urlsPerPage
- + '&page_size=' + params.urlsPerPage
- + (params.instanceType === '*' ? '' : '&ViewUrlInfo/view_instance_common_name=' + params.instanceType)
-
- })
- .success(function(data) {
- deferred.resolve(new ViewUrl(data));
- })
- .error(function(data) {
- deferred.reject(data);
- });
-
- return deferred.promise;
- };
-
-
ViewUrl.updateShortUrl = function(payload){
var deferred = $q.defer();
@@ -176,7 +150,7 @@ angular.module('ambariAdminConsole')
var versions = {};
angular.forEach(item.versions, function(version) {
versions[version.ViewVersionInfo.version] = {count: version.instances.length, status: version.ViewVersionInfo.status};
- if(version.ViewVersionInfo.status === 'DEPLOYED'){ // if atelast one version is deployed
+ if (version.ViewVersionInfo.status === 'DEPLOYED'){ // if at least one version is deployed
self.canCreateInstance = true;
}
@@ -203,10 +177,6 @@ angular.module('ambariAdminConsole')
return ViewInstance.find(viewName, version, instanceName);
};
- View.allUrls = function(req){
- return ViewUrl.all(req)
- };
-
View.getUrlInfo = function(urlName){
return ViewUrl.urlInfo(urlName);
};
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/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 66f23af..bd06bc0 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
@@ -367,10 +367,6 @@ a.gotoinstance{
width: 14px;
}
-.namefilter {
- font-weight: normal;
-}
-
.settings-edit-toggle.disabled, .properties-toggle.disabled{
color: #999;
cursor: not-allowed;
@@ -480,25 +476,18 @@ a.gotoinstance{
.search-container{
position: relative;
}
-.search-container .close{
+.search-container .close {
position: absolute;
right: 10px;
- top: 32px;
+ top: 8px;
+}
+.search-container input {
+ font-weight: normal;
}
.groups-pane .search-container .close{
top: 32px;
}
-.views-urls-table .search-container .close{
- top: 7px;
- right: 10px;
- z-index: 10;
-}
-.views-list-table .search-container .close{
- right: 50px;
- top: 7px;
- z-index: 10;
-}
.groups-pane table thead th{
border-top: 0;
}
@@ -563,9 +552,7 @@ table.no-border tr td{
.no-border{
border: none !important;
}
-.top-margin-4{
- margin-top: 4px;
-}
+
.table > thead > tr > th.vertical-top{
vertical-align: top;
}
@@ -647,10 +634,14 @@ button.btn.btn-xs{
border-radius: 3px;
}
-a.btn-primary {
+a.btn-primary, a.btn-primary:focus {
color: #fff;
}
+a.btn-default, a.btn-default:focus {
+ color: #666;
+}
+
.clusterDisplayName {
display:inline-block;
width:90%;
@@ -686,6 +677,12 @@ a.alert-link, a.alert-link:hover, a.alert-link:visited{
color: #666;
}
+.empty-table-alert {
+ background-color: #f0f0f0;
+ text-align: center;
+ text-transform: uppercase;
+}
+
.alert-container {
position: fixed;
top: 50px;
@@ -1475,10 +1472,6 @@ legend {
text-overflow: ellipsis;
}
-.pull-right {
- float: right;
-}
-
body {
height: 100%;
background-color: #f0f0f0;
@@ -1498,3 +1491,7 @@ body {
background-color: #fff;
padding: 15px;
}
+
+.navigation-bar-fit-height {
+ z-index: 1001;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
new file mode 100644
index 0000000..9ab66f5
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
@@ -0,0 +1,49 @@
+/**
+ * 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.
+ */
+
+.view-instance-actions>a {
+ color: inherit;
+ font-size: 16px;
+ cursor: pointer;
+ padding: 0 5px;
+}
+
+td.view-instance-actions,
+th.view-instance-actions {
+ width: 10%;
+}
+
+.view-instance-actions>a:hover,
+.view-instance-actions>a:visited:hover,
+.view-instance-actions>a:focus:hover {
+ text-decoration: none;
+}
+
+#create-instance-form i {
+ cursor: pointer;
+}
+
+#create-instance-form button.active {
+ color: #333;
+ background-color: #e6e6e6;
+ border-color: #adadad;
+}
+
+input[type="checkbox"] + label {
+ line-height: 18px;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html
deleted file mode 100644
index 91b9a93..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listTable.html
+++ /dev/null
@@ -1,110 +0,0 @@
-<!--
-* 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="views-list-table">
- <div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li class="active">{{'common.views' | translate}}</li>
- <button ng-click="reloadViews()"
- class="btn btn-xs">
- <i class="glyphicon glyphicon-refresh"></i>
- </button>
- </ol>
- <div class="pull-right col-sm-4">
- <div class="input-group search-container">
- <input type="text" class="form-control search-input" placeholder="{{'common.search' | translate}}" ng-model="viewsFilter" ng-change="getFilteredViews()">
- <button type="button" class="close clear-search" ng-show="viewsFilter" ng-click="viewsFilter=''; getFilteredViews()"><span aria-hidden="true">×</span><span class="sr-only">{{"common.controls.close" | translate}}</span></button>
- <span class="input-group-addon">
- <span class="glyphicon glyphicon-search"></span>
- </span>
- </div>
- </div>
- </div>
- <hr>
- <div class="row">
- <div class="col-sm-3 padding-left-30"><h4>{{'views.viewName' | translate}}</h4></div>
- <div class="col-sm-3"><h4>{{'views.instances' | translate}}</h4></div>
- <div class="col-sm-6"><h4></h4></div>
- </div>
- <accordion close-others="false">
- <accordion-group ng-repeat="view in filteredViews" is-open="view.isOpened">
- <accordion-heading>
- <div class="row">
- <div class="col-sm-4">
- <i class="glyphicon glyphicon-chevron-right" ng-class="{'opened': view.isOpened}"></i>
- {{view.view_name}}
- </div>
- <div class="col-sm-3">
- <span ng-repeat="(version, vData) in view.versions">
- {{version}}
- <span ng-switch="vData.status">
- <span ng-switch-when="PENDING" class="viewstatus pending" ng-switch-when="true" tooltip="{{'views.pending' | translate}}"></span>
- <div class="viewstatus deploying" ng-switch-when="DEPLOYING" tooltip="{{'views.deploying' | translate}}">
- <div class="rect1"></div>
- <div class="rect2"></div>
- <div class="rect3"></div>
- </div>
- <span ng-switch-when="DEPLOYED">({{vData.count}})</span>
- <span ng-switch-when="ERROR" tooltip="{{'views.alerts.deployError' | translate}}"><i class="fa fa-exclamation-triangle"></i></span>
- </span>
- {{$last ? '' : ', '}}
- </span>
- </div>
- <div class="col-sm-6">{{view.description}}</div>
- </div>
- </accordion-heading>
- <table class="table instances-table">
- <tbody>
- <tr ng-repeat="instance in view.instances">
- <td class="col-sm-1"></td>
- <td class="col-sm-5">
- <a href="#/views/{{view.view_name}}/versions/{{instance.ViewInstanceInfo.version}}/instances/{{instance.ViewInstanceInfo.instance_name}}/edit" class="instance-link">{{instance.label}}</a>
- </td>
- <td class="col-sm-5">{{instance.ViewInstanceInfo.version}}</td>
- <td class="col-sm-5 " ><div class="description-column" tooltip="{{instance.ViewInstanceInfo.description}}">{{instance.ViewInstanceInfo.description || 'No description'}}</div>
- </td>
- <td class="col-sm-1">
- <a class="instance-link ng-scope ng-binding" href="#/views/{{view.view_name}}/versions/{{instance.ViewInstanceInfo.version}}/instances/{{instance.ViewInstanceInfo.instance_name}}/clone"><i class="fa fa-copy"></i></a>
- </td>
- <td class="col-sm-1">
- <a class="instance-link ng-scope ng-binding" href ng-click="deleteInstance(instance)"><i class="fa fa-trash-o"></i></a>
- </td>
- </tr>
- </tbody>
- <tfoot>
- <tr>
- <td class="col-sm-4"></td>
- <td class="col-sm-3 padding-left-30">
- <a tooltip="{{view.canCreateInstance ? '' : constants.unable}}" class="btn btn-default createisntance-btn {{view.canCreateInstance ? '' : 'disabled'}}" href ng-click="gotoCreate(view.view_name, view.canCreateInstance);"><span class="glyphicon glyphicon-plus"></span> {{'views.create' | translate}}</a>
- </td>
- <td class="col-sm-3"></td>
- <td class="col-sm-3">
- </td>
- </tr>
- </tfoot>
- </table>
- </accordion-group>
- <div ng-if="isLoadingViews" class="spinner-container">
- <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
- </div>
- <div class="alert alert-info" ng-show="views && !filteredViews.length && !isLoadingViews">
- {{'common.alerts.nothingToDisplay' | translate: '{term: constants.views}'}}
- </div>
-
- </accordion>
-</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listUrls.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listUrls.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listUrls.html
deleted file mode 100644
index 13ff311..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listUrls.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<!--
-* 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="views-urls-table" data-ng-init="initViewUrls()">
-
-
- <div class="clearfix">
- <ol class="breadcrumb pull-left">
- <li class="active">{{'common.viewUrls' | translate}}</li>
- </ol>
- <div class="pull-right top-margin-4">
- <div class="tooltip-wrapper" tooltip="{{(createUrlDisabled)? ('urls.noViewInstances' | translate) : ''}}">
- <link-to ng-disabled="createUrlDisabled" route="views.createViewUrl" class="btn btn-primary createuser-btn"><span class="glyphicon glyphicon-plus"></span> {{'urls.createNewUrl' | translate}}</link-to>
- </div>
- </div>
- </div>
- <hr>
- <table class="table table-striped table-hover">
- <thead>
- <tr class="fix-bottom">
-
- <th class="fix-bottom col-md-2">
- <span>{{'urls.name' | translate}}</span>
- </th>
- <th class="fix-bottom col-md-3">
- <span>{{'urls.url' | translate}}</span>
- </th>
- <th class="fix-bottom col-md-2">
- <span >{{'urls.view' | translate}}</span>
- </th>
- <th class="fix-bottom col-md-2">
- <span>{{'urls.viewInstance' | translate}}</span>
- </th>
- </tr>
-
- <tr>
-
- <th class="fix-top">
- <div class="search-container">
- <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="urlNameFilter" ng-change="resetPagination()">
- <button type="button" class="close clearfilter" ng-show="urlNameFilter" ng-click="urlNameFilter=''; resetPagination()"><span class="pull-right" aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
- </div>
- </th>
- <th class="fix-top">
- <div class="search-container">
- <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="urlSuffixfilter" ng-change="resetPagination()">
- <button type="button" class="close clearfilter" ng-show="urlSuffixfilter" ng-click="urlSuffixfilter=''; resetPagination()"><span class="pull-right" aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
- </div>
- </th>
- <th class="fix-top">
- <select class="form-control typefilter v-small-input"
- ng-model="instanceTypeFilter"
- ng-options="item.label for item in typeFilterOptions"
- ng-change="resetPagination()">
- </select>
- </th>
- <th class="fix-top">
- </th>
- </tr>
-
- </thead>
- <tbody>
- <tr ng-repeat="url in urls.items">
-
- <td>
- <a href="#/urls/edit/{{url.ViewUrlInfo.url_name}}">{{url.ViewUrlInfo.url_name}}</a>
- </td>
- <td>
- <a target="_blank" href="{{fromSiteRoot('/#/main/view/' + url.ViewUrlInfo.view_instance_common_name + '/' + url.ViewUrlInfo.url_suffix)}}">/main/view/{{url.ViewUrlInfo.view_instance_common_name}}/{{url.ViewUrlInfo.url_suffix}}
- <i class="fa fa-external-link" aria-hidden="true"></i></a>
-
- </td>
- <td>
- <span>{{url.ViewUrlInfo.view_instance_common_name}} {{"{"+url.ViewUrlInfo.view_instance_version+"}"}} </span>
- </td>
- <td>
- <span>{{url.ViewUrlInfo.view_instance_name}}</span>
- </td>
-
- </tr>
- </tbody>
- </table>
- <div ng-if="isLoadingUrls" class="spinner-container">
- <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
- </div>
- <div class="alert alert-info col-sm-12" ng-show="!urls.items.length && !isLoadingUrls">
- {{'urls.noUrlsToDisplay'| translate}}
- </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: urs.urls}'}}</span>
- <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
- </div>
- <div class="pull-right left-margin">
- <pagination class="paginator" total-items="totalUrls" max-size="maxVisiblePages" items-per-page="urlsPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
- </div>
- <div class="pull-right">
- <select class="form-control" ng-model="urlsPerPage" ng-change="urlsPerPageChanged()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
- </div>
- </div>
-
-</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/create.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/create.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/create.html
index c5410c1..48757d4 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/create.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/create.html
@@ -15,110 +15,160 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<form class="form-horizontal" role="form" name="form.instanceCreateForm" novalidate>
+<form role="form" id="create-instance-form" name="form.instanceCreateForm" novalidate>
<div class="modal-header">
<h3 class="modal-title">{{'views.createViewInstance' | translate}}</h3>
</div>
-<div class="modal-body createViewModal">
- <div class="view-header">
- <img src="http://placehold.it/64x64" alt="" class="icon-big">
- <img src="http://placehold.it/32x32" alt="" class="icon-small">
- <div class="description">
- <h3>{{view.ViewVersionInfo.view_name}}</h3>
- <span>{{view.ViewVersionInfo.label}} | Version: {{view.ViewVersionInfo.version}}</span>
+<div class="modal-body" ng-hide="isLoading">
+
+ <div class="row">
+
+ <div class="form-group col-sm-6" ng-class="{ 'has-error': form.instanceCreateForm.view.$error.required && form.instanceCreateForm.submitted }">
+ <label for="view">
+ {{'views.createInstance.selectView' | translate}}<span>*</span>
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <select
+ class="form-control"
+ id="view"
+ name="view"
+ ng-model="formData.view"
+ ng-change="updateVersionOptions()"
+ ng-options="item.label for item in viewOptions"
+ required>
+ </select>
+ <span class="help-block validation-block" ng-show='form.instanceCreateForm.view.$error.required && form.instanceCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ </div>
+
+ <div class="form-group col-sm-6" ng-class="{ 'has-error': form.instanceCreateForm.version.$error.required && form.instanceCreateForm.submitted }">
+ <label for="version">
+ {{'views.createInstance.selectVersion' | translate}}<span>*</span>
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <select
+ class="form-control"
+ id="version"
+ name="version"
+ ng-model="formData.version"
+ ng-options="item.label for item in versionOptions">
+ </select>
+ <span class="help-block validation-block" ng-show='form.instanceCreateForm.version.$error.required && form.instanceCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
</div>
</div>
-
- <div class="panel panel-default">
- <div class="panel-heading">
- <h3 class="panel-title">{{'common.details' | translate}}</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-labe col-sm-2">{{'views.instanceName' | translate}}</label>
- <div class="col-sm-10">
- <input type="text" class="form-control" name="instanceNameInput" ng-pattern="nameValidationPattern" required ng-model="instance.instance_name">
- <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm.instanceNameInput.$error.required && form.instanceCreateForm.submitted'>
- {{'common.alerts.fieldRequired' | translate}}
- </div>
- <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm.instanceNameInput.$error.pattern && form.instanceCreateForm.submitted'>
- {{'common.alerts.noSpecialChars' | translate}}
- </div>
- <div class="alert alert-danger no-margin-bottom top-margin" ng-show='instanceExists'>
- {{'views.alerts.instanceExists' | translate}}
- </div>
- </div>
- </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-labe col-sm-2">{{'common.displayLabel' | translate}}</label>
- <div class="col-sm-10">
- <input type="text" class="form-control" name="displayLabel" ng-model="instance.label" required ng-pattern="nameValidationPattern">
+ <div class="h4">{{'common.details' | translate}}</div>
+ <div class="form-group"
+ ng-class="{ 'has-error': (form.instanceCreateForm.instanceName.$error.required || form.instanceCreateForm.instanceName.$error.pattern || isInstanceExists) && form.instanceCreateForm.submitted }">
+ <label for="instanceName">
+ {{'views.instanceName' | translate}}<span>*</span>
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <input type="text" class="form-control"
+ ng-model="formData.instanceName"
+ name="instanceName"
+ id="instanceName"
+ ng-change="checkIfInstanceExist()"
+ ng-pattern="nameValidationPattern" required>
+ <span class="help-block validation-block"
+ ng-show='form.instanceCreateForm.instanceName.$error.required && form.instanceCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ <span class="help-block validation-block"
+ ng-show='form.instanceCreateForm.instanceName.$error.pattern && form.instanceCreateForm.submitted'>
+ {{'common.alerts.noSpecialChars' | translate}}
+ </span>
+ <span class="help-block validation-block"
+ ng-show='isInstanceExists && form.instanceCreateForm.submitted'>
+ {{'views.alerts.instanceExists' | translate}}
+ </span>
+ </div>
- <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm.displayLabel.$error.required && form.instanceCreateForm.submitted'>
- {{'common.alerts.fieldRequired' | translate}}
- </div>
- <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm.displayLabel.$error.pattern && form.instanceCreateForm.submitted'>
- {{'common.alerts.noSpecialChars' | translate}}
- </div>
- </div>
- </div>
- </div>
- <div class="form-group">
- <div class="col-sm-10 col-sm-offset-2">
- <button class="btn btn-default" ng-click="isAdvancedClosed = !isAdvancedClosed">{{'views.advanced' | translate}}</button>
- </div>
- </div>
- <div collapse="isAdvancedClosed">
- <div class="form-group">
- <div class="col-sm-10 col-sm-offset-2">
- <div class="checkbox">
- <label>
- <input type="checkbox" ng-model='instance.visible'> {{'views.visible' | translate}}
- </label>
- </div>
- </div>
- </div>
- <div class="form-group">
- <div class="col-sm-10 col-sm-offset-2">
- <label for="" class="control-label col-sm-2">{{'views.icon' | translate}}</label>
- <div class="col-sm-10">
- <input type="text" class="form-control" name="iconUrl" ng-model="instance.icon_path">
- </div>
- </div>
- </div>
- <div class="form-group">
- <div class="col-sm-10 col-sm-offset-2">
- <label for="" class="control-label col-sm-2">{{'views.icon64' | translate}}</label>
- <div class="col-sm-10">
- <input type="text" class="form-control" name="icon64Url" ng-model="instance.icon64_path">
- </div>
- </div>
- </div>
- </div>
- </div>
+ <div class="form-group" ng-class="{ 'has-error': form.instanceCreateForm.displayName.$error.required && form.instanceCreateForm.submitted }">
+ <label for="displayName">
+ {{'views.displayName' | translate}}<span>*</span>
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <input type="text" class="form-control" required
+ name="displayName"
+ ng-model="formData.displayName"
+ id="displayName">
+ <span class="help-block validation-block" ng-show='form.instanceCreateForm.displayName.$error.required && form.instanceCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ </div>
- <div class="panel panel-default">
- <div class="panel-heading">
- <h3 class="panel-title">{{'views.configuration' | translate}}</h3>
- </div>
- <div class="panel-body">
- <div class="form-group" ng-repeat="parameter in instance.properties"
- ng-class="{'has-error' : (form.instanceCreateForm[parameter.name].$error.required && form.instanceCreateForm.submitted)}" >
- <label for="" class="col-sm-3 control-label">{{parameter.description}}</label>
- <div class="col-sm-9">
- <input type="text" class="form-control" name="{{parameter.name}}" ng-required="parameter.required" ng-model="parameter.value">
- <div class="alert alert-danger no-margin-bottom top-margin" ng-show='form.instanceCreateForm[parameter.name].$error.required && form.instanceCreateForm.submitted'>
- {{'common.alerts.fieldRequired' | translate}}
- </div>
- </div>
- </div>
+ <div class="form-group" ng-class="{ 'has-error': form.instanceCreateForm.description.$error.required && form.instanceCreateForm.submitted }">
+ <label for="description">
+ {{'views.description' | translate}}<span>*</span>
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <input type="text" class="form-control" required
+ name="description"
+ ng-model="formData.description"
+ id="description">
+ <span class="help-block validation-block" ng-show='form.instanceCreateForm.description.$error.required && form.instanceCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ </div>
+
+ <div class="form-group checkbox">
+ <input type="checkbox" class="form-control"
+ name="visible"
+ ng-model="formData.visible"
+ id="visible">
+ <label for="visible">
+ {{'views.visible' | translate}}
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ </div>
+
+ <div class="h4">{{'views.clusterConfiguration' | translate}}</div>
+ <div class="form-group">
+ <label for="clusterType">
+ {{'views.createInstance.clusterType' | translate}}?
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <div>
+ <div class="btn-group" role="group" id="clusterType">
+ <button type="button" class="btn btn-default"
+ ng-class="isLocalTypeChosen && 'active'"
+ ng-click="switchClusterType(true)">
+ {{'common.local' | translate}}
+ </button>
+ <button type="button" class="btn btn-default"
+ ng-class="!isLocalTypeChosen && 'active'"
+ ng-click="switchClusterType(false)">
+ {{'common.remote' | translate}}
+ </button>
</div>
</div>
-
+ </div>
+ <div class="row">
+ <div class="form-group col-sm-6" ng-class="{ 'has-error': form.instanceCreateForm.clusterName.$error.required && form.instanceCreateForm.submitted }">
+ <label for="clusterName">
+ {{'views.clusterName' | translate}}<span>*</span>
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </label>
+ <select
+ required
+ name="clusterName"
+ ng-options="item.label for item in clusterOptions"
+ class="form-control"
+ ng-model="formData.clusterName"
+ id="clusterName">
+ </select>
+ <span class="help-block validation-block" ng-show='form.instanceCreateForm.clusterName.$error.required && form.instanceCreateForm.submitted'>
+ {{'common.alerts.fieldRequired' | translate}}
+ </span>
+ </div>
+ </div>
+</div>
+<div ng-if="isLoading" class="spinner-container">
+ <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
</div>
<div class="modal-footer">
<button class="btn btn-default" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button>
http://git-wip-us.apache.org/repos/asf/ambari/blob/dd0421a2/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/edit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/edit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/edit.html
deleted file mode 100644
index aab526e..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/edit.html
+++ /dev/null
@@ -1,138 +0,0 @@
-<!--
-* 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">{{'views.edit' | translate}} {{instance.ViewInstanceInfo.view_name}}: {{instance.ViewInstanceInfo.label}}</h3>
-</div>
-<div class="modal-body">
- <div class="panel panel-default">
- <div class="panel-heading clearfix">
- <h3 class="panel-title pull-left">{{'views.settings' | translate}}</h3>
- <div class="pull-right">
- <a href ng-click="edit.editSettingsDisabled = !edit.editSettingsDisabled" ng-show="edit.editSettingsDisabled"> <span class="glyphicon glyphicon-cog"></span> {{'views.edit' | translate}}</a>
- </div>
- </div>
- <div class="panel-body">
- <form class="form-horizontal">
- <fieldset ng-disabled="edit.editSettingsDisabled">
- <div class="form-group">
- <label for="" class="col-sm-2 control-label">{{'views.instanceId' | translate}}</label>
- <label for="" class="col-sm-10 control-label text-left">{{instance.ViewInstanceInfo.instance_name}}</label>
- </div>
- <div class="form-group">
- <label for="" class="col-sm-2 control-label">{{'views.displayName' | translate}}</label>
- <div class="col-sm-10"><input type="text" class="form-control" placeholder="{{'views.displayName' | translate}}" ng-model="settings.label"></div>
- </div>
- <div class="form-group">
- <div class="col-sm-offset-2 col-sm-10">
- <div class="checkbox">
- <label>
- <input type="checkbox" ng-model="settings.visible"> {{'views.visible' | translate}}
- </label>
- </div>
- </div>
- </div>
- <div class="form-group" ng-hide="edit.editSettingsDisabled">
- <div class="col-sm-offset-2 col-sm-10">
- <button class="btn btn-default pull-right left-margin" ng-click="cancelSettings()">{{'common.controls.cancel' | translate}}</button>
- <button class="btn btn-primary pull-right" ng-click="saveSettings()">{{'common.controls.save' | translate}}</button>
- </div>
- </div>
- </fieldset>
- </form>
- </div>
- </div>
-
- <div class="panel panel-default views-permissions-panel" style="">
- <div class="panel-heading clearfix">
- <h3 class="panel-title pull-left">{{'views.permissions' | translate}}</h3>
- <div class="pull-right">
- <a href ng-click="edit.editPermissionDisabled = !edit.editPermissionDisabled" ng-show="edit.editPermissionDisabled"> <span class="glyphicon glyphicon-cog"></span> {{'views.edit' | translate}}</a>
- </div>
- </div>
- <div class="panel-body">
- <form class="form-horizontal">
- <div class="form-group">
- <div class="col-sm-2"></div>
- <label class="col-sm-5 control-label text-left">{{'common.users' | translate}}</label>
- <label class="col-sm-5 control-label text-left">{{'common.groups' | translate}}</label>
- </div>
- <div class="form-group" ng-repeat="permission in permissions">
- <label class="col-sm-2 control-label">{{permission.PermissionInfo.permission_name}}</label>
- <div class="col-sm-5" ng-switch="edit.editPermissionDisabled">
- <textarea name="" id="" cols="30" rows="4" class="form-control" ng-model="permissionsEdit[permission.PermissionInfo.permission_name].USER" ng-switch-when="false"></textarea>
- <div class="well" ng-switch-when="true">
- <span ng-repeat="user in permission.USER">
- <link-to route="users.show" id="{{user}}">{{user}}</link-to>
- <button type="button" class="close remove-button"
- ng-click="removePermission(permission.name, 'USER', user)"><span aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
- {{$last ? '' :', '}}
- </span>
- </div>
- </div>
- <div class="col-sm-5" ng-switch="edit.editPermissionDisabled">
- <textarea name="" id="" cols="30" rows="4" class="form-control" ng-model="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" ng-switch-when="false"></textarea>
- <div class="well" ng-switch-when="true">
- <span ng-repeat="group in permission.GROUP">
- <link-to route="groups.edit" id="{{group}}" >{{group}}</link-to>
- <button type="button" class="close remove-button"
- ng-click="removePermission(permission.name, 'GROUP', group)"><span aria-hidden="true">×</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
- {{$last ? '' :', '}}
- </span>
- </div>
- </div>
- </div>
- <div class="form-group" ng-hide="edit.editPermissionDisabled">
- <div class="col-sm-offset-2 col-sm-10">
- <button class="btn btn-default pull-right left-margin" ng-click="cancelPermissions()">{{'common.controls.cancel' | translate}}</button>
- <button class="btn btn-primary pull-right" ng-click="savePermissions()">{{'common.controls.save' | translate}}</button>
- </div>
- </div>
- </form>
-
- </div>
- </div>
-
- <div class="panel panel-default">
- <div class="panel-heading clearfix">
- <h3 class="panel-title pull-left">{{'views.configuration' | translate}}</h3>
- <div class="pull-right">
- <a href ng-click="edit.editConfigurationDisabled = !edit.editConfigurationDisabled" ng-show="edit.editConfigurationDisabled"> <span class="glyphicon glyphicon-cog"></span> {{'views.edit' | translate}}</a>
- </div>
- </div>
- <div class="panel-body">
- <form action="" class="form-horizontal">
- <fieldset ng-disabled="edit.editConfigurationDisabled">
- <div class="form-group" ng-repeat="(propertyName, propertyValue) in configuration">
- <label for="" class="control-label col-sm-3">{{propertyName}}</label>
- <div class="col-sm-9"><input type="text" class="form-control" ng-model="configuration[propertyName]"></div>
- </div>
- <div class="form-group" ng-hide="edit.editConfigurationDisabled">
- <div class="col-sm-offset-2 col-sm-10">
- <button class="btn btn-default pull-right left-margin" ng-click="cancelConfiguration()">{{'common.controls.cancel' | translate}}</button>
- <button class="btn btn-primary pull-right" ng-click="saveConfiguration()">{{'common.controls.save' | translate}}</button>
- </div>
- </div>
- </fieldset>
- </form>
- </div>
- </div>
-</div>
-<div class="modal-footer">
- <button class="btn btn-default" ng-click="close()">{{'common.controls.save' | translate}}</button>
-</div>