You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by db...@apache.org on 2016/04/26 09:03:45 UTC
[2/2] ambari git commit: AMBARI-15821 Ability to provide logical urls
to view instances,
Added URL wizard and other UI fixes(Ashwin Rajeev via dipayanb)
AMBARI-15821 Ability to provide logical urls to view instances, Added URL wizard and other UI fixes(Ashwin Rajeev via dipayanb)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f62a9277
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f62a9277
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f62a9277
Branch: refs/heads/trunk
Commit: f62a927708bddb5f1dffe7342131cb307a550eee
Parents: 614b12f
Author: Dipayan Bhowmick <di...@gmail.com>
Authored: Tue Apr 26 12:33:26 2016 +0530
Committer: Dipayan Bhowmick <di...@gmail.com>
Committed: Tue Apr 26 12:33:26 2016 +0530
----------------------------------------------------------------------
.../main/resources/ui/admin-web/app/index.html | 5 +-
.../ambariViews/CreateViewInstanceCtrl.js | 5 +
.../controllers/ambariViews/ViewUrlCtrl.js | 153 ++++++++
.../controllers/ambariViews/ViewUrlEditCtrl.js | 94 +++++
.../controllers/ambariViews/ViewsEditCtrl.js | 3 +-
.../controllers/ambariViews/ViewsListCtrl.js | 14 +-
.../ui/admin-web/app/scripts/i18n.config.js | 26 +-
.../ui/admin-web/app/scripts/routes.js | 20 ++
.../ui/admin-web/app/scripts/services/View.js | 136 ++++++-
.../resources/ui/admin-web/app/styles/main.css | 23 +-
.../admin-web/app/views/ambariViews/create.html | 8 -
.../admin-web/app/views/ambariViews/edit.html | 9 +-
.../app/views/ambariViews/listTable.html | 130 +++----
.../app/views/ambariViews/listUrls.html | 72 ++++
.../ui/admin-web/app/views/leftNavbar.html | 18 +-
.../ui/admin-web/app/views/urls/create.html | 51 +++
.../admin-web/app/views/urls/create_step_1.html | 36 ++
.../admin-web/app/views/urls/create_step_2.html | 44 +++
.../admin-web/app/views/urls/create_step_3.html | 60 ++++
.../ui/admin-web/app/views/urls/edit.html | 73 ++++
.../resources/ResourceInstanceFactoryImpl.java | 4 +
.../resources/ViewUrlResourceDefinition.java | 54 +++
.../server/api/services/ViewUrlsService.java | 144 ++++++++
.../internal/DefaultProviderModule.java | 2 +
.../internal/ViewInstanceResourceProvider.java | 23 +-
.../internal/ViewURLResourceProvider.java | 358 +++++++++++++++++++
.../ambari/server/controller/spi/Resource.java | 2 +
.../ambari/server/orm/dao/ViewURLDAO.java | 111 ++++++
.../server/orm/entities/ViewInstanceEntity.java | 45 ++-
.../server/orm/entities/ViewURLEntity.java | 144 ++++++++
.../server/upgrade/UpgradeCatalog240.java | 19 +-
.../apache/ambari/server/view/ViewRegistry.java | 21 +-
.../view/configuration/InstanceConfig.java | 15 -
.../main/resources/Ambari-DDL-Derby-CREATE.sql | 13 +-
.../main/resources/Ambari-DDL-MySQL-CREATE.sql | 12 +-
.../main/resources/Ambari-DDL-Oracle-CREATE.sql | 12 +-
.../resources/Ambari-DDL-Postgres-CREATE.sql | 14 +-
.../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql | 13 +-
.../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 12 +-
.../resources/Ambari-DDL-SQLServer-CREATE.sql | 13 +-
.../src/main/resources/META-INF/persistence.xml | 19 +-
.../ViewInstanceResourceProviderTest.java | 49 ---
.../server/upgrade/UpgradeCatalog240Test.java | 15 +-
.../ambari/view/ViewInstanceDefinition.java | 5 -
44 files changed, 1853 insertions(+), 246 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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 fa911a6..8d7e8e7 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
@@ -90,7 +90,7 @@
</div>
</div>
-
+
<!-- build:js scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
@@ -119,6 +119,7 @@
<script src="bower_components/bootstrap/js/scrollspy.js"></script>
<script src="bower_components/bootstrap/js/collapse.js"></script>
<script src="bower_components/bootstrap/js/tab.js"></script>
+
<!-- endbuild -->
<!-- build:js scripts/main.js -->
@@ -139,6 +140,8 @@
<script src="scripts/controllers/groups/GroupsEditCtrl.js"></script>
<script src="scripts/controllers/ambariViews/ViewsListCtrl.js"></script>
<script src="scripts/controllers/ambariViews/ViewsEditCtrl.js"></script>
+ <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/clusters/ClustersManageAccessCtrl.js"></script>
<script src="scripts/controllers/clusters/UserAccessListCtrl.js"></script>
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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 962b795..127bc74 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
@@ -198,4 +198,9 @@ angular.module('ambariAdminConsole')
}
});
+
+
+
+
+
}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewUrlCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewUrlCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewUrlCtrl.js
new file mode 100644
index 0000000..0cf8d03
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewUrlCtrl.js
@@ -0,0 +1,153 @@
+/**
+ * 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('ViewUrlCtrl',['$scope', 'View', 'Alert', 'Cluster', '$routeParams', '$location', 'UnsavedDialog', '$translate', function($scope, View, Alert, Cluster, $routeParams, $location, UnsavedDialog, $translate) {
+ var $t = $translate.instant;
+ $scope.form = {};
+ $scope.constants = {
+ props: $t('views.properties')
+ };
+ var targetUrl = '/viewUrls';
+ $scope.url={};
+ $scope.formHolder = {};
+
+ View.getAllVisibleInstance().then(function(views) {
+ var names = [];
+ var instances=[];
+ views.map(function(view){
+ var nameVersion = view.view_name+" {"+view.version+"}";
+ names.push(nameVersion);
+ instances.push({nameV:nameVersion,instance:view.instance_name,cname:view.view_name,version:view.version});
+ });
+
+ var output = [],
+ keys = [];
+
+ angular.forEach(names, function(item) {
+ var key = item;
+ if(keys.indexOf(key) === -1) {
+ keys.push(key);
+ output.push(item);
+ }
+ });
+
+ $scope.viewsVersions = output;
+ $scope.viewInstances = instances;
+
+ if($routeParams.viewName && $routeParams.viewVersion && $routeParams.viewInstanceName){
+ var selectedView = $routeParams.viewName+" {"+$routeParams.viewVersion+"}";
+ $scope.url.selectedView = selectedView;
+ $scope.url.selectedInstance = instances.find(function(inst){
+ return inst.nameV === selectedView && inst.instance === $routeParams.viewInstanceName && inst.version === $routeParams.viewVersion && inst.cname === $routeParams.viewName;
+ });
+ }
+
+ }).catch(function(data) {
+ Alert.error($t('views.alerts.cannotLoadViews'), data.data.message);
+ });
+
+ $scope.filterByName = function(nameV){
+ return function (item) {
+ if (item.nameV === nameV)
+ {
+ return true;
+ }
+ return false;
+ };
+ };
+
+ $scope.chomp = function(viewNameVersion){
+ return viewNameVersion.substr(0,viewNameVersion.indexOf("{")).trim();
+ };
+
+
+ $scope.wizardController = function () {
+ var wizard = this;
+
+ //Model
+ wizard.currentStep = 1;
+ wizard.steps = [
+ {
+ step: 1,
+ name: $t('urls.step1'),
+ template: "views/urls/create_step_1.html"
+ },
+ {
+ step: 2,
+ name: $t('urls.step2'),
+ template: "views/urls/create_step_2.html"
+ },
+ {
+ step: 3,
+ name: $t('urls.step3'),
+ template: "views/urls/create_step_3.html"
+ }
+ ];
+ wizard.user = {};
+
+ //Functions
+ wizard.gotoStep = function(newStep) {
+ $scope.formHolder.form.submitted = true;
+ if (newStep < wizard.currentStep || $scope.formHolder.form.$valid) {
+ wizard.currentStep = newStep;
+ }
+ };
+
+ wizard.getStepTemplate = function(){
+ for (var i = 0; i < wizard.steps.length; i++) {
+ if (wizard.currentStep == wizard.steps[i].step) {
+ return wizard.steps[i].template;
+ }
+ }
+ };
+
+ wizard.save = function() {
+ $scope.formHolder.form.submitted = true;
+
+ if($scope.formHolder.form.$valid){
+
+ var payload = {ViewUrlInfo:{
+ url_name:$scope.url.urlName,
+ url_suffix:$scope.url.suffix,
+ view_instance_version:$scope.url.selectedInstance.version,
+ view_instance_name:$scope.url.selectedInstance.instance,
+ view_instance_common_name:$scope.url.selectedInstance.cname
+ }};
+
+ View.updateShortUrl(payload).then(function(urlStatus) {
+ Alert.success($t('urls.urlCreated', {
+ viewName:$scope.url.selectedInstance.cname ,
+ shortUrl:$scope.url.suffix,
+ urlName:$scope.url.urlName
+ }));
+ $scope.formHolder.form.$setPristine();
+ $location.path(targetUrl);
+ }).catch(function(data) {
+ Alert.error($t('views.alerts.cannotLoadViewUrls'), data.message);
+ });
+
+ }
+ };
+ }
+
+
+
+
+}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewUrlEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewUrlEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewUrlEditCtrl.js
new file mode 100644
index 0000000..93edc69
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewUrlEditCtrl.js
@@ -0,0 +1,94 @@
+/**
+ * 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('ViewUrlEditCtrl',['$scope', 'View', 'Alert', 'Cluster', '$routeParams', '$location', 'UnsavedDialog', '$translate','ConfirmationModal' ,function($scope, View, Alert, Cluster, $routeParams, $location, UnsavedDialog, $translate,ConfirmationModal) {
+ var $t = $translate.instant;
+ $scope.form = {};
+ $scope.constants = {
+ props: $t('views.properties')
+ };
+ var targetUrl = '/viewUrls';
+
+
+ function setUpEdit(){
+
+ View.getUrlInfo($routeParams.urlName).then(function(url) {
+ $scope.url = url.ViewUrlInfo;
+ $scope.nameVersion = url.ViewUrlInfo.view_instance_common_name +" {" + url.ViewUrlInfo.view_instance_version +"}"
+ }).catch(function(data) {
+ Alert.error($t('views.alerts.cannotLoadViewUrl'), data.data.message);
+ });
+ }
+
+ setUpEdit();
+
+
+ $scope.updateUrl = function() {
+ $scope.url_form.submitted = true;
+
+ if($scope.url_form.$valid){
+
+ var payload = {ViewUrlInfo:{
+ url_name:$scope.url.url_name,
+ url_suffix:$scope.url.url_suffix,
+ view_instance_version:'',
+ view_instance_name:'',
+ view_instance_common_name:''
+ }};
+
+ View.editShortUrl(payload).then(function(urlStatus) {
+ Alert.success($t('urls.urlUpdated', {
+ viewName:$scope.url.view_instance_common_name ,
+ shortUrl:$scope.url.suffix,
+ urlName:$scope.url.url_name
+ }));
+ $scope.url_form.$setPristine();
+ $location.path(targetUrl);
+ }).catch(function(data) {
+ Alert.error($t('views.alerts.cannotLoadViewUrls'), data.data.message);
+ });
+
+ }
+ };
+
+
+ $scope.deleteUrl = function() {
+
+ ConfirmationModal.show(
+ $t('common.delete', {
+ term: $t('urls.url')
+ }),
+ $t('common.deleteConfirmation', {
+ instanceType: $t('urls.url').toLowerCase(),
+ instanceName: '"' + $scope.url.url_name + '"'
+ })
+ ).then(function() {
+ View.deleteUrl($scope.url.url_name).then(function() {
+ $location.path(targetUrl);
+ });
+ });
+
+
+
+ };
+
+
+
+}]);
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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 d46a30f..877e230 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
@@ -244,8 +244,7 @@ angular.module('ambariAdminConsole')
'ViewInstanceInfo':{
'visible': $scope.settings.visible,
'label': $scope.settings.label,
- 'description': $scope.settings.description,
- 'short_url': $scope.settings.shortUrl
+ 'description': $scope.settings.description
}
};
return View.updateInstance($routeParams.viewId, $routeParams.version, $routeParams.instanceId, data)
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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 6d1dc52..ed389e1 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,7 +18,7 @@
'use strict';
angular.module('ambariAdminConsole')
-.controller('ViewsListCtrl',['$scope', 'View', '$modal', 'Alert', 'ConfirmationModal', '$location', '$translate', function($scope, View, $modal, Alert, ConfirmationModal, $location, $translate) {
+.controller('ViewsListCtrl',['$scope', 'View','$modal', 'Alert', 'ConfirmationModal', '$location', '$translate', function($scope, View, $modal, Alert, ConfirmationModal, $location, $translate) {
var deferredList = [],
$t = $translate.instant;
$scope.constants = {
@@ -128,6 +128,18 @@ angular.module('ambariAdminConsole')
$scope.reloadViews = function () {
loadViews();
+ };
+
+
+ $scope.listViewUrls = function(){
+ View.allUrls().then(function(urls) {
+ $scope.urls = urls;
+ $scope.ViewNameFilterOptions = urls.items.map(function(url){
+ return url.ViewUrlInfo.view_instance_common_name;
+ });
+ }).catch(function(data) {
+ Alert.error($t('views.alerts.cannotLoadViewUrls'), data.data.message);
+ });
}
}]);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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 68a4bec..3e475d9 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,6 +32,7 @@ angular.module('ambariAdminConsole')
'signOut': 'Sign out',
'clusters': 'Clusters',
'views': 'Views',
+ 'viewUrls': 'View URL\'s',
'roles': 'Roles',
'users': 'Users',
'groups': 'Groups',
@@ -132,7 +133,9 @@ angular.module('ambariAdminConsole')
'cannotLoadClusterStatus': 'Cannot load cluster status',
'clusterRenamed': 'The cluster has been renamed to {{clusterName}}.',
'cannotRenameCluster': 'Cannot rename cluster to {{clusterName}}',
- 'unsavedChanges': 'You have unsaved changes. Save changes or discard?'
+ 'tooShort': 'URL is too short',
+ 'tooLong': 'URL is too long',
+ 'onlyText': 'You can add only text urls in the lower case'
}
},
@@ -202,6 +205,8 @@ angular.module('ambariAdminConsole')
'pending': 'Pending...',
'deploying': 'Deploying...',
'properties': 'properties',
+ 'urlCreate':'Create new URL',
+ 'urlDelete':'Delete URL',
'alerts': {
'noSpecialChars': 'Must not contain any special characters.',
@@ -222,10 +227,27 @@ angular.module('ambariAdminConsole')
'cannotSaveSettings': 'Cannot save settings',
'cannotSaveProperties': 'Cannot save properties',
'cannotDeleteInstance': 'Cannot delete instance',
- 'cannotLoadViews': 'Cannot load views'
+ 'cannotLoadViews': 'Cannot load views',
+ 'cannotLoadViewUrls': 'Cannot load view URL\'s',
+ 'cannotLoadViewUrl': 'Cannot load view URL'
}
},
+ 'urls':{
+ 'name':'Name',
+ 'url':'URL',
+ 'create':'Create',
+ 'edit':'Edit',
+ 'view':'View',
+ 'viewInstance':'Instance',
+ 'step1':'Create URL',
+ 'step2':'Select instance',
+ 'step3':'Assign URL',
+ 'noUrlsToDisplay':'No short URL\'s configured',
+ 'urlCreated':'Created short URL <a href="/#/main/view/{{viewName}}/{{shortUrl}}">{{urlName}}</a>',
+ 'urlUpdated':'Updated short URL <a href="/#/main/view/{{viewName}}/{{shortUrl}}">{{urlName}}</a>'
+ },
+
'clusters': {
'switchToList': 'Switch to list view',
'switchToBlock': 'Switch to block view',
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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 4fc4ea6..0566969 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
@@ -88,6 +88,26 @@ angular.module('ambariAdminConsole')
templateUrl: 'views/ambariViews/listTable.html',
controller: 'ViewsListCtrl'
},
+ listViewUrls: {
+ url: '/viewUrls',
+ templateUrl: 'views/ambariViews/listUrls.html',
+ controller: 'ViewsListCtrl'
+ },
+ createViewUrl:{
+ url: '/urls/new',
+ templateUrl: 'views/urls/create.html',
+ controller: 'ViewUrlCtrl'
+ },
+ linkViewUrl:{
+ url: '/urls/link/:viewName/:viewVersion/:viewInstanceName',
+ templateUrl: 'views/urls/create.html',
+ controller: 'ViewUrlCtrl'
+ },
+ editViewUrl:{
+ url: '/urls/edit/:urlName',
+ templateUrl: 'views/urls/edit.html',
+ controller: 'ViewUrlEditCtrl'
+ },
edit: {
url: '/views/:viewId/versions/:version/instances/:instanceId/edit',
templateUrl: 'views/ambariViews/edit.html',
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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 cbe11e4..36bd32d 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
@@ -24,6 +24,8 @@ angular.module('ambariAdminConsole')
angular.extend(this, item);
}
+
+
ViewInstance.find = function(viewName, version, instanceName) {
var deferred = $q.defer();
var fields = [
@@ -51,6 +53,114 @@ angular.module('ambariAdminConsole')
};
+ function ViewUrl(item) {
+ angular.extend(this, item);
+ }
+
+ function URLStatus(item){
+ angular.element(this,item);
+ }
+
+ ViewUrl.all = function() {
+ var deferred = $q.defer();
+
+ $http({
+ method: 'GET',
+ dataType: "json",
+ url: Settings.baseUrl + '/view/urls',
+
+ })
+ .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();
+
+ $http({
+ method: 'POST',
+ dataType: "json",
+ url: Settings.baseUrl + '/view/urls/'+payload.ViewUrlInfo.url_name,
+ data:payload
+ })
+ .success(function(data) {
+ deferred.resolve(new URLStatus(data));
+ })
+ .error(function(data) {
+ deferred.reject(data);
+ });
+
+ return deferred.promise;
+ };
+
+ ViewUrl.deleteUrl = function(urlName){
+ var deferred = $q.defer();
+
+ $http({
+ method: 'DELETE',
+ dataType: "json",
+ url: Settings.baseUrl + '/view/urls/'+ urlName,
+ })
+ .success(function(data) {
+ deferred.resolve(new URLStatus(data));
+ })
+ .error(function(data) {
+ deferred.reject(data);
+ });
+
+ return deferred.promise;
+ };
+
+
+ ViewUrl.editShortUrl = function(payload){
+ var deferred = $q.defer();
+
+ $http({
+ method: 'PUT',
+ dataType: "json",
+ url: Settings.baseUrl + '/view/urls/'+payload.ViewUrlInfo.url_name,
+ data:payload
+ })
+ .success(function(data) {
+ deferred.resolve(new URLStatus(data));
+ })
+ .error(function(data) {
+ deferred.reject(data);
+ });
+
+ return deferred.promise;
+ };
+
+
+ ViewUrl.urlInfo = function(urlName){
+
+ var deferred = $q.defer();
+
+ $http({
+ method: 'GET',
+ dataType: "json",
+ url: Settings.baseUrl + '/view/urls/'+urlName,
+
+ })
+ .success(function(data) {
+ deferred.resolve(new ViewUrl(data));
+ })
+ .error(function(data) {
+ deferred.reject(data);
+ });
+
+ return deferred.promise;
+ };
+
+
+
function View(item){
var self = this;
self.view_name = item.ViewInfo.view_name;
@@ -79,6 +189,27 @@ angular.module('ambariAdminConsole')
return ViewInstance.find(viewName, version, instanceName);
};
+ View.allUrls = function(){
+ return ViewUrl.all()
+ };
+
+ View.getUrlInfo = function(urlName){
+ return ViewUrl.urlInfo(urlName);
+ };
+
+ View.deleteUrl = function(urlName){
+ return ViewUrl.deleteUrl(urlName);
+ };
+
+
+ View.updateShortUrl = function(payload){
+ return ViewUrl.updateShortUrl(payload);
+ };
+
+ View.editShortUrl = function(payload){
+ return ViewUrl.editShortUrl(payload);
+ };
+
View.deleteInstance = function(viewName, version, instanceName) {
return $http.delete(Settings.baseUrl +'/views/'+viewName+'/versions/'+version+'/instances/'+instanceName, {
headers: {
@@ -168,8 +299,7 @@ angular.module('ambariAdminConsole')
visible: instanceInfo.visible,
icon_path: instanceInfo.icon_path,
icon64_path: instanceInfo.icon64_path,
- description: instanceInfo.description,
- short_url:instanceInfo.shortUrl
+ description: instanceInfo.description
};
angular.forEach(instanceInfo.properties, function(property) {
@@ -308,7 +438,7 @@ angular.module('ambariAdminConsole')
url: Settings.baseUrl + '/views',
params:{
'fields': fields.join(','),
- 'versions/ViewVersionInfo/system': false
+ 'versions/ViewVersionInfo/system' : false
}
}).success(function(data) {
var views = [];
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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 edf8524..b55d89c 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
@@ -97,7 +97,7 @@
-webkit-transform: rotateX(0deg);
-ms-transform: rotateX(0deg);
-o-transform: rotateX(0deg);
- transform: rotateX(0deg);
+ transform: rotateX(0deg);
}
.editable-list-container .actions-panel.ng-hide{
-webkit-transform: rotateX(90deg);
@@ -215,6 +215,10 @@
display: inline-block;
}
+ .small-input{
+ max-width: 300px;
+ }
+
.paginator{
margin: 0;
}
@@ -471,7 +475,7 @@ a.gotoinstance{
display: block;
float: left;
text-decoration: none;
-
+
}
#top-nav .navbar.navbar-static-top .brand.cluster-name{
margin-left: 10px;
@@ -487,7 +491,7 @@ a.gotoinstance{
}
.create-view-form .description h4 span{
font-weight: normal;
-
+
}
.create-view-form .view-header{
}
@@ -553,7 +557,7 @@ a.gotoinstance{
top: 5px;
right: 50px;
z-index: 10;
-}
+}
.views-list-pane .search-container .close{
right: 50px;
top: 5px;
@@ -629,6 +633,9 @@ ul.nav li > a{
.padding-left-30{
padding-left: 30px;
}
+.padding-bottom-30{
+ padding-bottom: 30px;
+}
.no-margin-bottom{
margin-bottom: 0!important;
}
@@ -1136,7 +1143,7 @@ button.btn.btn-xs{
-ms-transform: translateX(1000px);
-o-transform: translateX(1000px);
transform: translateX(1000px);
-
+
padding: 0;
margin: 0;
max-height: 0;
@@ -1260,15 +1267,15 @@ button.btn.btn-xs{
}
@-webkit-keyframes stretchdelay {
- 0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
+ 0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
20% { -webkit-transform: scaleY(1.0) }
}
@keyframes stretchdelay {
- 0%, 40%, 100% {
+ 0%, 40%, 100% {
transform: scaleY(0.4);
-webkit-transform: scaleY(0.4);
- } 20% {
+ } 20% {
transform: scaleY(1.0);
-webkit-transform: scaleY(1.0);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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 20ccadb..eaff70b 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
@@ -77,14 +77,6 @@
</div>
</div>
- <div class="form-group" ng-class="{'has-error' : form.instanceCreateForm.submitted }">
- <label for="" class="control-label col-sm-3">{{'views.shortUrl' | translate}}</label>
- <div class="col-sm-9">
- <input type="text" class="form-control" name="short_url" ng-model="instance.shortUrl" maxlength="200">
- </div>
- </div>
-
-
<div class="form-group">
<div class="col-sm-10 col-sm-offset-3">
<div class="checkbox">
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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 b41abc8..8eff030 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
@@ -78,14 +78,13 @@
</div>
</div>
-
- <div class="form-group" ng-class="{'has-error' : form.instanceCreateForm.submitted }">
+ <div class="form-group">
<label for="" class="control-label col-sm-3">{{'views.shortUrl' | translate}}</label>
<div class="col-sm-9">
- <input type="text" class="form-control" name="short_url" ng-model="settings.shortUrl" maxlength="200">
-
+ <p class="form-control-static"><a href="/#/main/view/{{instance.ViewInstanceInfo.view_name}}/{{settings.shortUrl}}" ng-if="settings.shortUrl">{{settings.shortUrl}}</a></p>
+ <a ng-if="!settings.shortUrl" href="#/urls/link/{{instance.ViewInstanceInfo.view_name}}/{{instance.ViewInstanceInfo.version}}/{{instance.ViewInstanceInfo.instance_name}}" class="btn btn-primary createuser-btn"><span class="glyphicon glyphicon-plus"></span> {{'views.urlCreate' | translate}}</a>
+ </div>
</div>
- </div>
<div class="form-group">
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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
index ae71d78..906eef5 100644
--- 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
@@ -15,87 +15,87 @@
* 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>
+ <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>
</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-3">
- <i class="glyphicon glyphicon-chevron-right" ng-class="{'opened': view.isOpened}"></i>
- {{view.view_name}}
- </div>
- <div class="col-sm-3">
+ <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-3">
+ <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 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>
+ <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>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="col-sm-3"></td>
+ <td class="col-sm-3">
+ <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 class="alert alert-info" ng-show="views && !filteredViews.length">
+ {{'common.alerts.nothingToDisplay' | translate: '{term: constants.views}'}}
</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>
- </tr>
- </tbody>
- <tfoot>
- <tr>
- <td class="col-sm-3"></td>
- <td class="col-sm-3">
- <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 class="alert alert-info" ng-show="views && !filteredViews.length">
- {{'common.alerts.nothingToDisplay' | translate: '{term: constants.views}'}}
- </div>
- </accordion>
+ </accordion>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/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
new file mode 100644
index 0000000..a2949f9
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/listUrls.html
@@ -0,0 +1,72 @@
+<!--
+* 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" data-ng-init="listViewUrls()">
+
+
+ <div class="clearfix">
+ <ol class="breadcrumb pull-left">
+ <li class="active">{{'common.viewUrls' | translate}}</li>
+ </ol>
+ <div class="pull-right top-margin-4">
+ <link-to route="views.createViewUrl" class="btn btn-primary createuser-btn"><span class="glyphicon glyphicon-plus"></span> {{'views.urlCreate' | translate}}</link-to>
+ </div>
+ </div>
+ <hr>
+ <table class="table table-striped table-hover">
+ <thead>
+ <tr>
+
+ <th>
+ <span class="padding-bottom-30">{{'urls.name' | translate}}</span>
+ </th>
+ <th>
+ <span class="padding-bottom-30">{{'urls.url' | translate}}</span>
+ </th>
+ <th>
+ <span class="padding-bottom-30">{{'urls.view' | translate}}</span>
+ </th>
+ <th>
+ <span class="padding-bottom-30">{{'urls.viewInstance' | translate}}</span>
+ </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 href="/#/main/view/{{url.ViewUrlInfo.view_instance_common_name}}/{{url.ViewUrlInfo.url_suffix}}">/main/view/{{url.ViewUrlInfo.view_instance_common_name}}/{{url.ViewUrlInfo.url_suffix}}</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 class="alert alert-info col-sm-12" ng-show="!urls.items.length">
+ {{'urls.noUrlsToDisplay'| translate}}
+ </div>
+
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-admin/src/main/resources/ui/admin-web/app/views/leftNavbar.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/leftNavbar.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/leftNavbar.html
index 9bc54ff..b155041 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/leftNavbar.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/leftNavbar.html
@@ -22,19 +22,19 @@
<div class="cluster-section" ng-show="cluster">
<div id="cluster-name" ng-switch on="editCluster.editingName">
<h5 ng-switch-when="false"><div title={{cluster.Clusters.cluster_name}} class="clusterDisplayName">{{clusterDisplayName()}}</div>
- <i ng-show="cluster.Clusters.provisioning_state == 'INSTALLED'"
- ng-click="toggleEditName()"
+ <i ng-show="cluster.Clusters.provisioning_state == 'INSTALLED'"
+ ng-click="toggleEditName()"
class="glyphicon glyphicon-edit pull-right edit-cluster-name renameCluster" tooltip="{{'common.renameCluster' | translate}}">
</i>
</h5>
- <form ng-keyup="toggleEditName($event)"
- tabindex="1"
- name="editClusterNameForm"
- class="editClusterNameForm"
+ <form ng-keyup="toggleEditName($event)"
+ tabindex="1"
+ name="editClusterNameForm"
+ class="editClusterNameForm"
ng-switch-when="true"
ng-submit="editCluster.name !== cluster.Clusters.cluster_name && editClusterNameForm.newClusterName.$valid && confirmClusterNameChange()">
- <div class="form-group"
+ <div class="form-group"
ng-class="{'has-error': editClusterNameForm.newClusterName.$invalid && !editClusterNameForm.newClusterName.$pristine }">
<input
autofocus
@@ -91,10 +91,12 @@
<div class="panel-body">
<ul class="nav nav-pills nav-stacked">
<li ng-class="{active: isActive('views.list')}"><link-to route="views.list" class="viewslist-link">{{'common.views' | translate}}</link-to></li>
+ <li ng-class="{active: isActive('views.listViewUrls')}"><link-to route="views.listViewUrls" class="viewsUrlList-link">{{'common.viewUrls' | translate}}</link-to></li>
</ul>
</div>
</div>
+
<div class="panel panel-default">
<div class="panel-heading"><span class="glyphicon glyphicon-user"></span> {{'common.userGroupManagement' | translate}}</div>
<div class="panel-body">
@@ -115,4 +117,4 @@
</div>
</div>
</div>
-
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create.html
new file mode 100644
index 0000000..eb31b42
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create.html
@@ -0,0 +1,51 @@
+<!--
+* 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.
+-->
+<ol class="breadcrumb">
+ <li><a href="#/users">{{'urls.url' | translate}}</a></li>
+ <li class="active">{{'urls.create' | translate}}</li>
+</ol>
+<hr>
+ <div class="row">
+ <div class="col-sm-10">
+
+ <div id="wizard-container" ng-controller="wizardController as wizard">
+
+ <div id="wizard-step-container" class="bottom-margin">
+ <ul class="nav nav-pills nav-justified">
+ <li ng-repeat="step in wizard.steps" ng-class="{'active':step.step == wizard.currentStep}"><a ng-click="wizard.gotoStep(step.step)" href="">{{step.name}}</a></li>
+ </ul>
+ </div>
+
+ <div id="wizard-content-container">
+ <ng-include src="wizard.getStepTemplate()"></ng-include>
+ </div>
+
+ <div id="wizard-navigation-container">
+ <div class="pull-right">
+ <span class="btn-group">
+ <button ng-disabled="wizard.currentStep <= 1" class="btn btn-default" name="previous" type="button" ng-click="wizard.gotoStep(wizard.currentStep - 1)"><i class="fa fa-arrow-left"></i> Previous step</button>
+ <button ng-disabled="wizard.currentStep >= wizard.steps.length" class="btn btn-primary" name="next" type="button" ng-click="wizard.gotoStep(wizard.currentStep + 1)">Next step <i class="fa fa-arrow-right"></i></button>
+ </span>
+ <button ng-disabled="wizard.currentStep != wizard.steps.length" class="btn btn-success" name="next" type="button" ng-click="wizard.save()"> <i class="fa fa-floppy-o"></i> Save</button>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_1.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_1.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_1.html
new file mode 100644
index 0000000..e19313e
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_1.html
@@ -0,0 +1,36 @@
+<!--
+* 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.
+-->
+
+<form ng-controller="wizardController as wizard" class="form-horizontal create-user-form" role="form" novalidate name="formHolder.form" autocomplete="off">
+ <div class="form-group" ng-class="{'has-error' : formHolder.form.url_name.$error.required && formHolder.form.submitted}">
+ <label for="urlname" class="col-sm-2 control-label">{{'urls.name' | translate}}</label>
+ <div class="col-sm-10">
+ <input type="text" id="urlname" class="form-control urlname-input" name="url_name" placeholder="{{'urls.name' | translate}}" ng-model="url.urlName" required autocomplete="off">
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_name.$error.required && formHolder.form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+
+
+ <div class="form-group" ng-class="{'has-error' : formHolder.form.url_view_name.$error.required && formHolder.form.submitted}">
+ <label for="urlselect" class="col-sm-2 control-label">{{'urls.view' | translate}}</label>
+ <div class="col-sm-10">
+ <select class="form-control" id="urlselect" name="url_view_name" ng-options="version for version in viewsVersions" ng-model="url.selectedView" required></select>
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_view_name.$error.required && formHolder.form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_2.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_2.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_2.html
new file mode 100644
index 0000000..36bce88
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_2.html
@@ -0,0 +1,44 @@
+<!--
+* 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.
+-->
+<form class="form-horizontal create-user-form" role="form" novalidate name="formHolder.form" autocomplete="off">
+ <div class="form-group" ng-class="{'has-error' : formHolder.form.url_name.$error.required && formHolder.form.submitted}">
+ <label for="urlname" class="col-sm-2 control-label">{{'urls.name' | translate}}</label>
+ <div class="col-sm-10">
+ <input disabled type="text" id="urlname" class="form-control urlname-input" name="url_name" placeholder="{{'urls.name' | translate}}" ng-model="url.urlName" required autocomplete="off">
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_name.$error.required && formHolder.form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+
+
+ <div class="form-group" ng-class="{'has-error' : formHolder.form.url_view_name.$error.required && formHolder.form.submitted}">
+ <label for="urlselect" class="col-sm-2 control-label">{{'urls.view' | translate}}</label>
+ <div class="col-sm-10">
+ <select class="form-control" disabled id="urlselect" name="url_view_name" ng-options="version for version in viewsVersions" ng-model="url.selectedView" required></select>
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_view_name.$error.required && formHolder.form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+
+ <div class="form-group" ng-class="{'has-error' : formHolder.form.url_view_instance_name.$error.required && formHolder.form.submitted}">
+ <label for="urlinstanceselect" class="col-sm-2 control-label">{{'urls.viewInstance' | translate}}</label>
+ <div class="col-sm-10">
+ <select class="form-control" id="urlinstanceselect" name="url_view_instance_name" ng-options="instance.instance for instance in viewInstances | filter:filterByName(url.selectedView)" ng-model="url.selectedInstance" required></select>
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_view_instance_name.$error.required && formHolder.form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+
+</form>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_3.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_3.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_3.html
new file mode 100644
index 0000000..e6b3c1c
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/create_step_3.html
@@ -0,0 +1,60 @@
+<!--
+* 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.
+-->
+<form class="form-horizontal create-user-form" role="form" novalidate name="formHolder.form" autocomplete="off">
+ <div class="form-group" ng-class="{'has-error' : formHolder.form.url_name.$error.required && formHolder.form.submitted}">
+ <label for="urlname" class="col-sm-2 control-label">{{'urls.name' | translate}}</label>
+ <div class="col-sm-10">
+ <input disabled type="text" id="urlname" class="form-control urlname-input" name="url_name" placeholder="{{'urls.name' | translate}}" ng-model="url.urlName" required autocomplete="off">
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_name.$error.required && formHolder.form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+
+
+ <div class="form-group" ng-class="{'has-error' : formHolder.form.url_view_name.$error.required && formHolder.form.submitted}">
+ <label for="urlselect" class="col-sm-2 control-label">{{'urls.view' | translate}}</label>
+ <div class="col-sm-10">
+ <select class="form-control" disabled id="urlselect" name="url_view_name" ng-options="version for version in viewsVersions" ng-model="url.selectedView" required></select>
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_view_name.$error.required && formHolder.form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+
+ <div class="form-group" ng-class="{'has-error' : formHolder.form.url_view_instance_name.$error.required && formHolder.form.submitted}">
+ <label for="urlinstanceselect" class="col-sm-2 control-label">{{'urls.viewInstance' | translate}}</label>
+ <div class="col-sm-10">
+ <select class="form-control" disabled id="urlinstanceselect" name="url_view_instance_name" ng-options="instance.instance for instance in viewInstances | filter:filterByName(url.selectedView)" ng-model="url.selectedInstance" required></select>
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_view_instance_name.$error.required && formHolder.form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+
+
+
+ <div class="form-group" ng-class="{'has-error' : formHolder.form.url_view_suffix.$error.required && formHolder.form.submitted}">
+ <label for="urlsuffixin" class="col-sm-2 control-label">{{'views.shortUrl' | translate}}</label>
+ <div class="col-sm-10">
+ <div class="input-group">
+ <span id="basic-addon1" class="input-group-addon">/main/view/{{chomp(url.selectedView)}}/</span><input aria-describedby="basic-addon1" type="text" class="form-control" id="urlsuffixin" name="url_view_suffix" placeholder="{{'views.shortUrl' | translate}}" ng-model="url.suffix" ng-pattern="/[a-z]+/" ng-minlength="3" ng-maxlength="10" required autocomplete="off">
+ </div>
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_view_suffix.$error.required && formHolder.form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_view_suffix.$error.minlength && formHolder.form.submitted">{{'common.alerts.tooShort' | translate}}</div>
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_view_suffix.$error.maxlength && formHolder.form.submitted">{{'common.alerts.tooLong' | translate}}</div>
+ <div class="alert alert-danger top-margin" ng-show="formHolder.form.url_view_suffix.$error.pattern && formHolder.form.submitted">{{'common.alerts.onlyText' | translate}}</div>
+
+ </div>
+ </div>
+
+</form>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/edit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/edit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/edit.html
new file mode 100644
index 0000000..de7722e
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/urls/edit.html
@@ -0,0 +1,73 @@
+<!--
+* 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.
+-->
+<ol class="breadcrumb">
+ <li><a href="#/users">{{'urls.url' | translate}}</a></li>
+ <li class="active">{{'urls.edit' | translate}}</li>
+ <div class="pull-right top-margin-4">
+ <button class="btn deleteuser-btn btn-danger" ng-click="deleteUrl()">{{'views.urlDelete' | translate}}</button>
+ </div>
+</ol>
+<hr>
+
+
+<form class="form-horizontal create-user-form" role="form" novalidate name="url_form" autocomplete="off">
+ <div class="form-group" ng-class="{'has-error' : url_form.url_name.$error.required && url_form.submitted}">
+ <label for="urlname" class="col-sm-2 control-label">{{'urls.name' | translate}}</label>
+ <div class="col-sm-10">
+ <input disabled type="text" id="urlname" class="form-control urlname-input" name="url_name" placeholder="{{'urls.name' | translate}}" ng-model="url.url_name" required autocomplete="off">
+ <div class="alert alert-danger top-margin" ng-show="url_form.url_name.$error.required && url_form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+
+
+ <div class="form-group" ng-class="{'has-error' : url_form.url_view_name.$error.required && url_form.submitted}">
+ <label for="urlselect" class="col-sm-2 control-label">{{'urls.view' | translate}}</label>
+ <div class="col-sm-10">
+ <input class="form-control" disabled id="urlselect" name="url_view_name" ng-model="nameVersion" required>
+ <div class="alert alert-danger top-margin" ng-show="url_form.url_view_name.$error.required && url_form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+
+ <div class="form-group" ng-class="{'has-error' : url_form.url_view_instance_name.$error.required && url_form.submitted}">
+ <label for="urlinstanceselect" class="col-sm-2 control-label">{{'urls.viewInstance' | translate}}</label>
+ <div class="col-sm-10">
+ <input class="form-control" disabled id="urlinstanceselect" name="url_view_instance_name" ng-model="url.view_instance_name" required>
+ <div class="alert alert-danger top-margin" ng-show="url_form.url_view_instance_name.$error.required && url_form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ </div>
+ </div>
+
+
+
+ <div class="form-group" ng-class="{'has-error' : url_form.url_view_suffix.$error.required && url_form.submitted}">
+ <label for="urlsuffixin" class="col-sm-2 control-label">{{'views.shortUrl' | translate}}</label>
+ <div class="col-sm-10">
+ <div class="input-group">
+ <span id="basic-addon1" class="input-group-addon">/main/view/{{url.view_instance_common_name}}/</span><input aria-describedby="basic-addon1" type="text" class="form-control" id="urlsuffixin" name="url_view_suffix" placeholder="{{'views.shortUrl' | translate}}" ng-model="url.url_suffix" ng-pattern="/[a-z]+/" ng-minlength="3" ng-maxlength="10" required autocomplete="off">
+ </div>
+ <div class="alert alert-danger top-margin" ng-show="url_form.url_view_suffix.$error.required && url_form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
+ <div class="alert alert-danger top-margin" ng-show="url_form.url_view_suffix.$error.minlength && url_form.submitted">{{'common.alerts.tooShort' | translate}}</div>
+ <div class="alert alert-danger top-margin" ng-show="url_form.url_view_suffix.$error.maxlength && url_form.submitted">{{'common.alerts.tooLong' | translate}}</div>
+ <div class="alert alert-danger top-margin" ng-show="url_form.url_view_suffix.$error.pattern && url_form.submitted">{{'common.alerts.onlyText' | translate}}</div>
+
+ </div>
+ </div>
+ <div class="pull-right">
+ <button ng-disabled="wizard.currentStep != wizard.steps.length" class="btn btn-success" name="update_url_button" type="button" ng-click="updateUrl()"> <i class="fa fa-edit"></i> Update</button>
+ </div>
+
+</form>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index eed2703..0b77511 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -237,6 +237,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
resourceDefinition = new ViewInstanceResourceDefinition(subResourceDefinitions);
break;
+ case ViewURL:
+ resourceDefinition = new ViewUrlResourceDefinition();
+ break;
+
case Blueprint:
resourceDefinition = new BlueprintResourceDefinition();
break;
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewUrlResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewUrlResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewUrlResourceDefinition.java
new file mode 100644
index 0000000..d2c7b62
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewUrlResourceDefinition.java
@@ -0,0 +1,54 @@
+/**
+ * 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.
+ */
+
+package org.apache.ambari.server.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+import java.util.Collections;
+import java.util.Set;
+
+
+/**
+ * View resource definition.
+ */
+public class ViewUrlResourceDefinition extends BaseResourceDefinition {
+
+ // ----- Constructors ------------------------------------------------------
+
+ /**
+ * Construct a view resource definition.
+ */
+ public ViewUrlResourceDefinition() {
+ super(Resource.Type.ViewURL);
+ }
+
+
+ // ----- ResourceDefinition ------------------------------------------------
+
+ @Override
+ public String getPluralName() {
+ return "view_urls";
+ }
+
+ @Override
+ public String getSingularName() {
+ return "view_url";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewUrlsService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewUrlsService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewUrlsService.java
new file mode 100644
index 0000000..3827c18
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewUrlsService.java
@@ -0,0 +1,144 @@
+/**
+ * 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.
+ */
+
+package org.apache.ambari.server.api.services;
+
+import com.google.common.base.Optional;
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.Collections;
+
+
+/**
+ * Service responsible for view resource requests.
+ */
+@Path("/view/urls")
+public class ViewUrlsService extends BaseService {
+
+ /**
+ * Get the list of all registered view URLs
+ * @param headers
+ * @param ui
+
+ * @return collections of all view urls and any instances registered against them
+ */
+ @GET
+ @Produces("text/plain")
+ public Response getViewUrls(@Context HttpHeaders headers, @Context UriInfo ui) {
+ return handleRequest(headers, null, ui, Request.Type.GET, createViewUrlResource(Optional.<String>absent()));
+ }
+
+
+ /**
+ * Create a new View URL
+ * @param body
+ * @param headers
+ * @param ui
+ * @param urlName
+ * @return
+ * @throws AuthorizationException
+ */
+ @POST
+ @Path("{urlName}")
+ @Produces("text/plain")
+ public Response createUrl(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("urlName") String urlName) throws AuthorizationException {
+ return handleRequest(headers, body, ui, Request.Type.POST, createViewUrlResource(Optional.of(urlName)));
+ }
+
+
+ /**
+ * Update a view URL
+ * @param body
+ * @param headers
+ * @param ui
+ * @param urlName
+ * @return
+ * @throws AuthorizationException
+ */
+ @PUT
+ @Path("{urlName}")
+ @Produces("text/plain")
+ public Response updateUrl(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("urlName") String urlName) throws AuthorizationException {
+ return handleRequest(headers, body, ui, Request.Type.PUT, createViewUrlResource(Optional.of(urlName)));
+ }
+
+ /**
+ * Remove a view URL
+ * @param body
+ * @param headers
+ * @param ui
+ * @param urlName
+ * @return
+ * @throws AuthorizationException
+ */
+ @DELETE
+ @Path("{urlName}")
+ @Produces("text/plain")
+ public Response deleteUrl(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("urlName") String urlName) throws AuthorizationException {
+ return handleRequest(headers, body, ui, Request.Type.DELETE, createViewUrlResource(Optional.of(urlName)));
+ }
+
+
+ /**
+ * Get information about a single view URL
+ * @param headers
+ * @param ui
+ * @param urlName
+ * @return
+ * @throws AuthorizationException
+ */
+ @GET
+ @Path("{urlName}")
+ @Produces("text/plain")
+ public Response getUrl(@Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("urlName") String urlName) throws AuthorizationException {
+ return handleRequest(headers, null, ui, Request.Type.GET, createViewUrlResource(Optional.of(urlName)));
+ }
+
+
+
+
+ // ----- helper methods ----------------------------------------------------
+
+ /**
+ * Create a view URL resource.
+ *
+ * @param urlName Name of the URL
+ *
+ * @return a view URL resource instance
+ */
+ private ResourceInstance createViewUrlResource(Optional<String> urlName) {
+ return createResource(Resource.Type.ViewURL,Collections.singletonMap(Resource.Type.ViewURL, urlName.isPresent()?urlName.get().toString():null));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
index c7dc117..4e7a032 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
@@ -68,6 +68,8 @@ public class DefaultProviderModule extends AbstractProviderModule {
return new ViewVersionResourceProvider();
case ViewInstance:
return new ViewInstanceResourceProvider();
+ case ViewURL:
+ return new ViewURLResourceProvider();
case StackServiceComponentDependency:
return new StackDependencyResourceProvider(propertyIds, keyPropertyIds);
case Permission:
http://git-wip-us.apache.org/repos/asf/ambari/blob/f62a9277/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java
index 6523962..2a9eee7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java
@@ -35,6 +35,7 @@ import org.apache.ambari.server.controller.utilities.PropertyHelper;
import org.apache.ambari.server.orm.entities.ViewEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceDataEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.orm.entities.ViewURLEntity;
import org.apache.ambari.server.security.authorization.RoleAuthorization;
import org.apache.ambari.server.view.ViewRegistry;
import org.apache.ambari.server.view.validation.InstanceValidationResultImpl;
@@ -242,7 +243,10 @@ public class ViewInstanceResourceProvider extends AbstractAuthorizedResourceProv
setResourceProperty(resource, VISIBLE_PROPERTY_ID, viewInstanceEntity.isVisible(), requestedIds);
setResourceProperty(resource, STATIC_PROPERTY_ID, viewInstanceEntity.isXmlDriven(), requestedIds);
setResourceProperty(resource, CLUSTER_HANDLE_PROPERTY_ID, viewInstanceEntity.getClusterHandle(), requestedIds);
- setResourceProperty(resource, SHORT_URL_PROPERTY_ID, viewInstanceEntity.getShortUrl(), requestedIds);
+ ViewURLEntity viewUrl = viewInstanceEntity.getViewUrl();
+ if(viewUrl != null) {
+ setResourceProperty(resource, SHORT_URL_PROPERTY_ID, viewUrl.getUrlSuffix(), requestedIds);
+ }
// only allow an admin to access the view properties
if (ViewRegistry.getInstance().checkAdmin()) {
@@ -344,11 +348,6 @@ public class ViewInstanceResourceProvider extends AbstractAuthorizedResourceProv
viewInstanceEntity.setClusterHandle((String) properties.get(CLUSTER_HANDLE_PROPERTY_ID));
}
- if (properties.containsKey(SHORT_URL_PROPERTY_ID)) {
- viewInstanceEntity.setShortUrl((String) properties.get(SHORT_URL_PROPERTY_ID));
- }
-
-
Map<String, String> instanceProperties = new HashMap<String, String>();
boolean isUserAdmin = viewRegistry.checkAdmin();
@@ -402,11 +401,6 @@ public class ViewInstanceResourceProvider extends AbstractAuthorizedResourceProv
throw new IllegalStateException("The view " + viewName + " is not loaded.");
}
- if(!Strings.isNullOrEmpty(instanceEntity.getShortUrl()) && viewRegistry.duplicatedShortUrl(instanceEntity)){
- throw new DuplicateResourceException("The short url " + instanceEntity.getShortUrl() + " already exists for "+ instanceEntity.getViewEntity().getCommonName() +
- " and version "+instanceEntity.getViewEntity().getVersion());
- }
-
if (viewRegistry.instanceExists(instanceEntity)) {
throw new DuplicateResourceException("The instance " + instanceEntity.getName() + " already exists.");
}
@@ -428,16 +422,9 @@ public class ViewInstanceResourceProvider extends AbstractAuthorizedResourceProv
@Transactional
@Override
public Void invoke() throws AmbariException {
- ViewRegistry viewRegistry = ViewRegistry.getInstance();
-
ViewInstanceEntity instance = toEntity(properties, true);
ViewEntity view = instance.getViewEntity();
- if(!Strings.isNullOrEmpty(instance.getShortUrl()) && viewRegistry.duplicatedShortUrl(instance)){
- throw new DuplicateResourceException("The short url " + instance.getShortUrl() + " already exists for "+ instance.getViewEntity().getCommonName() +
- " and version "+instance.getViewEntity().getVersion());
- }
-
if (includeInstance(view.getCommonName(), view.getVersion(), instance.getInstanceName(), false)) {
try {
ViewRegistry.getInstance().updateViewInstance(instance);