You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by mi...@apache.org on 2018/05/17 02:25:57 UTC

[incubator-trafficcontrol] 11/17: provides the ability to manage capabilities in TP

This is an automated email from the ASF dual-hosted git repository.

mitchell852 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-trafficcontrol.git

commit 6e9c49cca1f0e699c34f00ded6d3a2487082011b
Author: Jeremy Mitchell <mi...@gmail.com>
AuthorDate: Fri May 4 09:05:43 2018 -0600

    provides the ability to manage capabilities in TP
---
 traffic_portal/app/src/app.js                      |   5 +
 .../app/src/common/api/CapabilityService.js        |  53 +++++++---
 .../capability/FormCapabilityController.js}        |  22 ++---
 .../edit/FormEditCapabilityController.js           | 109 +++++++++++++++++++++
 .../capability/edit/index.js}                      |  22 +----
 .../form/capability/form.capability.tpl.html       |  58 +++++++++++
 .../capability/index.js}                           |  22 +----
 .../capability/new/FormNewCapabilityController.js} |  30 +++---
 .../capability/new/index.js}                       |  22 +----
 .../common/modules/form/role/form.role.tpl.html    |   5 +-
 .../common/modules/navigation/navigation.tpl.html  |   1 +
 .../capabilities/TableCapabilitiesController.js    |  12 ++-
 .../table/capabilities/table.capabilities.tpl.html |   7 +-
 .../private/capabilities/edit/index.js}            |  38 +++----
 .../private/capabilities/new/index.js}             |  38 +++----
 15 files changed, 299 insertions(+), 145 deletions(-)

diff --git a/traffic_portal/app/src/app.js b/traffic_portal/app/src/app.js
index a4e2dcb..9f5065d 100644
--- a/traffic_portal/app/src/app.js
+++ b/traffic_portal/app/src/app.js
@@ -60,7 +60,9 @@ var trafficPortal = angular.module('trafficPortal', [
         require('./modules/private/cacheChecks').name,
         require('./modules/private/cacheStats').name,
         require('./modules/private/capabilities').name,
+        require('./modules/private/capabilities/new').name,
         require('./modules/private/capabilities/list').name,
+        require('./modules/private/capabilities/edit').name,
         require('./modules/private/cdns').name,
         require('./modules/private/cdns/config').name,
         require('./modules/private/cdns/deliveryServices').name,
@@ -217,6 +219,9 @@ var trafficPortal = angular.module('trafficPortal', [
         require('./common/modules/form/asn').name,
         require('./common/modules/form/asn/edit').name,
         require('./common/modules/form/asn/new').name,
+        require('./common/modules/form/capability').name,
+        require('./common/modules/form/capability/edit').name,
+        require('./common/modules/form/capability/new').name,
         require('./common/modules/form/cdn').name,
         require('./common/modules/form/cdn/edit').name,
         require('./common/modules/form/cdn/new').name,
diff --git a/traffic_portal/app/src/common/api/CapabilityService.js b/traffic_portal/app/src/common/api/CapabilityService.js
index da8df4f..9d0855c 100644
--- a/traffic_portal/app/src/common/api/CapabilityService.js
+++ b/traffic_portal/app/src/common/api/CapabilityService.js
@@ -17,41 +17,68 @@
  * under the License.
  */
 
-var CapabilityService = function(Restangular, messageModel) {
+var CapabilityService = function(Restangular, $q, $http, messageModel, ENV) {
 
 	this.getCapabilities = function(queryParams) {
 		return Restangular.all('capabilities').getList(queryParams);
 	};
 
-	this.getCapability = function(id) {
-		return Restangular.one("capabilities", id).get();
+	this.getCapability = function(name) {
+		return Restangular.one("capabilities", name).get();
 	};
 
-	this.updateCapability = function(capability) {
-		return capability.put()
+	this.createCapability = function(cap) {
+		var request = $q.defer();
+
+		$http.post(ENV.api['root'] + "capabilities", cap)
 			.then(
-				function() {
-					messageModel.setMessages([ { level: 'success', text: 'Capability updated' } ], false);
+				function(result) {
+					request.resolve(result.data);
 				},
 				function(fault) {
 					messageModel.setMessages(fault.data.alerts, false);
+					request.reject(fault);
 				}
 			);
+
+		return request.promise;
 	};
 
-	this.deleteCapability = function(capability) {
-		return capability.remove()
+	this.updateCapability = function(cap) {
+		var request = $q.defer();
+
+		$http.put(ENV.api['root'] + "capabilities/" + cap.name, cap)
 			.then(
-				function() {
-					messageModel.setMessages([ { level: 'success', text: 'Capability deleted' } ], true);
+				function(result) {
+					request.resolve(result.data);
 				},
 				function(fault) {
-					messageModel.setMessages(fault.data.alerts, true);
+					messageModel.setMessages(fault.data.alerts, false);
+					request.reject();
 				}
 			);
+
+		return request.promise;
+	};
+
+	this.deleteCapability = function(cap) {
+		var request = $q.defer();
+
+		$http.delete(ENV.api['root'] + "capabilities/" + cap.name)
+			.then(
+				function(result) {
+					request.resolve(result.data);
+				},
+				function(fault) {
+					messageModel.setMessages(fault.data.alerts, false);
+					request.reject(fault);
+				}
+			);
+
+		return request.promise;
 	};
 
 };
 
-CapabilityService.$inject = ['Restangular', 'messageModel'];
+CapabilityService.$inject = ['Restangular', '$q', '$http', 'messageModel', 'ENV'];
 module.exports = CapabilityService;
diff --git a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js b/traffic_portal/app/src/common/modules/form/capability/FormCapabilityController.js
similarity index 60%
copy from traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
copy to traffic_portal/app/src/common/modules/form/capability/FormCapabilityController.js
index 0184f41..89445ca 100644
--- a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
+++ b/traffic_portal/app/src/common/modules/form/capability/FormCapabilityController.js
@@ -17,23 +17,17 @@
  * under the License.
  */
 
-var TableCapabilitiesController = function(capabilities, $scope, $state) {
+var FormCapabilityController = function(capability, $scope, formUtils, locationUtils) {
 
-	$scope.capabilities = capabilities;
+	$scope.capability = capability;
 
-	$scope.refresh = function() {
-		$state.reload(); // reloads all the resolves for the view
-	};
+	$scope.navigateToPath = locationUtils.navigateToPath;
 
-	angular.element(document).ready(function () {
-		$('#capabilitiesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": []
-		});
-	});
+	$scope.hasError = formUtils.hasError;
+
+	$scope.hasPropertyError = formUtils.hasPropertyError;
 
 };
 
-TableCapabilitiesController.$inject = ['capabilities', '$scope', '$state'];
-module.exports = TableCapabilitiesController;
+FormCapabilityController.$inject = ['capability', '$scope', 'formUtils', 'locationUtils'];
+module.exports = FormCapabilityController;
diff --git a/traffic_portal/app/src/common/modules/form/capability/edit/FormEditCapabilityController.js b/traffic_portal/app/src/common/modules/form/capability/edit/FormEditCapabilityController.js
new file mode 100644
index 0000000..da933ab
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/form/capability/edit/FormEditCapabilityController.js
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+var FormEditCapabilityController = function(capability, $scope, $controller, $uibModal, $anchorScroll, $location, locationUtils, capabilityService, messageModel) {
+
+	// extends the FormCapabilityController to inherit common methods
+	angular.extend(this, $controller('FormCapabilityController', { capability: capability, $scope: $scope }));
+
+	var deleteCapability = function(cap) {
+		capabilityService.deleteCapability(cap)
+			.then(function(result) {
+				messageModel.setMessages(result.alerts, true);
+				locationUtils.navigateToPath('/capabilities');
+			});
+	};
+
+	var save = function(cap) {
+		capabilityService.updateCapability(cap).
+			then(function(result) {
+				$scope.capName = angular.copy(cap.name);
+				messageModel.setMessages(result.alerts, false);
+				$anchorScroll(); // scrolls window to top
+			});
+	};
+
+	$scope.capName = angular.copy($scope.capability.name);
+
+	$scope.settings = {
+		isNew: false,
+		saveLabel: 'Update'
+	};
+
+	$scope.viewEndpoints = function() {
+		alert('viewEndpoints');
+		return;
+		$location.path($location.path() + '/endpoints');
+	};
+
+	$scope.viewUsers = function() {
+		alert('viewUsers');
+		return;
+		$location.path($location.path() + '/users');
+	};
+
+	$scope.confirmSave = function(cap) {
+		var params = {
+			title: 'Update Capability?',
+			message: 'Are you sure you want to update the capability?'
+		};
+
+		var modalInstance = $uibModal.open({
+			templateUrl: 'common/modules/dialog/confirm/dialog.confirm.tpl.html',
+			controller: 'DialogConfirmController',
+			size: 'md',
+			resolve: {
+				params: function () {
+					return params;
+				}
+			}
+		});
+		modalInstance.result.then(function() {
+			save(cap);
+		}, function () {
+			// do nothing
+		});
+	};
+
+	$scope.confirmDelete = function(cap) {
+		var params = {
+			title: 'Delete Capability: ' + cap.name,
+			key: cap.name
+		};
+		var modalInstance = $uibModal.open({
+			templateUrl: 'common/modules/dialog/delete/dialog.delete.tpl.html',
+			controller: 'DialogDeleteController',
+			size: 'md',
+			resolve: {
+				params: function () {
+					return params;
+				}
+			}
+		});
+		modalInstance.result.then(function() {
+			deleteCapability(cap);
+		}, function () {
+			// do nothing
+		});
+	};
+
+};
+
+FormEditCapabilityController.$inject = ['capability', '$scope', '$controller', '$uibModal', '$anchorScroll', '$location', 'locationUtils', 'capabilityService', 'messageModel'];
+module.exports = FormEditCapabilityController;
diff --git a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js b/traffic_portal/app/src/common/modules/form/capability/edit/index.js
similarity index 60%
copy from traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
copy to traffic_portal/app/src/common/modules/form/capability/edit/index.js
index 0184f41..52b7e61 100644
--- a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
+++ b/traffic_portal/app/src/common/modules/form/capability/edit/index.js
@@ -17,23 +17,5 @@
  * under the License.
  */
 
-var TableCapabilitiesController = function(capabilities, $scope, $state) {
-
-	$scope.capabilities = capabilities;
-
-	$scope.refresh = function() {
-		$state.reload(); // reloads all the resolves for the view
-	};
-
-	angular.element(document).ready(function () {
-		$('#capabilitiesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": []
-		});
-	});
-
-};
-
-TableCapabilitiesController.$inject = ['capabilities', '$scope', '$state'];
-module.exports = TableCapabilitiesController;
+module.exports = angular.module('trafficPortal.form.capability.edit', [])
+	.controller('FormEditCapabilityController', require('./FormEditCapabilityController'));
diff --git a/traffic_portal/app/src/common/modules/form/capability/form.capability.tpl.html b/traffic_portal/app/src/common/modules/form/capability/form.capability.tpl.html
new file mode 100644
index 0000000..6173a20
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/form/capability/form.capability.tpl.html
@@ -0,0 +1,58 @@
+<!--
+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="x_panel">
+    <div class="x_title">
+        <ol class="breadcrumb pull-left">
+            <li><a ng-click="navigateToPath('/capabilities')">Capabilities</a></li>
+            <li class="active">{{capName}}</li>
+        </ol>
+        <div class="pull-right" role="group" ng-show="!settings.isNew">
+            <button class="btn btn-primary" title="View Endpoints" ng-click="viewEndpoints()">View Endpoints</button>
+            <button class="btn btn-primary" title="View Users" ng-click="viewUsers()">View Users</button>
+        </div>
+        <div class="clearfix"></div>
+    </div>
+    <div class="x_content">
+        <br>
+        <form name="capForm" class="form-horizontal form-label-left" novalidate>
+            <div class="form-group" ng-class="{'has-error': hasError(capForm.name), 'has-feedback': hasError(capForm.name)}">
+                <label class="control-label col-md-2 col-sm-2 col-xs-12">Name *</label>
+                <div class="col-md-10 col-sm-10 col-xs-12">
+                    <input name="name" type="text" class="form-control" placeholder="Example: foo-read or foo-write" ng-disabled="!settings.isNew" ng-model="capability.name" ng-pattern="/^\S*$/" required autofocus>
+                    <small class="input-error" ng-show="hasPropertyError(capForm.name, 'required')">Required</small>
+                    <small class="input-error" ng-show="hasPropertyError(capForm.name, 'pattern')">No spaces</small>
+                    <span ng-show="hasError(capForm.name)" class="form-control-feedback"><i class="fa fa-times"></i></span>
+                </div>
+            </div>
+            <div class="form-group" ng-class="{'has-error': hasError(capForm.description), 'has-feedback': hasError(capForm.description)}">
+                <label class="control-label col-md-2 col-sm-2 col-xs-12">Description *</label>
+                <div class="col-md-10 col-sm-10 col-xs-12">
+                    <textarea name="description" type="text" class="form-control" ng-model="capability.description" rows="10" required autofocus></textarea>
+                    <small class="input-error" ng-show="hasPropertyError(capForm.description, 'required')">Required</small>
+                    <span ng-show="hasError(capForm.description)" class="form-control-feedback"><i class="fa fa-times"></i></span>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-danger" ng-show="!settings.isNew" ng-click="confirmDelete(capability)">Delete</button>
+                <button type="button" class="btn btn-success" ng-disabled="capForm.$pristine || capForm.$invalid" ng-click="confirmSave(capability)">{{settings.saveLabel}}</button>
+            </div>
+        </form>
+    </div>
+</div>
diff --git a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js b/traffic_portal/app/src/common/modules/form/capability/index.js
similarity index 60%
copy from traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
copy to traffic_portal/app/src/common/modules/form/capability/index.js
index 0184f41..fea4d08 100644
--- a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
+++ b/traffic_portal/app/src/common/modules/form/capability/index.js
@@ -17,23 +17,5 @@
  * under the License.
  */
 
-var TableCapabilitiesController = function(capabilities, $scope, $state) {
-
-	$scope.capabilities = capabilities;
-
-	$scope.refresh = function() {
-		$state.reload(); // reloads all the resolves for the view
-	};
-
-	angular.element(document).ready(function () {
-		$('#capabilitiesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": []
-		});
-	});
-
-};
-
-TableCapabilitiesController.$inject = ['capabilities', '$scope', '$state'];
-module.exports = TableCapabilitiesController;
+module.exports = angular.module('trafficPortal.form.capability', [])
+	.controller('FormCapabilityController', require('./FormCapabilityController'));
diff --git a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js b/traffic_portal/app/src/common/modules/form/capability/new/FormNewCapabilityController.js
similarity index 51%
copy from traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
copy to traffic_portal/app/src/common/modules/form/capability/new/FormNewCapabilityController.js
index 0184f41..b023c37 100644
--- a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
+++ b/traffic_portal/app/src/common/modules/form/capability/new/FormNewCapabilityController.js
@@ -17,23 +17,27 @@
  * under the License.
  */
 
-var TableCapabilitiesController = function(capabilities, $scope, $state) {
+var FormNewCapabilityController = function(capability, $scope, $controller, locationUtils, capabilityService, messageModel) {
 
-	$scope.capabilities = capabilities;
+	// extends the FormCapabilityController to inherit common methods
+	angular.extend(this, $controller('FormCapabilityController', { capability: capability, $scope: $scope }));
 
-	$scope.refresh = function() {
-		$state.reload(); // reloads all the resolves for the view
+	$scope.capName = 'New';
+
+	$scope.settings = {
+		isNew: true,
+		saveLabel: 'Create'
 	};
 
-	angular.element(document).ready(function () {
-		$('#capabilitiesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": []
-		});
-	});
+	$scope.confirmSave = function(cap) {
+		capabilityService.createCapability(cap).
+			then(function(result) {
+				messageModel.setMessages(result.alerts, true);
+				locationUtils.navigateToPath('/capabilities');
+			});
+	};
 
 };
 
-TableCapabilitiesController.$inject = ['capabilities', '$scope', '$state'];
-module.exports = TableCapabilitiesController;
+FormNewCapabilityController.$inject = ['capability', '$scope', '$controller', 'locationUtils', 'capabilityService', 'messageModel'];
+module.exports = FormNewCapabilityController;
diff --git a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js b/traffic_portal/app/src/common/modules/form/capability/new/index.js
similarity index 60%
copy from traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
copy to traffic_portal/app/src/common/modules/form/capability/new/index.js
index 0184f41..96ed51d 100644
--- a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
+++ b/traffic_portal/app/src/common/modules/form/capability/new/index.js
@@ -17,23 +17,5 @@
  * under the License.
  */
 
-var TableCapabilitiesController = function(capabilities, $scope, $state) {
-
-	$scope.capabilities = capabilities;
-
-	$scope.refresh = function() {
-		$state.reload(); // reloads all the resolves for the view
-	};
-
-	angular.element(document).ready(function () {
-		$('#capabilitiesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": []
-		});
-	});
-
-};
-
-TableCapabilitiesController.$inject = ['capabilities', '$scope', '$state'];
-module.exports = TableCapabilitiesController;
+module.exports = angular.module('trafficPortal.form.capability.new', [])
+	.controller('FormNewCapabilityController', require('./FormNewCapabilityController'));
diff --git a/traffic_portal/app/src/common/modules/form/role/form.role.tpl.html b/traffic_portal/app/src/common/modules/form/role/form.role.tpl.html
index c451a19..0dfece9 100644
--- a/traffic_portal/app/src/common/modules/form/role/form.role.tpl.html
+++ b/traffic_portal/app/src/common/modules/form/role/form.role.tpl.html
@@ -35,8 +35,9 @@ under the License.
             <div class="form-group" ng-class="{'has-error': hasError(roleForm.name), 'has-feedback': hasError(roleForm.name)}">
                 <label class="control-label col-md-2 col-sm-2 col-xs-12">Name *</label>
                 <div class="col-md-10 col-sm-10 col-xs-12">
-                    <input name="name" type="text" class="form-control" ng-model="role.name" required autofocus>
+                    <input name="name" type="text" class="form-control" ng-model="role.name" ng-pattern="/^\S*$/" required autofocus>
                     <small class="input-error" ng-show="hasPropertyError(roleForm.name, 'required')">Required</small>
+                    <small class="input-error" ng-show="hasPropertyError(roleForm.name, 'pattern')">No spaces</small>
                     <span ng-show="hasError(roleForm.name)" class="form-control-feedback"><i class="fa fa-times"></i></span>
                 </div>
             </div>
@@ -53,7 +54,7 @@ under the License.
             <div class="form-group" ng-class="{'has-error': hasError(roleForm.description), 'has-feedback': hasError(roleForm.description)}">
                 <label class="control-label col-md-2 col-sm-2 col-xs-12">Description *</label>
                 <div class="col-md-10 col-sm-10 col-xs-12">
-                    <textarea name="value" type="text" class="form-control" ng-model="role.description" rows="10" required autofocus></textarea>
+                    <textarea name="description" type="text" class="form-control" ng-model="role.description" rows="10" required autofocus></textarea>
                     <small class="input-error" ng-show="hasPropertyError(roleForm.description, 'required')">Required</small>
                     <span ng-show="hasError(roleForm.description)" class="form-control-feedback"><i class="fa fa-times"></i></span>
                 </div>
diff --git a/traffic_portal/app/src/common/modules/navigation/navigation.tpl.html b/traffic_portal/app/src/common/modules/navigation/navigation.tpl.html
index b535613..308d1e3 100644
--- a/traffic_portal/app/src/common/modules/navigation/navigation.tpl.html
+++ b/traffic_portal/app/src/common/modules/navigation/navigation.tpl.html
@@ -69,6 +69,7 @@ under the License.
                         <li class="side-menu-category-item" ng-class="{'current-page': isState('trafficPortal.private.users')}"><a href="/#!/users">Users</a></li>
                         <li class="side-menu-category-item" ng-class="{'current-page': isState('trafficPortal.private.tenants')}"><a href="/#!/tenants">Tenants</a></li>
                         <li class="side-menu-category-item" ng-class="{'current-page': isState('trafficPortal.private.roles')}"><a href="/#!/roles">Roles</a></li>
+                        <li class="side-menu-category-item" ng-class="{'current-page': isState('trafficPortal.private.capabilities')}"><a href="/#!/capabilities">Capabilities</a></li>
                     </ul>
                 </li>
                 <li class="side-menu-category" ng-if="customMenu.items.length > 0"><a href="javascript:void(0);"><i class="fa fa-sm fa-chevron-right"></i> {{::customMenu.name}}</span></a>
diff --git a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js b/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
index 0184f41..9fabc21 100644
--- a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
+++ b/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
@@ -17,10 +17,18 @@
  * under the License.
  */
 
-var TableCapabilitiesController = function(capabilities, $scope, $state) {
+var TableCapabilitiesController = function(capabilities, $scope, $state, locationUtils) {
 
 	$scope.capabilities = capabilities;
 
+	$scope.editCapability = function(name) {
+		locationUtils.navigateToPath('/capabilities/' + name);
+	};
+
+	$scope.createCapability = function() {
+		locationUtils.navigateToPath('/capabilities/new');
+	};
+
 	$scope.refresh = function() {
 		$state.reload(); // reloads all the resolves for the view
 	};
@@ -35,5 +43,5 @@ var TableCapabilitiesController = function(capabilities, $scope, $state) {
 
 };
 
-TableCapabilitiesController.$inject = ['capabilities', '$scope', '$state'];
+TableCapabilitiesController.$inject = ['capabilities', '$scope', '$state', 'locationUtils'];
 module.exports = TableCapabilitiesController;
diff --git a/traffic_portal/app/src/common/modules/table/capabilities/table.capabilities.tpl.html b/traffic_portal/app/src/common/modules/table/capabilities/table.capabilities.tpl.html
index bf43e04..256f1ab 100644
--- a/traffic_portal/app/src/common/modules/table/capabilities/table.capabilities.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/capabilities/table.capabilities.tpl.html
@@ -23,6 +23,7 @@ under the License.
             <li class="active">Capabilities</li>
         </ol>
         <div class="pull-right">
+            <button class="btn btn-primary" title="Create Capability" ng-click="createCapability()"><i class="fa fa-plus"></i></button>
             <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
         </div>
         <div class="clearfix"></div>
@@ -37,9 +38,9 @@ under the License.
             </tr>
             </thead>
             <tbody>
-            <tr ng-repeat="capability in ::capabilities">
-                <td>{{::capability.name}}</td>
-                <td>{{::capability.description}}</td>
+            <tr ng-click="editCapability(c.name)" ng-repeat="c in ::capabilities">
+                <td>{{::c.name}}</td>
+                <td>{{::c.description}}</td>
             </tr>
             </tbody>
         </table>
diff --git a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js b/traffic_portal/app/src/modules/private/capabilities/edit/index.js
similarity index 56%
copy from traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
copy to traffic_portal/app/src/modules/private/capabilities/edit/index.js
index 0184f41..b51cd66 100644
--- a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
+++ b/traffic_portal/app/src/modules/private/capabilities/edit/index.js
@@ -17,23 +17,23 @@
  * under the License.
  */
 
-var TableCapabilitiesController = function(capabilities, $scope, $state) {
-
-	$scope.capabilities = capabilities;
-
-	$scope.refresh = function() {
-		$state.reload(); // reloads all the resolves for the view
-	};
-
-	angular.element(document).ready(function () {
-		$('#capabilitiesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": []
-		});
+module.exports = angular.module('trafficPortal.private.capabilities.edit', [])
+	.config(function($stateProvider, $urlRouterProvider) {
+		$stateProvider
+			.state('trafficPortal.private.capabilities.edit', {
+				url: '/{capName}',
+				views: {
+					capabilitiesContent: {
+						templateUrl: 'common/modules/form/capability/form.capability.tpl.html',
+						controller: 'FormEditCapabilityController',
+						resolve: {
+							capability: function($stateParams, capabilityService) {
+								return capabilityService.getCapability($stateParams.capName);
+							}
+						}
+					}
+				}
+			})
+		;
+		$urlRouterProvider.otherwise('/');
 	});
-
-};
-
-TableCapabilitiesController.$inject = ['capabilities', '$scope', '$state'];
-module.exports = TableCapabilitiesController;
diff --git a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js b/traffic_portal/app/src/modules/private/capabilities/new/index.js
similarity index 60%
copy from traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
copy to traffic_portal/app/src/modules/private/capabilities/new/index.js
index 0184f41..c6980e3 100644
--- a/traffic_portal/app/src/common/modules/table/capabilities/TableCapabilitiesController.js
+++ b/traffic_portal/app/src/modules/private/capabilities/new/index.js
@@ -17,23 +17,23 @@
  * under the License.
  */
 
-var TableCapabilitiesController = function(capabilities, $scope, $state) {
-
-	$scope.capabilities = capabilities;
-
-	$scope.refresh = function() {
-		$state.reload(); // reloads all the resolves for the view
-	};
-
-	angular.element(document).ready(function () {
-		$('#capabilitiesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": []
-		});
+module.exports = angular.module('trafficPortal.private.capabilities.new', [])
+	.config(function($stateProvider, $urlRouterProvider) {
+		$stateProvider
+			.state('trafficPortal.private.capabilities.new', {
+				url: '/new',
+				views: {
+					capabilitiesContent: {
+						templateUrl: 'common/modules/form/capability/form.capability.tpl.html',
+						controller: 'FormNewCapabilityController',
+						resolve: {
+							capability: function() {
+								return {};
+							}
+						}
+					}
+				}
+			})
+		;
+		$urlRouterProvider.otherwise('/');
 	});
-
-};
-
-TableCapabilitiesController.$inject = ['capabilities', '$scope', '$state'];
-module.exports = TableCapabilitiesController;

-- 
To stop receiving notification emails like this one, please contact
mitchell852@apache.org.