You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by oc...@apache.org on 2020/08/26 22:35:05 UTC

[trafficcontrol] branch master updated: Converts all of TP's server tables to use ag-grid (#4974)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 4929b9a  Converts all of TP's server tables to use ag-grid (#4974)
4929b9a is described below

commit 4929b9ab251a56bb2fda5fa39f28530a827e6d80
Author: Jeremy Mitchell <mi...@users.noreply.github.com>
AuthorDate: Wed Aug 26 16:34:50 2020 -0600

    Converts all of TP's server tables to use ag-grid (#4974)
    
    * allow a filter to be passed to the controller so table.servers.tpl.html and TableServersController can be used for cdn servers, type servers, status servers, etc...
    
    * removes unused condition when queuing/clearing cdn server updates
    
    * updates cdn servers table to use ag-grid
    
    * uses ag-grid from cachegroup servers table
    
    * uses ag-grid for phys loc servers table
    
    * uses ag-grid for profile servers table
    
    * uses ag-grid for status servers table
    
    * uses ag-grid for type servers table
    
    * passes in tablename and filter for the main servers table
    
    * uses ag-grid for ds servers table
    
    * refactors UI test to account for reorganization of buttons
    
    * adds changelog entry
    
    * fixes servers table documentation
    
    * updates image of servers table for new ag-grid
    
    * calls out the ability to filter by column in the servers table example and the description
    
    * adds table for topology servers
    
    * removes dependency on TableParentServersController so it can be deleted.
    
    * deletes the unused TableParentServerController that was used for the servers tables that used jquery datatables
    
    * fixes broken UI test
    
    * limits the contents of each server table to the correct scope identified in the url
---
 CHANGELOG.md                                       |   1 +
 .../traffic_portal/images/tp_table_server.png      | Bin 27136 -> 67910 bytes
 .../admin/traffic_portal/usingtrafficportal.rst    |   8 +-
 traffic_portal/app/src/app.js                      |   2 +
 .../TableCacheGroupServersController.js            |  45 +--
 .../table.cacheGroupServers.tpl.html               | 190 ++++------
 .../table/cdnServers/TableCDNServersController.js  |  34 +-
 .../table/cdnServers/table.cdnServers.tpl.html     | 190 ++++------
 .../TableDeliveryServiceServersController.js       |  66 +---
 .../table.deliveryServiceServers.tpl.html          | 188 ++++------
 .../TablePhysLocationServersController.js          |  34 +-
 .../table.physLocationServers.tpl.html             | 177 ++++-----
 .../TableProfileServersController.js               |  34 +-
 .../profileServers/table.profileServers.tpl.html   | 174 ++++-----
 .../TableServerCapabilityServersController.js      |  17 +-
 .../table.serverCapabilityServers.tpl.html         |   4 +-
 .../table/servers/TableParentServersController.js  | 414 ---------------------
 .../table/servers/TableServersController.js        | 168 +++------
 .../app/src/common/modules/table/servers/index.js  |   3 +-
 .../statusServers/TableStatusServersController.js  |  34 +-
 .../statusServers/table.statusServers.tpl.html     | 175 ++++-----
 .../TableTopologyServersController.js}             |  13 +-
 .../table/{servers => topologyServers}/index.js    |   6 +-
 .../topologyServers/table.topologyServers.tpl.html | 103 +++++
 .../typeServers/TableTypeServersController.js      |  34 +-
 .../table/typeServers/table.typeServers.tpl.html   | 174 ++++-----
 .../modules/private/cacheGroups/servers/index.js   |  13 +-
 .../app/src/modules/private/cdns/servers/index.js  |  13 +-
 .../private/deliveryServices/servers/index.js      |   3 +
 .../modules/private/physLocations/servers/index.js |  13 +-
 .../src/modules/private/profiles/servers/index.js  |  13 +-
 .../app/src/modules/private/servers/list/index.js  |   6 +
 .../src/modules/private/statuses/servers/index.js  |   9 +
 .../{profiles => topologies}/servers/index.js      |  23 +-
 .../app/src/modules/private/types/servers/index.js |   9 +
 traffic_portal/app/src/styles/main.scss            |  18 +
 .../deliveryServices/delivery-services-spec.js     |   3 +-
 .../test/end_to_end/deliveryServices/pageData.js   |   2 +-
 38 files changed, 879 insertions(+), 1534 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b87778b..e5413d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -63,6 +63,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 ### Changed
 - Changed some Traffic Ops Go Client methods to use `DeliveryServiceNullable` inputs and outputs.
 - Changed Traffic Portal to use Traffic Ops API v3
+- Changed Traffic Portal to use the more performant and powerful ag-grid for all server tables.
 - Changed ORT Config Generation to be deterministic, which will prevent spurious diffs when nothing actually changed.
 - Changed ORT to find the local ATS config directory and use it when location Parameters don't exist for many required configs, including all Delivery Service files (Header Rewrites, Regex Remap, URL Sig, URI Signing).
 - Changed the access logs in Traffic Ops to now show the route ID with every API endpoint call. The Route ID is appended to the end of the access log line.
diff --git a/docs/source/admin/traffic_portal/images/tp_table_server.png b/docs/source/admin/traffic_portal/images/tp_table_server.png
index c890926..4251813 100644
Binary files a/docs/source/admin/traffic_portal/images/tp_table_server.png and b/docs/source/admin/traffic_portal/images/tp_table_server.png differ
diff --git a/docs/source/admin/traffic_portal/usingtrafficportal.rst b/docs/source/admin/traffic_portal/usingtrafficportal.rst
index 801d3ae..e3d67b2 100644
--- a/docs/source/admin/traffic_portal/usingtrafficportal.rst
+++ b/docs/source/admin/traffic_portal/usingtrafficportal.rst
@@ -365,15 +365,16 @@ A configurable table of all servers (of all kinds) across all :term:`Delivery Se
 
 	Table of Servers
 
-Use the `Select Columns` menu to select the server columns to view and search. Columns can also be rearranged using drag-and-drop. Available server columns include:
+Use the `Quick Search` to search across all table columns or the column filter to apply a more powerful filter to individual columns. Use the `Select Columns` menu to select the server columns to view. Columns can also be rearranged using drag-and-drop. Available server columns include:
 
 :Cache Group:       [Visible by default] The :ref:`Name of the Cache Group <cache-group-name>` to which this server belongs
 :CDN:               [Visible by default] The name of the CDN to which the server belongs
 :Domain:            [Visible by default] The domain part of the server's :abbr:`FQDN (Fully Qualified Domain Name)`
+:Hash ID:			The identifier of the server used in Traffic Router's consistent hashing algorithm.
 :Host:              [Visible by default] The (short) hostname of the server
 :HTTPS Port:        The port on which the server listens for incoming HTTPS connections/requests
 :ID:                An integral, unique identifier for this server
-:ILO IP Address:    [Visible by default] The IPv4 address of the server's :abbr:`ILO (Integrated Lights-Out)` service
+:ILO IP Address:    The IPv4 address of the server's :abbr:`ILO (Integrated Lights-Out)` service
 
 	.. seealso:: `Hewlett Packard ILO Wikipedia Page <https://en.wikipedia.org/wiki/HP_Integrated_Lights-Out>`_
 
@@ -392,7 +393,7 @@ Use the `Select Columns` menu to select the server columns to view and search. C
 :Network MTU:       The Maximum Transmission Unit (MTU) to configured on ``interfaceName``
 :Network Subnet:    The IPv4 subnet mask used by ``interfaceName``
 :Offline Reason:    A user-entered reason why the server is in ADMIN_DOWN or OFFLINE status
-:Phys Location:     [Visible by default] The name of the physical location where the server resides
+:Phys Location:     The name of the physical location where the server resides
 :Profile:           [Visible by default] The :ref:`profile-name` of the :term:`Profile` used by this server
 :Rack:              A string indicating "server rack" location
 :Reval Pending:     [Visible by default] A boolean value represented as a clock (content invalidation/revalidation is pending) or green check mark (content invalidation/revalidation is not pending)
@@ -414,7 +415,6 @@ Server management includes the ability to (where applicable):
 - :term:`Queue Updates` on a server, or clear such updates
 - Update server status
 - View server :term:`Delivery Services`
-- View server configuration files
 - Clone :term:`Delivery Service` assignments
 - Assign :term:`Delivery Services` to server(s)
 - :ref:`server_server_capabilities`
diff --git a/traffic_portal/app/src/app.js b/traffic_portal/app/src/app.js
index 5b39530..ad83c4b 100644
--- a/traffic_portal/app/src/app.js
+++ b/traffic_portal/app/src/app.js
@@ -216,6 +216,7 @@ var trafficPortal = angular.module('trafficPortal', [
         require('./modules/private/topologies/edit').name,
         require('./modules/private/topologies/list').name,
         require('./modules/private/topologies/new').name,
+        require('./modules/private/topologies/servers').name,
         require('./modules/private/types/edit').name,
         require('./modules/private/types/list').name,
         require('./modules/private/types/new').name,
@@ -413,6 +414,7 @@ var trafficPortal = angular.module('trafficPortal', [
         require('./common/modules/table/topologyDeliveryServices').name,
         require('./common/modules/table/topologyCacheGroups').name,
         require('./common/modules/table/topologyCacheGroupServers').name,
+        require('./common/modules/table/topologyServers').name,
         require('./common/modules/table/types').name,
         require('./common/modules/table/typeCacheGroups').name,
         require('./common/modules/table/typeDeliveryServices').name,
diff --git a/traffic_portal/app/src/common/modules/table/cacheGroupServers/TableCacheGroupServersController.js b/traffic_portal/app/src/common/modules/table/cacheGroupServers/TableCacheGroupServersController.js
index 8ea50a2..b3d61c8 100644
--- a/traffic_portal/app/src/common/modules/table/cacheGroupServers/TableCacheGroupServersController.js
+++ b/traffic_portal/app/src/common/modules/table/cacheGroupServers/TableCacheGroupServersController.js
@@ -17,16 +17,14 @@
  * under the License.
  */
 
-var TableCacheGroupsServersController = function(cacheGroup, servers, $controller, $scope, $state, $uibModal, cacheGroupService) {
+var TableCacheGroupsServersController = function(cacheGroup, servers, filter, $controller, $scope, $state, $uibModal, cacheGroupService) {
 
-	// extends the TableParentServersController to inherit common methods
-	angular.extend(this, $controller('TableParentServersController', { servers: servers, $scope: $scope }));
-
-	let cacheGroupServersTable;
+	// extends the TableServersController to inherit common methods
+	angular.extend(this, $controller('TableServersController', { tableName: 'cacheGroupServers', servers: servers, filter: filter, $scope: $scope }));
 
 	$scope.cacheGroup = cacheGroup;
 
-	var queueCacheGroupServerUpdates = function(cacheGroup, cdnId) {
+	let queueCacheGroupServerUpdates = function(cacheGroup, cdnId) {
 		cacheGroupService.queueServerUpdates(cacheGroup.id, cdnId)
 			.then(
 				function() {
@@ -35,7 +33,7 @@ var TableCacheGroupsServersController = function(cacheGroup, servers, $controlle
 			);
 	};
 
-	var clearCacheGroupServerUpdates = function(cacheGroup, cdnId) {
+	let clearCacheGroupServerUpdates = function(cacheGroup, cdnId) {
 		cacheGroupService.clearServerUpdates(cacheGroup.id, cdnId)
 			.then(
 				function() {
@@ -45,11 +43,11 @@ var TableCacheGroupsServersController = function(cacheGroup, servers, $controlle
 	};
 
 	$scope.confirmCacheGroupQueueServerUpdates = function(cacheGroup) {
-		var params = {
+		const params = {
 			title: 'Queue Server Updates: ' + cacheGroup.name,
 			message: "Please select a CDN"
 		};
-		var modalInstance = $uibModal.open({
+		const modalInstance = $uibModal.open({
 			templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
 			controller: 'DialogSelectController',
 			size: 'md',
@@ -70,11 +68,11 @@ var TableCacheGroupsServersController = function(cacheGroup, servers, $controlle
 	};
 
 	$scope.confirmCacheGroupClearServerUpdates = function(cacheGroup) {
-		var params = {
+		const params = {
 			title: 'Clear Server Updates: ' + cacheGroup.name,
 			message: "Please select a CDN"
 		};
-		var modalInstance = $uibModal.open({
+		const modalInstance = $uibModal.open({
 			templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
 			controller: 'DialogSelectController',
 			size: 'md',
@@ -94,30 +92,7 @@ var TableCacheGroupsServersController = function(cacheGroup, servers, $controlle
 		});
 	};
 
-	$scope.toggleVisibility = function(colName) {
-		const col = cacheGroupServersTable.column(colName + ':name');
-		col.visible(!col.visible());
-		cacheGroupServersTable.rows().invalidate().draw();
-	};
-
-	angular.element(document).ready(function () {
-		cacheGroupServersTable = $('#cacheGroupServersTable').DataTable({
-			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": [],
-			"columns": $scope.columns,
-			"initComplete": function(settings, json) {
-				try {
-					// need to create the show/hide column checkboxes and bind to the current visibility
-					$scope.columns = JSON.parse(localStorage.getItem('DataTables_cacheGroupServersTable_/')).columns;
-				} catch (e) {
-					console.error("Failure to retrieve required column info from localStorage (key=DataTables_cacheGroupServersTable_/):", e);
-				}
-			}
-		});
-	});
-
 };
 
-TableCacheGroupsServersController.$inject = ['cacheGroup', 'servers', '$controller', '$scope', '$state', '$uibModal', 'cacheGroupService'];
+TableCacheGroupsServersController.$inject = ['cacheGroup', 'servers', 'filter', '$controller', '$scope', '$state', '$uibModal', 'cacheGroupService'];
 module.exports = TableCacheGroupsServersController;
diff --git a/traffic_portal/app/src/common/modules/table/cacheGroupServers/table.cacheGroupServers.tpl.html b/traffic_portal/app/src/common/modules/table/cacheGroupServers/table.cacheGroupServers.tpl.html
index da5f209..d69dc73 100644
--- a/traffic_portal/app/src/common/modules/table/cacheGroupServers/table.cacheGroupServers.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/cacheGroupServers/table.cacheGroupServers.tpl.html
@@ -20,126 +20,92 @@ under the License.
 <div class="x_panel">
     <div class="x_title">
         <ol class="breadcrumb pull-left">
-            <li><a ng-click="navigateToPath('/cache-groups')">Cache Groups</a></li>
-            <li><a ng-click="navigateToPath('/cache-groups/' + cacheGroup.id)">{{::cacheGroup.name}}</a></li>
+            <li><a href="#!/cache-groups">Cache Groups</a></li>
+            <li><a ng-href="#!/cache-groups/{{cacheGroup.id}}">{{::cacheGroup.name}}</a></li>
             <li class="active">Servers</li>
         </ol>
         <div class="pull-right">
-            <div class="btn-group" role="group" uib-dropdown is-open="queue.isopen">
-                <button type="button" class="btn btn-primary dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
-                    Queue Updates&nbsp;
-                    <span class="caret"></span>
-                </button>
-                <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
-                    <li role="menuitem"><a ng-click="confirmCacheGroupQueueServerUpdates(cacheGroup)"><i class="fa fa-flag"></i>&nbsp;&nbsp;Queue {{::cacheGroup.name}} Server Updates</a></li>
-                    <li role="menuitem"><a ng-click="confirmCacheGroupClearServerUpdates(cacheGroup)"><i class="fa fa-ban"></i>&nbsp;&nbsp;Clear {{::cacheGroup.name}} Server Updates</a></li>
-                </ul>
-            </div>
-            <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
-            <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
-                <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
-                    <i class="fa fa-columns"></i>&nbsp;
-                    <span class="caret"></span>
-                </button>
-                <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
-                    <li role="menuitem" ng-repeat="c in columns | orderBy:'name'">
-                        <div class="checkbox">
-                            <label><input type="checkbox" ng-model="c.visible" ng-click="toggleVisibility(c.name)"> {{::c.name}}</label>
-                        </div>
-                    </li>
-                </menu>
+            <div class="form-inline" role="search">
+                <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
+                <div class="input-group text-input">
+                    <span class="input-group-addon">
+                        <label for="pageSize">Page size</label>
+                    </span>
+                    <input id="pageSize" name="pageSize" type="number" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
+                </div>
+                <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
+                    <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        <i class="fa fa-columns"></i>&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
+                            <div class="checkbox">
+                                <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
+                            </div>
+                        </li>
+                    </menu>
+                </div>
+                <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
+                    <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        More&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem"><a name="createServerMenuItem" href="#!/servers/new">Create New Server</a></li>
+                        <li class="divider"></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="confirmCacheGroupQueueServerUpdates(cacheGroup)">Queue Server Updates</button></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="confirmCacheGroupClearServerUpdates(cacheGroup)">Clear Server Updates</button></li>
+                        <li class="divider"></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearColFilters()">Clear Column Filters</button></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
+                    </ul>
+                </div>
             </div>
         </div>
         <div class="clearfix"></div>
     </div>
     <div class="x_content">
-        <br>
-        <table id="cacheGroupServersTable" class="table responsive-utilities jambo_table">
-            <thead>
-                <tr class="headings">
-                    <th>Cache Group</th>
-                    <th>CDN</th>
-                    <th>Domain</th>
-                    <th>Host</th>
-                    <th>HTTPS Port</th>
-                    <th>ID</th>
-                    <th>ILO IP Address</th>
-                    <th>ILO IP Gateway</th>
-                    <th>ILO IP Netmask</th>
-                    <th>ILO Username</th>
-                    <th>Interface Name</th>
-                    <th>IPv6 Address</th>
-                    <th>IPv6 Gateway</th>
-                    <th>Last Updated</th>
-                    <th>Mgmt IP Address</th>
-                    <th>Mgmt IP Gateway</th>
-                    <th>Mgmt IP Netmask</th>
-                    <th>Network Gateway</th>
-                    <th>Network IP</th>
-                    <th>Network MTU</th>
-                    <th>Network Subnet</th>
-                    <th>Offline Reason</th>
-                    <th>Phys Location</th>
-                    <th>Profile</th>
-                    <th>Rack</th>
-                    <th>Reval Pending</th>
-                    <th>Router Hostname</th>
-                    <th>Router Port Name</th>
-                    <th>Status</th>
-                    <th>TCP Port</th>
-                    <th>Type</th>
-                    <th>Update Pending</th>
-                </tr>
-            </thead>
-            <tbody>
-                <tr ng-click="editServer(s.id)" ng-repeat="s in ::servers" ng-class="::{'active': s.updPending}" context-menu="contextMenuItems">
-                    <td data-search="^{{::s.cachegroup}}$">{{::s.cachegroup}}</td>
-                    <td data-search="^{{::s.cdnName}}$">{{::s.cdnName}}</td>
-                    <td data-search="^{{::s.domainName}}$">{{::s.domainName}}</td>
-                    <td data-search="^{{::s.hostName}}$">{{::s.hostName}}</td>
-                    <td data-search="^{{::s.httpsPort}}$">{{::s.httpsPort}}</td>
-                    <td data-search="^{{::s.id}}$">{{::s.id}}</td>
-                    <td data-search="^{{::s.iloIpAddress}}$"><a ng-click="ssh(s.iloIpAddress, $event)">{{::s.iloIpAddress}}</a></td>
-                    <td data-search="^{{::s.iloIpGateway}}$"><a ng-click="ssh(s.iloIpGateway, $event)">{{::s.iloIpGateway}}</a></td>
-                    <td data-search="^{{::s.iloIpNetmask}}$">{{::s.iloIpNetmask}}</td>
-                    <td data-search="^{{::s.iloUsername}}$">{{::s.iloUsername}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceName}}$">{{::serverNetInfo.get(s.id).interfaceName}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Address}}$">{{::serverNetInfo.get(s.id).ip6Address}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Gateway}}$">{{::serverNetInfo.get(s.id).ip6Gateway}}</td>
-                    <td data-search="^{{::getRelativeTime(s.lastUpdated)}}$" data-order="{{::s.lastUpdated}}">{{::getRelativeTime(s.lastUpdated)}}</td>
-                    <td data-search="^{{::s.mgmtIpAddress}}$"><a ng-click="ssh(s.mgmtIpAddress, $event)">{{::s.mgmtIpAddress}}</a></td>
-                    <td data-search="^{{::s.mgmtIpGateway}}$"><a ng-click="ssh(s.mgmtIpGateway, $event)">{{::s.mgmtIpGateway}}</a></td>
-                    <td data-search="^{{::s.mgmtIpNetmask}}$">{{::s.mgmtIpNetmask}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipGateway}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipGateway, $event)">{{::serverNetInfo.get(s.id).ipGateway}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipAddress}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipAddress, $event)">{{::serverNetInfo.get(s.id).ipAddress}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceMtu}}$">{{::serverNetInfo.get(s.id).interfaceMtu}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipNetmask}}$">{{::serverNetInfo.get(s.id).ipNetmask}}</td>
-                    <td data-search="^{{::s.offlineReason}}$">{{::s.offlineReason}}</td>
-                    <td data-search="^{{::s.physLocation}}$">{{::s.physLocation}}</td>
-                    <td data-search="^{{::s.profile}}$">{{::s.profile}}</td>
-                    <td data-search="^{{::s.rack}}$">{{::s.rack}}</td>
-                    <td data-search="{{(s.revalPending) ? 'RVL' : ''}}" data-order="{{::s.revalPending}}">
-                        <i title="Reval Pending (RVL)" ng-show="s.revalPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Reval Applied" ng-show="!s.revalPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                    <td data-search="^{{::s.routerHostName}}$">{{::s.routerHostName}}</td>
-                    <td data-search="^{{::s.routerPortName}}$">{{::s.routerPortName}}</td>
-                    <td data-search="^{{::s.status}}$">
-                        <span ng-if="!isOffline(s.status)">{{::s.status}}</span>
-                        <span ng-if="isOffline(s.status)" uib-popover="{{::offlineReason(s)}}" popover-title="Offline Reason" popover-trigger="mouseenter" popover-placement="bottom" popover-append-to-body="true">{{::s.status}}</span>
-                    </td>
-                    <td data-search="^{{::s.tcpPort}}$">{{::s.tcpPort}}</td>
-                    <td data-search="^{{::s.type}}$">{{::s.type}}</td>
-                    <td data-search="{{(s.updPending) ? 'UPD' : ''}}" data-order="{{::s.updPending}}">
-                        <i title="Updates Pending (UPD)" ng-show="s.updPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Updates Applied" ng-show="!s.updPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                </tr>
-            </tbody>
-        </table>
+        <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
     </div>
 </div>
 
-
-
-
+<menu class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
+    <ul>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}" target="_blank">Open in New Tab</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="http://{{server.hostName}}.{{server.domainName}}" target="_blank">Navigate To Server FQDN</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}">Edit</a>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmDelete(server, $event)">Delete</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmStatusUpdate(server, $event)">Update Status</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="queueServerUpdates(server, $event)" ng-disabled="!isCache(server) || server.updPending">Queue Server Updates</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="clearServerUpdates(server, $event)" ng-disabled="!isCache(server) || !server.updPending">Clear Server Updates</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-if="showCharts">
+            <a ng-href="{{chartsBase}}{{server.hostName}}" target="_blank">Show Charts</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-show="isCache(server)">
+            <a ng-href="#!/servers/{{server.id}}/capabilities">Manage Capabilities</a>
+        </li>
+        <li role="menuitem" ng-show="isEdge(server) || isOrigin(server)">
+            <a ng-href="#!/servers/{{server.id}}/delivery-services">Manage Delivery Services</a>
+        </li>
+    </ul>
+</menu>
diff --git a/traffic_portal/app/src/common/modules/table/cdnServers/TableCDNServersController.js b/traffic_portal/app/src/common/modules/table/cdnServers/TableCDNServersController.js
index b6a4dca..c2e31dc 100644
--- a/traffic_portal/app/src/common/modules/table/cdnServers/TableCDNServersController.js
+++ b/traffic_portal/app/src/common/modules/table/cdnServers/TableCDNServersController.js
@@ -17,39 +17,13 @@
  * under the License.
  */
 
-var TableCDNServersController = function(cdn, servers, $controller, $scope) {
+var TableCDNServersController = function(cdn, servers, filter, $controller, $scope) {
 
-	// extends the TableParentServersController to inherit common methods
-	angular.extend(this, $controller('TableParentServersController', { servers: servers, $scope: $scope }));
-
-	let cdnServersTable;
+	// extends the TableServersController to inherit common methods
+	angular.extend(this, $controller('TableServersController', { tableName: 'cdnServers', servers: servers, filter: filter, $scope: $scope }));
 
 	$scope.cdn = cdn;
-
-	$scope.toggleVisibility = function(colName) {
-		const col = cdnServersTable.column(colName + ':name');
-		col.visible(!col.visible());
-		cdnServersTable.rows().invalidate().draw();
-	};
-
-	angular.element(document).ready(function () {
-		cdnServersTable = $('#cdnServersTable').DataTable({
-			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": [],
-			"columns": $scope.columns,
-			"initComplete": function(settings, json) {
-				try {
-					// need to create the show/hide column checkboxes and bind to the current visibility
-					$scope.columns = JSON.parse(localStorage.getItem('DataTables_cdnServersTable_/')).columns;
-				} catch (e) {
-					console.error("Failure to retrieve required column info from localStorage (key=DataTables_cdnServersTable_/):", e);
-				}
-			}
-		});
-	});
-
 };
 
-TableCDNServersController.$inject = ['cdn', 'servers', '$controller', '$scope'];
+TableCDNServersController.$inject = ['cdn', 'servers', 'filter', '$controller', '$scope'];
 module.exports = TableCDNServersController;
diff --git a/traffic_portal/app/src/common/modules/table/cdnServers/table.cdnServers.tpl.html b/traffic_portal/app/src/common/modules/table/cdnServers/table.cdnServers.tpl.html
index 612aed5..ca2cd47 100644
--- a/traffic_portal/app/src/common/modules/table/cdnServers/table.cdnServers.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/cdnServers/table.cdnServers.tpl.html
@@ -20,126 +20,92 @@ under the License.
 <div class="x_panel">
     <div class="x_title">
         <ol class="breadcrumb pull-left">
-            <li><a ng-click="navigateToPath('/cdns')">CDNs</a></li>
-            <li><a ng-click="navigateToPath('/cdns/' + cdn.id)">{{::cdn.name}}</a></li>
+            <li><a href="#!/cdns">CDNs</a></li>
+            <li><a ng-href="#!/cdns/{{cdn.id}}">{{::cdn.name}}</a></li>
             <li class="active">Servers</li>
         </ol>
         <div class="pull-right">
-            <div class="btn-group" role="group" uib-dropdown is-open="queue.isopen">
-                <button type="button" class="btn btn-primary dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
-                    Queue Updates&nbsp;
-                    <span class="caret"></span>
-                </button>
-                <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
-                    <li role="menuitem"><a ng-click="confirmCDNQueueServerUpdates(cdn)">Queue {{cdn.name}} Server Updates</a></li>
-                    <li role="menuitem"><a ng-click="confirmCDNClearServerUpdates(cdn)">Clear {{cdn.name}} Server Updates</a></li>
-                </ul>
-            </div>
-            <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
-            <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
-                <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
-                    <i class="fa fa-columns"></i>&nbsp;
-                    <span class="caret"></span>
-                </button>
-                <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
-                    <li role="menuitem" ng-repeat="c in columns | orderBy:'name'">
-                        <div class="checkbox">
-                            <label><input type="checkbox" ng-model="c.visible" ng-click="toggleVisibility(c.name)"> {{::c.name}}</label>
-                        </div>
-                    </li>
-                </menu>
+            <div class="form-inline" role="search">
+                <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
+                <div class="input-group text-input">
+                    <span class="input-group-addon">
+                        <label for="pageSize">Page size</label>
+                    </span>
+                    <input id="pageSize" name="pageSize" type="number" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
+                </div>
+                <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
+                    <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        <i class="fa fa-columns"></i>&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
+                            <div class="checkbox">
+                                <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
+                            </div>
+                        </li>
+                    </menu>
+                </div>
+                <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
+                    <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        More&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem"><a name="createServerMenuItem" href="#!/servers/new">Create New Server</a></li>
+                        <li class="divider"></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="confirmCDNQueueServerUpdates(null)">Queue Server Updates</button></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="confirmCDNClearServerUpdates(null)">Clear Server Updates</button></li>
+                        <li class="divider"></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearColFilters()">Clear Column Filters</button></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
+                    </ul>
+                </div>
             </div>
         </div>
         <div class="clearfix"></div>
     </div>
     <div class="x_content">
-        <br>
-        <table id="cdnServersTable" class="table responsive-utilities jambo_table">
-            <thead>
-                <tr class="headings">
-                    <th>Cache Group</th>
-                    <th>CDN</th>
-                    <th>Domain</th>
-                    <th>Host</th>
-                    <th>HTTPS Port</th>
-                    <th>ID</th>
-                    <th>ILO IP Address</th>
-                    <th>ILO IP Gateway</th>
-                    <th>ILO IP Netmask</th>
-                    <th>ILO Username</th>
-                    <th>Interface Name</th>
-                    <th>IPv6 Address</th>
-                    <th>IPv6 Gateway</th>
-                    <th>Last Updated</th>
-                    <th>Mgmt IP Address</th>
-                    <th>Mgmt IP Gateway</th>
-                    <th>Mgmt IP Netmask</th>
-                    <th>Network Gateway</th>
-                    <th>Network IP</th>
-                    <th>Network MTU</th>
-                    <th>Network Subnet</th>
-                    <th>Offline Reason</th>
-                    <th>Phys Location</th>
-                    <th>Profile</th>
-                    <th>Rack</th>
-                    <th>Reval Pending</th>
-                    <th>Router Hostname</th>
-                    <th>Router Port Name</th>
-                    <th>Status</th>
-                    <th>TCP Port</th>
-                    <th>Type</th>
-                    <th>Update Pending</th>
-                </tr>
-            </thead>
-            <tbody>
-                <tr ng-click="editServer(s.id)" ng-repeat="s in ::servers" ng-class="::{'active': s.updPending}" context-menu="contextMenuItems">
-                    <td data-search="^{{::s.cachegroup}}$">{{::s.cachegroup}}</td>
-                    <td data-search="^{{::s.cdnName}}$">{{::s.cdnName}}</td>
-                    <td data-search="^{{::s.domainName}}$">{{::s.domainName}}</td>
-                    <td data-search="^{{::s.hostName}}$">{{::s.hostName}}</td>
-                    <td data-search="^{{::s.httpsPort}}$">{{::s.httpsPort}}</td>
-                    <td data-search="^{{::s.id}}$">{{::s.id}}</td>
-                    <td data-search="^{{::s.iloIpAddress}}$"><a ng-click="ssh(s.iloIpAddress, $event)">{{::s.iloIpAddress}}</a></td>
-                    <td data-search="^{{::s.iloIpGateway}}$"><a ng-click="ssh(s.iloIpGateway, $event)">{{::s.iloIpGateway}}</a></td>
-                    <td data-search="^{{::s.iloIpNetmask}}$">{{::s.iloIpNetmask}}</td>
-                    <td data-search="^{{::s.iloUsername}}$">{{::s.iloUsername}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceName}}$">{{::serverNetInfo.get(s.id).interfaceName}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Address}}$">{{::serverNetInfo.get(s.id).ip6Address}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Gateway}}$">{{::serverNetInfo.get(s.id).ip6Gateway}}</td>
-                    <td data-search="^{{::getRelativeTime(s.lastUpdated)}}$" data-order="{{::s.lastUpdated}}">{{::getRelativeTime(s.lastUpdated)}}</td>
-                    <td data-search="^{{::s.mgmtIpAddress}}$"><a ng-click="ssh(s.mgmtIpAddress, $event)">{{::s.mgmtIpAddress}}</a></td>
-                    <td data-search="^{{::s.mgmtIpGateway}}$"><a ng-click="ssh(s.mgmtIpGateway, $event)">{{::s.mgmtIpGateway}}</a></td>
-                    <td data-search="^{{::s.mgmtIpNetmask}}$">{{::s.mgmtIpNetmask}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipGateway}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipGateway, $event)">{{::serverNetInfo.get(s.id).ipGateway}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipAddress}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipAddress, $event)">{{::serverNetInfo.get(s.id).ipAddress}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceMtu}}$">{{::serverNetInfo.get(s.id).interfaceMtu}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipNetmask}}$">{{::serverNetInfo.get(s.id).ipNetmask}}</td>
-                    <td data-search="^{{::s.offlineReason}}$">{{::s.offlineReason}}</td>
-                    <td data-search="^{{::s.physLocation}}$">{{::s.physLocation}}</td>
-                    <td data-search="^{{::s.profile}}$">{{::s.profile}}</td>
-                    <td data-search="^{{::s.rack}}$">{{::s.rack}}</td>
-                    <td data-search="{{(s.revalPending) ? 'RVL' : ''}}" data-order="{{::s.revalPending}}">
-                        <i title="Reval Pending (RVL)" ng-show="s.revalPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Reval Applied" ng-show="!s.revalPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                    <td data-search="^{{::s.routerHostName}}$">{{::s.routerHostName}}</td>
-                    <td data-search="^{{::s.routerPortName}}$">{{::s.routerPortName}}</td>
-                    <td data-search="^{{::s.status}}$">
-                        <span ng-if="!isOffline(s.status)">{{::s.status}}</span>
-                        <span ng-if="isOffline(s.status)" uib-popover="{{::offlineReason(s)}}" popover-title="Offline Reason" popover-trigger="mouseenter" popover-placement="bottom" popover-append-to-body="true">{{::s.status}}</span>
-                    </td>
-                    <td data-search="^{{::s.tcpPort}}$">{{::s.tcpPort}}</td>
-                    <td data-search="^{{::s.type}}$">{{::s.type}}</td>
-                    <td data-search="{{(s.updPending) ? 'UPD' : ''}}" data-order="{{::s.updPending}}">
-                        <i title="Updates Pending (UPD)" ng-show="s.updPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Updates Applied" ng-show="!s.updPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                </tr>
-            </tbody>
-        </table>
+        <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
     </div>
 </div>
 
-
-
-
+<menu class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
+    <ul>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}" target="_blank">Open in New Tab</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="http://{{server.hostName}}.{{server.domainName}}" target="_blank">Navigate To Server FQDN</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}">Edit</a>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmDelete(server, $event)">Delete</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmStatusUpdate(server, $event)">Update Status</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="queueServerUpdates(server, $event)" ng-disabled="!isCache(server) || server.updPending">Queue Server Updates</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="clearServerUpdates(server, $event)" ng-disabled="!isCache(server) || !server.updPending">Clear Server Updates</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-if="showCharts">
+            <a ng-href="{{chartsBase}}{{server.hostName}}" target="_blank">Show Charts</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-show="isCache(server)">
+            <a ng-href="#!/servers/{{server.id}}/capabilities">Manage Capabilities</a>
+        </li>
+        <li role="menuitem" ng-show="isEdge(server) || isOrigin(server)">
+            <a ng-href="#!/servers/{{server.id}}/delivery-services">Manage Delivery Services</a>
+        </li>
+    </ul>
+</menu>
diff --git a/traffic_portal/app/src/common/modules/table/deliveryServiceServers/TableDeliveryServiceServersController.js b/traffic_portal/app/src/common/modules/table/deliveryServiceServers/TableDeliveryServiceServersController.js
index 5d0c094..303d5b6 100644
--- a/traffic_portal/app/src/common/modules/table/deliveryServiceServers/TableDeliveryServiceServersController.js
+++ b/traffic_portal/app/src/common/modules/table/deliveryServiceServers/TableDeliveryServiceServersController.js
@@ -17,14 +17,12 @@
  * under the License.
  */
 
-var TableDeliveryServiceServersController = function(deliveryService, servers, $controller, $scope, $uibModal, deliveryServiceService, serverUtils) {
+var TableDeliveryServiceServersController = function(deliveryService, servers, filter, $controller, $scope, $uibModal, deliveryServiceService) {
 
-	// extends the TableParentServersController to inherit common methods
-	angular.extend(this, $controller('TableParentServersController', { servers: servers, $scope: $scope }));
+	// extends the TableServersController to inherit common methods
+	angular.extend(this, $controller('TableServersController', { tableName: 'deliveryServiceServers', servers: servers, filter: filter, $scope: $scope }));
 
-	let dsServersTable;
-
-	var removeServer = function(serverId) {
+	let removeServer = function(serverId) {
 		deliveryServiceService.deleteDeliveryServiceServer($scope.deliveryService.id, serverId)
 			.then(
 				function() {
@@ -35,23 +33,6 @@ var TableDeliveryServiceServersController = function(deliveryService, servers, $
 
 	$scope.deliveryService = deliveryService;
 
-	$scope.isEdge = serverUtils.isEdge;
-
-	$scope.isOrigin = serverUtils.isOrigin;
-
-	// adds some items to the base servers context menu
-	$scope.contextMenuItems.splice(2, 0,
-		{
-			text: 'Unlink Server from Delivery Service',
-			hasBottomDivider: function() {
-				return true;
-			},
-			click: function ($itemScope, evt) {
-				$scope.confirmRemoveServer($itemScope.s, evt);
-			}
-		}
-	);
-
 	$scope.selectServers = function() {
 		var modalInstance = $uibModal.open({
 			templateUrl: 'common/modules/table/deliveryServiceServers/table.assignDSServers.tpl.html',
@@ -86,11 +67,11 @@ var TableDeliveryServiceServersController = function(deliveryService, servers, $
 			$event.stopPropagation(); // this kills the click event so it doesn't trigger anything else
 		}
 
-		var params = {
+		const params = {
 			title: 'Remove Server from Delivery Service?',
 			message: 'Are you sure you want to remove ' + server.hostName + ' from this delivery service?'
 		};
-		var modalInstance = $uibModal.open({
+		const modalInstance = $uibModal.open({
 			templateUrl: 'common/modules/dialog/confirm/dialog.confirm.tpl.html',
 			controller: 'DialogConfirmController',
 			size: 'md',
@@ -107,40 +88,7 @@ var TableDeliveryServiceServersController = function(deliveryService, servers, $
 		});
 	};
 
-	$scope.toggleVisibility = function(colName) {
-		const col = dsServersTable.column(colName + ':name');
-		col.visible(!col.visible());
-		dsServersTable.rows().invalidate().draw();
-	};
-
-	$scope.columnFilterFn = function(column) {
-		if (column.name === 'Action') {
-			return false;
-		}
-		return true;
-	};
-
-	angular.element(document).ready(function () {
-		dsServersTable = $('#dsServersTable').DataTable({
-			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": [],
-			"columnDefs": [
-				{ 'orderable': false, 'targets': 32 }
-			],
-			"columns": $scope.columns.concat([{ "name": "Action", "visible": true, "searchable": false }]),
-			"initComplete": function(settings, json) {
-				try {
-					// need to create the show/hide column checkboxes and bind to the current visibility
-					$scope.columns = JSON.parse(localStorage.getItem('DataTables_dsServersTable_/')).columns;
-				} catch (e) {
-					console.error("Failure to retrieve required column info from localStorage (key=DataTables_dsServersTable_/):", e);
-				}
-			}
-		});
-	});
-
 };
 
-TableDeliveryServiceServersController.$inject = ['deliveryService', 'servers', '$controller', '$scope', '$uibModal', 'deliveryServiceService', 'serverUtils'];
+TableDeliveryServiceServersController.$inject = ['deliveryService', 'servers', 'filter', '$controller', '$scope', '$uibModal', 'deliveryServiceService'];
 module.exports = TableDeliveryServiceServersController;
diff --git a/traffic_portal/app/src/common/modules/table/deliveryServiceServers/table.deliveryServiceServers.tpl.html b/traffic_portal/app/src/common/modules/table/deliveryServiceServers/table.deliveryServiceServers.tpl.html
index 8971623..c0ae775 100644
--- a/traffic_portal/app/src/common/modules/table/deliveryServiceServers/table.deliveryServiceServers.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/deliveryServiceServers/table.deliveryServiceServers.tpl.html
@@ -20,121 +20,95 @@ under the License.
 <div class="x_panel">
     <div class="x_title">
         <ol class="breadcrumb pull-left">
-            <li><a ng-click="navigateToPath('/delivery-services')">Delivery Services</a></li>
-            <li><a name="dsLink" ng-click="navigateToPath('/delivery-services/' + deliveryService.id + '?type=' + deliveryService.type)">{{::deliveryService.xmlId}}</a></li>
+            <li><a href="#!/delivery-services">Delivery Services</a></li>
+            <li><a name="dsLink" ng-href="{{'#!/delivery-services/' + deliveryService.id + '?type=' + deliveryService.type}}">{{::deliveryService.xmlId}}</a></li>
             <li class="active">Servers</li>
         </ol>
         <div class="pull-right">
-            <button ng-if="!deliveryService.topology" name="selectServersBtn" class="btn btn-primary" title="Link Servers to Delivery Service" ng-click="selectServers()"><i class="fa fa-link"></i></button>
-            <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
-            <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
-                <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
-                    <i class="fa fa-columns"></i>&nbsp;
-                    <span class="caret"></span>
-                </button>
-                <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
-                    <li role="menuitem" ng-repeat="c in columns | orderBy:'name' | filter:columnFilterFn">
-                        <div class="checkbox">
-                            <label><input type="checkbox" ng-model="c.visible" ng-click="toggleVisibility(c.name)"> {{::c.name}}</label>
-                        </div>
-                    </li>
-                </menu>
+            <div class="form-inline" role="search">
+                <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
+                <div class="input-group text-input">
+                    <span class="input-group-addon">
+                        <label for="pageSize">Page size</label>
+                    </span>
+                    <input id="pageSize" name="pageSize" type="number" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
+                </div>
+                <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
+                    <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        <i class="fa fa-columns"></i>&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
+                            <div class="checkbox">
+                                <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
+                            </div>
+                        </li>
+                    </menu>
+                </div>
+                <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
+                    <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        More&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem">
+                            <button type="button" name="selectServersMenuItem" title="{{(!deliveryService.topology) ? 'Assign servers to delivery service' : 'Servers cannot be manually assigned to topology-based delivery services'}}" ng-disabled="deliveryService.topology" ng-click="selectServers()">Assign Servers</button>
+                        </li>
+                        <li class="divider"></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearColFilters()">Clear Column Filters</button></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
+                    </ul>
+                </div>
             </div>
         </div>
         <div class="clearfix"></div>
     </div>
     <div class="x_content">
-        <br>
-        <table id="dsServersTable" class="table responsive-utilities jambo_table">
-            <thead>
-                <tr class="headings">
-                    <th>Cache Group</th>
-                    <th>CDN</th>
-                    <th>Domain</th>
-                    <th>Host</th>
-                    <th>HTTPS Port</th>
-                    <th>ID</th>
-                    <th>ILO IP Address</th>
-                    <th>ILO IP Gateway</th>
-                    <th>ILO IP Netmask</th>
-                    <th>ILO Username</th>
-                    <th>Interface Name</th>
-                    <th>IPv6 Address</th>
-                    <th>IPv6 Gateway</th>
-                    <th>Last Updated</th>
-                    <th>Mgmt IP Address</th>
-                    <th>Mgmt IP Gateway</th>
-                    <th>Mgmt IP Netmask</th>
-                    <th>Network Gateway</th>
-                    <th>Network IP</th>
-                    <th>Network MTU</th>
-                    <th>Network Subnet</th>
-                    <th>Offline Reason</th>
-                    <th>Phys Location</th>
-                    <th>Profile</th>
-                    <th>Rack</th>
-                    <th>Reval Pending</th>
-                    <th>Router Hostname</th>
-                    <th>Router Port Name</th>
-                    <th>Status</th>
-                    <th>TCP Port</th>
-                    <th>Type</th>
-                    <th>Update Pending</th>
-                    <th>Action</th>
-                </tr>
-            </thead>
-            <tbody>
-                <tr ng-click="editServer(s.id)" ng-repeat="s in ::servers" ng-class="::{'active': s.updPending}" context-menu="contextMenuItems">
-                    <td data-search="^{{::s.cachegroup}}$">{{::s.cachegroup}}</td>
-                    <td data-search="^{{::s.cdnName}}$">{{::s.cdnName}}</td>
-                    <td data-search="^{{::s.domainName}}$">{{::s.domainName}}</td>
-                    <td data-search="^{{::s.hostName}}$">{{::s.hostName}}</td>
-                    <td data-search="^{{::s.httpsPort}}$">{{::s.httpsPort}}</td>
-                    <td data-search="^{{::s.id}}$">{{::s.id}}</td>
-                    <td data-search="^{{::s.iloIpAddress}}$"><a ng-click="ssh(s.iloIpAddress, $event)">{{::s.iloIpAddress}}</a></td>
-                    <td data-search="^{{::s.iloIpGateway}}$"><a ng-click="ssh(s.iloIpGateway, $event)">{{::s.iloIpGateway}}</a></td>
-                    <td data-search="^{{::s.iloIpNetmask}}$">{{::s.iloIpNetmask}}</td>
-                    <td data-search="^{{::s.iloUsername}}$">{{::s.iloUsername}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceName}}$">{{::serverNetInfo.get(s.id).interfaceName}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Address}}$">{{::serverNetInfo.get(s.id).ip6Address}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Gateway}}$">{{::serverNetInfo.get(s.id).ip6Gateway}}</td>
-                    <td data-search="^{{::getRelativeTime(s.lastUpdated)}}$" data-order="{{::s.lastUpdated}}">{{::getRelativeTime(s.lastUpdated)}}</td>
-                    <td data-search="^{{::s.mgmtIpAddress}}$"><a ng-click="ssh(s.mgmtIpAddress, $event)">{{::s.mgmtIpAddress}}</a></td>
-                    <td data-search="^{{::s.mgmtIpGateway}}$"><a ng-click="ssh(s.mgmtIpGateway, $event)">{{::s.mgmtIpGateway}}</a></td>
-                    <td data-search="^{{::s.mgmtIpNetmask}}$">{{::s.mgmtIpNetmask}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipGateway}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipGateway, $event)">{{::serverNetInfo.get(s.id).ipGateway}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipAddress}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipAddress, $event)">{{::serverNetInfo.get(s.id).ipAddress}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceMtu}}$">{{::serverNetInfo.get(s.id).interfaceMtu}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipNetmask}}$">{{::serverNetInfo.get(s.id).ipNetmask}}</td>
-                    <td data-search="^{{::s.offlineReason}}$">{{::s.offlineReason}}</td>
-                    <td data-search="^{{::s.physLocation}}$">{{::s.physLocation}}</td>
-                    <td data-search="^{{::s.profile}}$">{{::s.profile}}</td>
-                    <td data-search="^{{::s.rack}}$">{{::s.rack}}</td>
-                    <td data-search="{{(s.revalPending) ? 'RVL' : ''}}" data-order="{{::s.revalPending}}">
-                        <i title="Reval Pending (RVL)" ng-show="s.revalPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Reval Applied" ng-show="!s.revalPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                    <td data-search="^{{::s.routerHostName}}$">{{::s.routerHostName}}</td>
-                    <td data-search="^{{::s.routerPortName}}$">{{::s.routerPortName}}</td>
-                    <td data-search="^{{::s.status}}$">
-                        <span ng-if="!isOffline(s.status)">{{::s.status}}</span>
-                        <span ng-if="isOffline(s.status)" uib-popover="{{::offlineReason(s)}}" popover-title="Offline Reason" popover-trigger="mouseenter" popover-placement="bottom" popover-append-to-body="true">{{::s.status}}</span>
-                    </td>
-                    <td data-search="^{{::s.tcpPort}}$">{{::s.tcpPort}}</td>
-                    <td data-search="^{{::s.type}}$">{{::s.type}}</td>
-                    <td data-search="{{(s.updPending) ? 'UPD' : ''}}" data-order="{{::s.updPending}}">
-                        <i title="Updates Pending (UPD)" ng-show="s.updPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Updates Applied" ng-show="!s.updPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                    <td style="text-align: right;">
-                        <button type="button" ng-if="!deliveryService.topology && (isEdge(s) || isOrigin(s))" class="link action-link" title="Unlink Server from Delivery Service" ng-click="confirmRemoveServer(s, $event)"><i class="fa fa-sm fa-chain-broken"></i></button>
-                    </td>
-                </tr>
-            </tbody>
-        </table>
+        <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
     </div>
 </div>
 
-
-
-
+<menu class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
+    <ul>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}" target="_blank">Open in New Tab</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmRemoveServer(server, $event)" ng-disabled="deliveryService.topology">Remove Server from Delivery Service</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="http://{{server.hostName}}.{{server.domainName}}" target="_blank">Navigate To Server FQDN</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}">Edit</a>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmDelete(server, $event)">Delete</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmStatusUpdate(server, $event)">Update Status</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="queueServerUpdates(server, $event)" ng-disabled="!isCache(server) || server.updPending">Queue Server Updates</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="clearServerUpdates(server, $event)" ng-disabled="!isCache(server) || !server.updPending">Clear Server Updates</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-if="showCharts">
+            <a ng-href="{{chartsBase}}{{server.hostName}}" target="_blank">Show Charts</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-show="isCache(server)">
+            <a ng-href="#!/servers/{{server.id}}/capabilities">Manage Capabilities</a>
+        </li>
+        <li role="menuitem" ng-show="isEdge(server) || isOrigin(server)">
+            <a ng-href="#!/servers/{{server.id}}/delivery-services">Manage Delivery Services</a>
+        </li>
+    </ul>
+</menu>
diff --git a/traffic_portal/app/src/common/modules/table/physLocationServers/TablePhysLocationServersController.js b/traffic_portal/app/src/common/modules/table/physLocationServers/TablePhysLocationServersController.js
index f329796..05684e1 100644
--- a/traffic_portal/app/src/common/modules/table/physLocationServers/TablePhysLocationServersController.js
+++ b/traffic_portal/app/src/common/modules/table/physLocationServers/TablePhysLocationServersController.js
@@ -17,39 +17,13 @@
  * under the License.
  */
 
-var TablePhysLocationServersController = function(physLocation, servers, $controller, $scope) {
+var TablePhysLocationServersController = function(physLocation, servers, filter, $controller, $scope) {
 
-	// extends the TableParentServersController to inherit common methods
-	angular.extend(this, $controller('TableParentServersController', { servers: servers, $scope: $scope }));
-
-	let physLocServersTable;
+	// extends the TableServersController to inherit common methods
+	angular.extend(this, $controller('TableServersController', { tableName: 'physLocationServers', servers: servers, filter: filter, $scope: $scope }));
 
 	$scope.physLocation = physLocation;
-
-	$scope.toggleVisibility = function(colName) {
-		const col = physLocServersTable.column(colName + ':name');
-		col.visible(!col.visible());
-		physLocServersTable.rows().invalidate().draw();
-	};
-
-	angular.element(document).ready(function () {
-		physLocServersTable = $('#physLocServersTable').DataTable({
-			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": [],
-			"columns": $scope.columns,
-			"initComplete": function(settings, json) {
-				try {
-					// need to create the show/hide column checkboxes and bind to the current visibility
-					$scope.columns = JSON.parse(localStorage.getItem('DataTables_physLocServersTable_/')).columns;
-				} catch (e) {
-					console.error("Failure to retrieve required column info from localStorage (key=DataTables_physLocServersTable_/):", e);
-				}
-			}
-		});
-	});
-
 };
 
-TablePhysLocationServersController.$inject = ['physLocation', 'servers', '$controller', '$scope'];
+TablePhysLocationServersController.$inject = ['physLocation', 'servers', 'filter', '$controller', '$scope'];
 module.exports = TablePhysLocationServersController;
diff --git a/traffic_portal/app/src/common/modules/table/physLocationServers/table.physLocationServers.tpl.html b/traffic_portal/app/src/common/modules/table/physLocationServers/table.physLocationServers.tpl.html
index d5788f9..2ac6ef1 100644
--- a/traffic_portal/app/src/common/modules/table/physLocationServers/table.physLocationServers.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/physLocationServers/table.physLocationServers.tpl.html
@@ -20,116 +20,89 @@ under the License.
 <div class="x_panel">
     <div class="x_title">
         <ol class="breadcrumb pull-left">
-            <li><a ng-click="navigateToPath('/phys-locations')">Physical Locations</a></li>
-            <li><a ng-click="navigateToPath('/phys-locations/' + physLocation.id)">{{::physLocation.name}}</a></li>
+            <li><a href="#!/phys-locations">Physical Locations</a></li>
+            <li><a ng-href="#!/phys-locations/{{physLocation.id}}">{{::physLocation.name}}</a></li>
             <li class="active">Servers</li>
         </ol>
         <div class="pull-right">
-            <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
-            <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
-                <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
-                    <i class="fa fa-columns"></i>&nbsp;
-                    <span class="caret"></span>
-                </button>
-                <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
-                    <li role="menuitem" ng-repeat="c in columns | orderBy:'name'">
-                        <div class="checkbox">
-                            <label><input type="checkbox" ng-model="c.visible" ng-click="toggleVisibility(c.name)"> {{::c.name}}</label>
-                        </div>
-                    </li>
-                </menu>
+            <div class="form-inline" role="search">
+                <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
+                <div class="input-group text-input">
+                    <span class="input-group-addon">
+                        <label for="pageSize">Page size</label>
+                    </span>
+                    <input id="pageSize" name="pageSize" type="number" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
+                </div>
+                <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
+                    <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        <i class="fa fa-columns"></i>&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
+                            <div class="checkbox">
+                                <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
+                            </div>
+                        </li>
+                    </menu>
+                </div>
+                <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
+                    <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        More&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem"><a name="createServerMenuItem" href="#!/servers/new">Create New Server</a></li>
+                        <li class="divider"></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearColFilters()">Clear Column Filters</button></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
+                    </ul>
+                </div>
             </div>
         </div>
         <div class="clearfix"></div>
     </div>
     <div class="x_content">
-        <br>
-        <table id="physLocServersTable" class="table responsive-utilities jambo_table">
-            <thead>
-                <tr class="headings">
-                    <th>Cache Group</th>
-                    <th>CDN</th>
-                    <th>Domain</th>
-                    <th>Host</th>
-                    <th>HTTPS Port</th>
-                    <th>ID</th>
-                    <th>ILO IP Address</th>
-                    <th>ILO IP Gateway</th>
-                    <th>ILO IP Netmask</th>
-                    <th>ILO Username</th>
-                    <th>Interface Name</th>
-                    <th>IPv6 Address</th>
-                    <th>IPv6 Gateway</th>
-                    <th>Last Updated</th>
-                    <th>Mgmt IP Address</th>
-                    <th>Mgmt IP Gateway</th>
-                    <th>Mgmt IP Netmask</th>
-                    <th>Network Gateway</th>
-                    <th>Network IP</th>
-                    <th>Network MTU</th>
-                    <th>Network Subnet</th>
-                    <th>Offline Reason</th>
-                    <th>Phys Location</th>
-                    <th>Profile</th>
-                    <th>Rack</th>
-                    <th>Reval Pending</th>
-                    <th>Router Hostname</th>
-                    <th>Router Port Name</th>
-                    <th>Status</th>
-                    <th>TCP Port</th>
-                    <th>Type</th>
-                    <th>Update Pending</th>
-                </tr>
-            </thead>
-            <tbody>
-                <tr ng-click="editServer(s.id)" ng-repeat="s in ::servers" ng-class="::{'active': s.updPending}" context-menu="contextMenuItems">
-                    <td data-search="^{{::s.cachegroup}}$">{{::s.cachegroup}}</td>
-                    <td data-search="^{{::s.cdnName}}$">{{::s.cdnName}}</td>
-                    <td data-search="^{{::s.domainName}}$">{{::s.domainName}}</td>
-                    <td data-search="^{{::s.hostName}}$">{{::s.hostName}}</td>
-                    <td data-search="^{{::s.httpsPort}}$">{{::s.httpsPort}}</td>
-                    <td data-search="^{{::s.id}}$">{{::s.id}}</td>
-                    <td data-search="^{{::s.iloIpAddress}}$"><a ng-click="ssh(s.iloIpAddress, $event)">{{::s.iloIpAddress}}</a></td>
-                    <td data-search="^{{::s.iloIpGateway}}$"><a ng-click="ssh(s.iloIpGateway, $event)">{{::s.iloIpGateway}}</a></td>
-                    <td data-search="^{{::s.iloIpNetmask}}$">{{::s.iloIpNetmask}}</td>
-                    <td data-search="^{{::s.iloUsername}}$">{{::s.iloUsername}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceName}}$">{{::serverNetInfo.get(s.id).interfaceName}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Address}}$">{{::serverNetInfo.get(s.id).ip6Address}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Gateway}}$">{{::serverNetInfo.get(s.id).ip6Gateway}}</td>
-                    <td data-search="^{{::getRelativeTime(s.lastUpdated)}}$" data-order="{{::s.lastUpdated}}">{{::getRelativeTime(s.lastUpdated)}}</td>
-                    <td data-search="^{{::s.mgmtIpAddress}}$"><a ng-click="ssh(s.mgmtIpAddress, $event)">{{::s.mgmtIpAddress}}</a></td>
-                    <td data-search="^{{::s.mgmtIpGateway}}$"><a ng-click="ssh(s.mgmtIpGateway, $event)">{{::s.mgmtIpGateway}}</a></td>
-                    <td data-search="^{{::s.mgmtIpNetmask}}$">{{::s.mgmtIpNetmask}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipGateway}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipGateway, $event)">{{::serverNetInfo.get(s.id).ipGateway}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipAddress}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipAddress, $event)">{{::serverNetInfo.get(s.id).ipAddress}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceMtu}}$">{{::serverNetInfo.get(s.id).interfaceMtu}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipNetmask}}$">{{::serverNetInfo.get(s.id).ipNetmask}}</td>
-                    <td data-search="^{{::s.offlineReason}}$">{{::s.offlineReason}}</td>
-                    <td data-search="^{{::s.physLocation}}$">{{::s.physLocation}}</td>
-                    <td data-search="^{{::s.profile}}$">{{::s.profile}}</td>
-                    <td data-search="^{{::s.rack}}$">{{::s.rack}}</td>
-                    <td data-search="{{(s.revalPending) ? 'RVL' : ''}}" data-order="{{::s.revalPending}}">
-                        <i title="Reval Pending (RVL)" ng-show="s.revalPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Reval Applied" ng-show="!s.revalPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                    <td data-search="^{{::s.routerHostName}}$">{{::s.routerHostName}}</td>
-                    <td data-search="^{{::s.routerPortName}}$">{{::s.routerPortName}}</td>
-                    <td data-search="^{{::s.status}}$">
-                        <span ng-if="!isOffline(s.status)">{{::s.status}}</span>
-                        <span ng-if="isOffline(s.status)" uib-popover="{{::offlineReason(s)}}" popover-title="Offline Reason" popover-trigger="mouseenter" popover-placement="bottom" popover-append-to-body="true">{{::s.status}}</span>
-                    </td>
-                    <td data-search="^{{::s.tcpPort}}$">{{::s.tcpPort}}</td>
-                    <td data-search="^{{::s.type}}$">{{::s.type}}</td>
-                    <td data-search="{{(s.updPending) ? 'UPD' : ''}}" data-order="{{::s.updPending}}">
-                        <i title="Updates Pending (UPD)" ng-show="s.updPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Updates Applied" ng-show="!s.updPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                </tr>
-            </tbody>
-        </table>
+        <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
     </div>
 </div>
 
-
-
-
+<menu class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
+    <ul>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}" target="_blank">Open in New Tab</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="http://{{server.hostName}}.{{server.domainName}}" target="_blank">Navigate To Server FQDN</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}">Edit</a>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmDelete(server, $event)">Delete</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmStatusUpdate(server, $event)">Update Status</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="queueServerUpdates(server, $event)" ng-disabled="!isCache(server) || server.updPending">Queue Server Updates</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="clearServerUpdates(server, $event)" ng-disabled="!isCache(server) || !server.updPending">Clear Server Updates</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-if="showCharts">
+            <a ng-href="{{chartsBase}}{{server.hostName}}" target="_blank">Show Charts</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-show="isCache(server)">
+            <a ng-href="#!/servers/{{server.id}}/capabilities">Manage Capabilities</a>
+        </li>
+        <li role="menuitem" ng-show="isEdge(server) || isOrigin(server)">
+            <a ng-href="#!/servers/{{server.id}}/delivery-services">Manage Delivery Services</a>
+        </li>
+    </ul>
+</menu>
diff --git a/traffic_portal/app/src/common/modules/table/profileServers/TableProfileServersController.js b/traffic_portal/app/src/common/modules/table/profileServers/TableProfileServersController.js
index eff77f2..bc174a4 100644
--- a/traffic_portal/app/src/common/modules/table/profileServers/TableProfileServersController.js
+++ b/traffic_portal/app/src/common/modules/table/profileServers/TableProfileServersController.js
@@ -17,39 +17,13 @@
  * under the License.
  */
 
-var TableProfileServersController = function(profile, servers, $controller, $scope) {
+var TableProfileServersController = function(profile, servers, filter, $controller, $scope) {
 
-	// extends the TableParentServersController to inherit common methods
-	angular.extend(this, $controller('TableParentServersController', { servers: servers, $scope: $scope }));
-
-	let profileServersTable;
+	// extends the TableServersController to inherit common methods
+	angular.extend(this, $controller('TableServersController', { tableName: 'profileServers', servers: servers, filter: filter, $scope: $scope }));
 
 	$scope.profile = profile;
-
-	$scope.toggleVisibility = function(colName) {
-		const col = profileServersTable.column(colName + ':name');
-		col.visible(!col.visible());
-		profileServersTable.rows().invalidate().draw();
-	};
-
-	angular.element(document).ready(function () {
-		profileServersTable = $('#profileServersTable').DataTable({
-			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": [],
-			"columns": $scope.columns,
-			"initComplete": function(settings, json) {
-				try {
-					// need to create the show/hide column checkboxes and bind to the current visibility
-					$scope.columns = JSON.parse(localStorage.getItem('DataTables_profileServersTable_/')).columns;
-				} catch (e) {
-					console.error("Failure to retrieve required column info from localStorage (key=DataTables_profileServersTable_/):", e);
-				}
-			}
-		});
-	});
-
 };
 
-TableProfileServersController.$inject = ['profile', 'servers', '$controller', '$scope'];
+TableProfileServersController.$inject = ['profile', 'servers', 'filter', '$controller', '$scope'];
 module.exports = TableProfileServersController;
diff --git a/traffic_portal/app/src/common/modules/table/profileServers/table.profileServers.tpl.html b/traffic_portal/app/src/common/modules/table/profileServers/table.profileServers.tpl.html
index 0711fb2..1a7a63b 100644
--- a/traffic_portal/app/src/common/modules/table/profileServers/table.profileServers.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/profileServers/table.profileServers.tpl.html
@@ -20,113 +20,89 @@ under the License.
 <div class="x_panel">
     <div class="x_title">
         <ol class="breadcrumb pull-left">
-            <li><a ng-click="navigateToPath('/profiles')">Profiles</a></li>
-            <li><a ng-click="navigateToPath('/profiles/' + profile.id)">{{::profile.name}}</a></li>
+            <li><a href="#!/profiles">Profiles</a></li>
+            <li><a ng-href="#!/profiles/{{profile.id}}">{{::profile.name}}</a></li>
             <li class="active">Servers</li>
         </ol>
         <div class="pull-right">
-            <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
-            <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
-                <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
-                    <i class="fa fa-columns"></i>&nbsp;
-                    <span class="caret"></span>
-                </button>
-                <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
-                    <li role="menuitem" ng-repeat="c in columns | orderBy:'name'">
-                        <div class="checkbox">
-                            <label><input type="checkbox" ng-model="c.visible" ng-click="toggleVisibility(c.name)"> {{::c.name}}</label>
-                        </div>
-                    </li>
-                </menu>
+            <div class="form-inline" role="search">
+                <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
+                <div class="input-group text-input">
+                    <span class="input-group-addon">
+                        <label for="pageSize">Page size</label>
+                    </span>
+                    <input id="pageSize" name="pageSize" type="number" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
+                </div>
+                <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
+                    <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        <i class="fa fa-columns"></i>&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
+                            <div class="checkbox">
+                                <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
+                            </div>
+                        </li>
+                    </menu>
+                </div>
+                <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
+                    <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        More&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem"><a name="createServerMenuItem" href="#!/servers/new">Create New Server</a></li>
+                        <li class="divider"></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearColFilters()">Clear Column Filters</button></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
+                    </ul>
+                </div>
             </div>
         </div>
         <div class="clearfix"></div>
     </div>
     <div class="x_content">
-        <br>
-        <table id="profileServersTable" class="table responsive-utilities jambo_table">
-            <thead>
-                <tr class="headings">
-                    <th>Cache Group</th>
-                    <th>CDN</th>
-                    <th>Domain</th>
-                    <th>Host</th>
-                    <th>HTTPS Port</th>
-                    <th>ID</th>
-                    <th>ILO IP Address</th>
-                    <th>ILO IP Gateway</th>
-                    <th>ILO IP Netmask</th>
-                    <th>ILO Username</th>
-                    <th>Interface Name</th>
-                    <th>IPv6 Address</th>
-                    <th>IPv6 Gateway</th>
-                    <th>Last Updated</th>
-                    <th>Mgmt IP Address</th>
-                    <th>Mgmt IP Gateway</th>
-                    <th>Mgmt IP Netmask</th>
-                    <th>Network Gateway</th>
-                    <th>Network IP</th>
-                    <th>Network MTU</th>
-                    <th>Network Subnet</th>
-                    <th>Offline Reason</th>
-                    <th>Phys Location</th>
-                    <th>Profile</th>
-                    <th>Rack</th>
-                    <th>Reval Pending</th>
-                    <th>Router Hostname</th>
-                    <th>Router Port Name</th>
-                    <th>Status</th>
-                    <th>TCP Port</th>
-                    <th>Type</th>
-                    <th>Update Pending</th>
-                </tr>
-            </thead>
-            <tbody>
-                <tr ng-click="editServer(s.id)" ng-repeat="s in ::servers" ng-class="::{'active': s.updPending}" context-menu="contextMenuItems">
-                    <td data-search="^{{::s.cachegroup}}$">{{::s.cachegroup}}</td>
-                    <td data-search="^{{::s.cdnName}}$">{{::s.cdnName}}</td>
-                    <td data-search="^{{::s.domainName}}$">{{::s.domainName}}</td>
-                    <td data-search="^{{::s.hostName}}$">{{::s.hostName}}</td>
-                    <td data-search="^{{::s.httpsPort}}$">{{::s.httpsPort}}</td>
-                    <td data-search="^{{::s.id}}$">{{::s.id}}</td>
-                    <td data-search="^{{::s.iloIpAddress}}$"><a ng-click="ssh(s.iloIpAddress, $event)">{{::s.iloIpAddress}}</a></td>
-                    <td data-search="^{{::s.iloIpGateway}}$"><a ng-click="ssh(s.iloIpGateway, $event)">{{::s.iloIpGateway}}</a></td>
-                    <td data-search="^{{::s.iloIpNetmask}}$">{{::s.iloIpNetmask}}</td>
-                    <td data-search="^{{::s.iloUsername}}$">{{::s.iloUsername}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceName}}$">{{::serverNetInfo.get(s.id).interfaceName}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Address}}$">{{::serverNetInfo.get(s.id).ip6Address}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Gateway}}$">{{::serverNetInfo.get(s.id).ip6Gateway}}</td>
-                    <td data-search="^{{::getRelativeTime(s.lastUpdated)}}$" data-order="{{::s.lastUpdated}}">{{::getRelativeTime(s.lastUpdated)}}</td>
-                    <td data-search="^{{::s.mgmtIpAddress}}$"><a ng-click="ssh(s.mgmtIpAddress, $event)">{{::s.mgmtIpAddress}}</a></td>
-                    <td data-search="^{{::s.mgmtIpGateway}}$"><a ng-click="ssh(s.mgmtIpGateway, $event)">{{::s.mgmtIpGateway}}</a></td>
-                    <td data-search="^{{::s.mgmtIpNetmask}}$">{{::s.mgmtIpNetmask}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipGateway}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipGateway, $event)">{{::serverNetInfo.get(s.id).ipGateway}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipAddress}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipAddress, $event)">{{::serverNetInfo.get(s.id).ipAddress}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceMtu}}$">{{::serverNetInfo.get(s.id).interfaceMtu}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipNetmask}}$">{{::serverNetInfo.get(s.id).ipNetmask}}</td>
-                    <td data-search="^{{::s.offlineReason}}$">{{::s.offlineReason}}</td>
-                    <td data-search="^{{::s.physLocation}}$">{{::s.physLocation}}</td>
-                    <td data-search="^{{::s.profile}}$">{{::s.profile}}</td>
-                    <td data-search="^{{::s.rack}}$">{{::s.rack}}</td>
-                    <td data-search="{{(s.revalPending) ? 'RVL' : ''}}" data-order="{{::s.revalPending}}">
-                        <i title="Reval Pending (RVL)" ng-show="s.revalPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Reval Applied" ng-show="!s.revalPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                    <td data-search="^{{::s.routerHostName}}$">{{::s.routerHostName}}</td>
-                    <td data-search="^{{::s.routerPortName}}$">{{::s.routerPortName}}</td>
-                    <td data-search="^{{::s.status}}$">
-                        <span ng-if="!isOffline(s.status)">{{::s.status}}</span>
-                        <span ng-if="isOffline(s.status)" uib-popover="{{::offlineReason(s)}}" popover-title="Offline Reason" popover-trigger="mouseenter" popover-placement="bottom" popover-append-to-body="true">{{::s.status}}</span>
-                    </td>
-                    <td data-search="^{{::s.tcpPort}}$">{{::s.tcpPort}}</td>
-                    <td data-search="^{{::s.type}}$">{{::s.type}}</td>
-                    <td data-search="{{(s.updPending) ? 'UPD' : ''}}" data-order="{{::s.updPending}}">
-                        <i title="Updates Pending (UPD)" ng-show="s.updPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Updates Applied" ng-show="!s.updPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                </tr>
-            </tbody>
-        </table>
+        <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
     </div>
 </div>
 
+<menu class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
+    <ul>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}" target="_blank">Open in New Tab</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="http://{{server.hostName}}.{{server.domainName}}" target="_blank">Navigate To Server FQDN</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}">Edit</a>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmDelete(server, $event)">Delete</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmStatusUpdate(server, $event)">Update Status</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="queueServerUpdates(server, $event)" ng-disabled="!isCache(server) || server.updPending">Queue Server Updates</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="clearServerUpdates(server, $event)" ng-disabled="!isCache(server) || !server.updPending">Clear Server Updates</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-if="showCharts">
+            <a ng-href="{{chartsBase}}{{server.hostName}}" target="_blank">Show Charts</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-show="isCache(server)">
+            <a ng-href="#!/servers/{{server.id}}/capabilities">Manage Capabilities</a>
+        </li>
+        <li role="menuitem" ng-show="isEdge(server) || isOrigin(server)">
+            <a ng-href="#!/servers/{{server.id}}/delivery-services">Manage Delivery Services</a>
+        </li>
+    </ul>
+</menu>
diff --git a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js
index 1afca89..7911132 100644
--- a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js
+++ b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js
@@ -17,10 +17,7 @@
  * under the License.
  */
 
-var TableServerCapabilityServersController = function(serverCapability, servers, $scope, $state, $controller, $uibModal, $window, locationUtils, serverService, messageModel) {
-
-	// extends the TableParentServersController to inherit common methods
-	angular.extend(this, $controller('TableParentServersController', { servers: servers, $scope: $scope }));
+var TableServerCapabilityServersController = function(serverCapability, servers, $scope, $state, $uibModal, $window, locationUtils, serverService, messageModel) {
 
 	var removeCapability = function(serverId) {
 		serverService.removeServerCapability(serverId, serverCapability.name)
@@ -32,6 +29,8 @@ var TableServerCapabilityServersController = function(serverCapability, servers,
 			);
 	};
 
+	$scope.servers = servers;
+
 	$scope.serverCapability = serverCapability;
 
 	$scope.contextMenuItems = [
@@ -63,6 +62,10 @@ var TableServerCapabilityServersController = function(serverCapability, servers,
 		}
 	];
 
+	$scope.editServer = function(id) {
+		locationUtils.navigateToPath('/servers/' + id);
+	};
+
 	$scope.confirmRemoveCapability = function(serverId, $event) {
 		if ($event) {
 			$event.stopPropagation(); // this kills the click event so it doesn't trigger anything else
@@ -87,6 +90,10 @@ var TableServerCapabilityServersController = function(serverCapability, servers,
 		});
 	};
 
+	$scope.refresh = function() {
+		$state.reload(); // reloads all the resolves for the view
+	};
+
 	angular.element(document).ready(function () {
 		$('#serverCapabilityServersTable').dataTable({
 			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
@@ -97,5 +104,5 @@ var TableServerCapabilityServersController = function(serverCapability, servers,
 
 };
 
-TableServerCapabilityServersController.$inject = ['serverCapability', 'servers', '$scope', '$state', '$controller', '$uibModal', '$window', 'locationUtils', 'serverService', 'messageModel'];
+TableServerCapabilityServersController.$inject = ['serverCapability', 'servers', '$scope', '$state', '$uibModal', '$window', 'locationUtils', 'serverService', 'messageModel'];
 module.exports = TableServerCapabilityServersController;
diff --git a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.serverCapabilityServers.tpl.html b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.serverCapabilityServers.tpl.html
index ba3b88a..b85205b 100644
--- a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.serverCapabilityServers.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.serverCapabilityServers.tpl.html
@@ -20,8 +20,8 @@ under the License.
 <div class="x_panel">
     <div class="x_title">
         <ol class="breadcrumb pull-left">
-            <li><a ng-click="navigateToPath('/server-capabilities')">Server Capabilities</a></li>
-            <li><a ng-click="navigateToPath('/server-capabilities/' + serverCapability.name)">{{::serverCapability.name}}</a></li>
+            <li><a href="#!/server-capabilities">Server Capabilities</a></li>
+            <li><a ng-href="#!/server-capabilities/{{serverCapability.name}}">{{::serverCapability.name}}</a></li>
             <li class="active">Servers</li>
         </ol>
         <div class="pull-right">
diff --git a/traffic_portal/app/src/common/modules/table/servers/TableParentServersController.js b/traffic_portal/app/src/common/modules/table/servers/TableParentServersController.js
deleted file mode 100644
index 19796fd..0000000
--- a/traffic_portal/app/src/common/modules/table/servers/TableParentServersController.js
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-var TableParentServersController = function(servers, $scope, $state, $uibModal, $window, dateUtils, locationUtils, serverUtils, cdnService, serverService, statusService, propertiesModel, messageModel) {
-
-	let serversTable;
-
-	var getStatuses = function() {
-		statusService.getStatuses()
-			.then(function(result) {
-				$scope.statuses = result;
-			});
-	};
-
-	var queueServerUpdates = function(server) {
-		serverService.queueServerUpdates(server.id)
-			.then(
-				function() {
-					$scope.refresh();
-				}
-			);
-	};
-
-	var clearServerUpdates = function(server) {
-		serverService.clearServerUpdates(server.id)
-			.then(
-				function() {
-					$scope.refresh();
-				}
-			);
-	};
-
-	var queueCDNServerUpdates = function(cdnId) {
-		cdnService.queueServerUpdates(cdnId)
-			.then(
-				function() {
-					$scope.refresh();
-				}
-			);
-	};
-
-	var clearCDNServerUpdates = function(cdnId) {
-		cdnService.clearServerUpdates(cdnId)
-			.then(
-				function() {
-					$scope.refresh();
-				}
-			);
-	};
-
-	var confirmDelete = function(server) {
-		var params = {
-			title: 'Delete Server: ' + server.hostName,
-			key: server.hostName
-		};
-		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() {
-			deleteServer(server);
-		}, function () {
-			// do nothing
-		});
-	};
-
-	var deleteServer = function(server) {
-		serverService.deleteServer(server.id)
-			.then(function(result) {
-				messageModel.setMessages(result.alerts, false);
-				$scope.refresh();
-			});
-	};
-
-	var confirmStatusUpdate = function(server) {
-		var modalInstance = $uibModal.open({
-			templateUrl: 'common/modules/dialog/select/status/dialog.select.status.tpl.html',
-			controller: 'DialogSelectStatusController',
-			size: 'md',
-			resolve: {
-				server: function() {
-					return server;
-				},
-				statuses: function() {
-					return $scope.statuses;
-				}
-			}
-		});
-		modalInstance.result.then(function(status) {
-			updateStatus(status, server);
-		}, function () {
-			// do nothing
-		});
-	};
-
-	var updateStatus = function(status, server) {
-		serverService.updateStatus(server.id, { status: status.id, offlineReason: status.offlineReason })
-			.then(
-				function(result) {
-					messageModel.setMessages(result.data.alerts, false);
-					$scope.refresh();
-				},
-				function(fault) {
-					messageModel.setMessages(fault.data.alerts, false);
-				}
-			);
-	};
-
-	$scope.servers = servers;
-	$scope.serverNetInfo = new Map(servers.map(function(s){return [s.id, serverUtils.toLegacyIPInfo(s.interfaces)];}));
-
-
-	$scope.columns = [
-		{ "name": "Cache Group", "visible": true, "searchable": true },
-		{ "name": "CDN", "visible": true, "searchable": true },
-		{ "name": "Domain", "visible": true, "searchable": true },
-		{ "name": "Host", "visible": true, "searchable": true },
-		{ "name": "HTTPS Port", "visible": false, "searchable": false },
-		{ "name": "ID", "visible": false, "searchable": false },
-		{ "name": "ILO IP Address", "visible": true, "searchable": true },
-		{ "name": "ILO IP Gateway", "visible": false, "searchable": false },
-		{ "name": "ILO IP Netmask", "visible": false, "searchable": false },
-		{ "name": "ILO Username", "visible": false, "searchable": false },
-		{ "name": "Interface Name", "visible": false, "searchable": false },
-		{ "name": "IPv6 Address", "visible": true, "searchable": true },
-		{ "name": "IPv6 Gateway", "visible": false, "searchable": false },
-		{ "name": "Last Updated", "visible": false, "searchable": false },
-		{ "name": "Mgmt IP Address", "visible": false, "searchable": false },
-		{ "name": "Mgmt IP Gateway", "visible": false, "searchable": false },
-		{ "name": "Mgmt IP Netmask", "visible": false, "searchable": false },
-		{ "name": "Network Gateway", "visible": false, "searchable": false },
-		{ "name": "Network IP", "visible": true, "searchable": true },
-		{ "name": "Network MTU", "visible": false, "searchable": false },
-		{ "name": "Network Subnet", "visible": false, "searchable": false },
-		{ "name": "Offline Reason", "visible": false, "searchable": false },
-		{ "name": "Phys Location", "visible": true, "searchable": true },
-		{ "name": "Profile", "visible": true, "searchable": true },
-		{ "name": "Rack", "visible": false, "searchable": false },
-		{ "name": "Reval Pending", "visible": false, "searchable": false },
-		{ "name": "Router Hostname", "visible": false, "searchable": false },
-		{ "name": "Router Port Name", "visible": false, "searchable": false },
-		{ "name": "Status", "visible": true, "searchable": true },
-		{ "name": "TCP Port", "visible": false, "searchable": false },
-		{ "name": "Type", "visible": true, "searchable": true },
-		{ "name": "Update Pending", "visible": true, "searchable": true }
-	];
-
-	$scope.contextMenuItems = [
-		{
-			text: 'Open in New Tab',
-			click: function ($itemScope) {
-				$window.open('/#!/servers/' + $itemScope.s.id, '_blank');
-			}
-		},
-		null, // Divider
-		{
-			text: 'Navigate to Server FQDN',
-			click: function ($itemScope) {
-				$window.open('http://' + $itemScope.s.hostName + '.' + $itemScope.s.domainName, '_blank');
-			}
-		},
-		null, // Divider
-		{
-			text: 'Edit',
-			click: function ($itemScope) {
-				$scope.editServer($itemScope.s.id);
-			}
-		},
-		{
-			text: 'Delete',
-			click: function ($itemScope) {
-				confirmDelete($itemScope.s);
-			}
-		},
-		null, // Divider
-		{
-			text: 'Update Status',
-			click: function ($itemScope) {
-				confirmStatusUpdate($itemScope.s);
-			}
-		},
-		{
-			text: 'Queue Server Updates',
-			displayed: function ($itemScope) {
-				return serverUtils.isCache($itemScope.s) && !$itemScope.s.updPending;
-			},
-			click: function ($itemScope) {
-				queueServerUpdates($itemScope.s);
-			}
-		},
-		{
-			text: 'Clear Server Updates',
-			displayed: function ($itemScope) {
-				return serverUtils.isCache($itemScope.s) && $itemScope.s.updPending;
-			},
-			click: function ($itemScope) {
-				clearServerUpdates($itemScope.s);
-			}
-		},
-		{
-			text: 'Show Charts',
-			displayed: function () {
-				return propertiesModel.properties.servers.charts.show;
-			},
-			hasBottomDivider: function () {
-				return true;
-			},
-			hasTopDivider: function () {
-				return true;
-			},
-			click: function ($itemScope) {
-				$window.open(propertiesModel.properties.servers.charts.baseUrl + $itemScope.s.hostName, '_blank');
-			}
-		},
-		{
-			text: 'Manage Capabilities',
-			displayed: function ($itemScope) {
-				return serverUtils.isCache($itemScope.s);
-			},
-			hasTopDivider: function () {
-				return true;
-			},
-			click: function ($itemScope) {
-				locationUtils.navigateToPath('/servers/' + $itemScope.s.id + '/capabilities');
-			}
-		},
-		{
-			text: 'Manage Delivery Services',
-			displayed: function ($itemScope) {
-				return serverUtils.isEdge($itemScope.s) || serverUtils.isOrigin($itemScope.s);
-			},
-			hasTopDivider: function ($itemScope) {
-				return !serverUtils.isCache($itemScope.s);
-			},
-			click: function ($itemScope) {
-				locationUtils.navigateToPath('/servers/' + $itemScope.s.id + '/delivery-services');
-			}
-		}
-	];
-
-	$scope.editServer = function(id) {
-		locationUtils.navigateToPath('/servers/' + id);
-	};
-
-	$scope.createServer = function() {
-		locationUtils.navigateToPath('/servers/new');
-	};
-
-	$scope.confirmCDNQueueServerUpdates = function(cdn) {
-		var params;
-		if (cdn) {
-			params = {
-				title: 'Queue Server Updates: ' + cdn.name,
-				message: 'Are you sure you want to queue server updates for all ' + cdn.name + ' servers?'
-			};
-			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() {
-				queueCDNServerUpdates(cdn.id);
-			}, function () {
-				// do nothing
-			});
-		} else {
-			params = {
-				title: 'Queue Server Updates',
-				message: "Please select a CDN"
-			};
-			var modalInstance = $uibModal.open({
-				templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
-				controller: 'DialogSelectController',
-				size: 'md',
-				resolve: {
-					params: function () {
-						return params;
-					},
-					collection: function(cdnService) {
-						return cdnService.getCDNs();
-					}
-				}
-			});
-			modalInstance.result.then(function(cdn) {
-				queueCDNServerUpdates(cdn.id);
-			}, function () {
-				// do nothing
-			});
-		}
-	};
-
-	$scope.confirmCDNClearServerUpdates = function(cdn) {
-		var params;
-		if (cdn) {
-			params = {
-				title: 'Clear Server Updates: ' + cdn.name,
-				message: 'Are you sure you want to clear server updates for all ' + cdn.name + ' servers?'
-			};
-			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() {
-				clearCDNServerUpdates(cdn.id);
-			}, function () {
-				// do nothing
-			});
-
-
-		} else {
-			params = {
-				title: 'Clear Server Updates',
-				message: "Please select a CDN"
-			};
-			var modalInstance = $uibModal.open({
-				templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
-				controller: 'DialogSelectController',
-				size: 'md',
-				resolve: {
-					params: function () {
-						return params;
-					},
-					collection: function(cdnService) {
-						return cdnService.getCDNs();
-					}
-				}
-			});
-			modalInstance.result.then(function(cdn) {
-				clearCDNServerUpdates(cdn.id);
-			}, function () {
-				// do nothing
-			});
-		}
-	};
-
-	$scope.refresh = function() {
-		$state.reload(); // reloads all the resolves for the view
-	};
-
-	$scope.toggleVisibility = function(colName) {
-		const col = serversTable.column(colName + ':name');
-		col.visible(!col.visible());
-		serversTable.rows().invalidate().draw();
-	};
-
-	$scope.ssh = serverUtils.ssh;
-
-	$scope.isOffline = serverUtils.isOffline;
-
-	$scope.offlineReason = serverUtils.offlineReason;
-
-	$scope.getRelativeTime = dateUtils.getRelativeTime;
-
-	$scope.navigateToPath = locationUtils.navigateToPath;
-
-	var init = function () {
-		getStatuses();
-	};
-	init();
-
-	angular.element(document).ready(function () {
-		serversTable = $('#serversTable').DataTable({
-			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": [],
-			"columns": $scope.columns,
-			"initComplete": function(settings, json) {
-				try {
-					// need to create the show/hide column checkboxes and bind to the current visibility
-					$scope.columns = JSON.parse(localStorage.getItem('DataTables_serversTable_/')).columns;
-				} catch (e) {
-					console.error("Failure to retrieve required column info from localStorage (key=DataTables_serversTable_/):", e);
-				}
-			}
-		});
-	});
-
-};
-
-TableParentServersController.$inject = ['servers', '$scope', '$state', '$uibModal', '$window', 'dateUtils', 'locationUtils', 'serverUtils', 'cdnService', 'serverService', 'statusService', 'propertiesModel', 'messageModel'];
-module.exports = TableParentServersController;
diff --git a/traffic_portal/app/src/common/modules/table/servers/TableServersController.js b/traffic_portal/app/src/common/modules/table/servers/TableServersController.js
index 27e3485..10ca342 100644
--- a/traffic_portal/app/src/common/modules/table/servers/TableServersController.js
+++ b/traffic_portal/app/src/common/modules/table/servers/TableServersController.js
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-var TableServersController = function(servers, $scope, $state, $uibModal, $window, dateUtils, locationUtils, serverUtils, cdnService, serverService, statusService, propertiesModel, messageModel, userModel, $document) {
+var TableServersController = function(tableName, servers, filter, $scope, $state, $uibModal, $window, dateUtils, locationUtils, serverUtils, cdnService, serverService, statusService, propertiesModel, messageModel, userModel, $document) {
 	/**** Table cell formatters/renderers ****/
 
 	// browserify can't handle classes...
@@ -314,7 +314,7 @@ var TableServersController = function(servers, $scope, $state, $uibModal, $windo
 		paginationPageSize: $scope.pageSize,
 		rowBuffer: 0,
 		onColumnResized: function(params) {
-			localStorage.setItem("servers_table_columns", JSON.stringify($scope.gridOptions.columnApi.getColumnState()));
+			localStorage.setItem(tableName + "_table_columns", JSON.stringify($scope.gridOptions.columnApi.getColumnState()));
 		},
 		tooltipShowDelay: 500,
 		allowContextMenuWithControlKey: true,
@@ -468,113 +468,65 @@ var TableServersController = function(servers, $scope, $state, $uibModal, $windo
 		);
 	};
 
-	$scope.confirmCDNQueueServerUpdates = function(cdn) {
-		let params;
-		if (cdn) {
-			params = {
-				title: 'Queue Server Updates: ' + cdn.name,
-				message: 'Are you sure you want to queue server updates for all ' + cdn.name + ' servers?'
-			};
-			const 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() {
-				cdnService.queueServerUpdates(cdn.id).then($scope.refresh);
-			}, function () {
-				// this is just a cancel event from closing the dialog, do nothing
-			});
-		} else {
-			params = {
-				title: 'Queue Server Updates',
-				message: "Please select a CDN"
-			};
-			const modalInstance = $uibModal.open({
-				templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
-				controller: 'DialogSelectController',
-				size: 'md',
-				resolve: {
-					params: function () {
-						return params;
-					},
-					collection: function(cdnService) {
-						return cdnService.getCDNs();
-					}
+	$scope.confirmCDNQueueServerUpdates = function() {
+		const params = {
+			title: 'Queue Server Updates',
+			message: "Please select a CDN"
+		};
+		const modalInstance = $uibModal.open({
+			templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
+			controller: 'DialogSelectController',
+			size: 'md',
+			resolve: {
+				params: function () {
+					return params;
+				},
+				collection: function(cdnService) {
+					return cdnService.getCDNs();
 				}
-			});
-			modalInstance.result.then(function(cdn) {
-				cdnService.queueServerUpdates(cdn.id).then($scope.refresh);
-			}, function () {
-				// do nothing
-			});
-		}
+			}
+		});
+		modalInstance.result.then(function(cdn) {
+			cdnService.queueServerUpdates(cdn.id).then($scope.refresh);
+		}, function () {
+			// do nothing
+		});
 	};
 
-	$scope.confirmCDNClearServerUpdates = function(cdn) {
-		let params;
-		if (cdn) {
-			params = {
-				title: 'Clear Server Updates: ' + cdn.name,
-				message: 'Are you sure you want to clear server updates for all ' + cdn.name + ' servers?'
-			};
-			const 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() {
-				cdnService.clearServerUpdates(cdn.id).then($scope.refresh);
-			}, function () {
-				// do nothing
-			});
-
-
-		} else {
-			params = {
-				title: 'Clear Server Updates',
-				message: "Please select a CDN"
-			};
-			const modalInstance = $uibModal.open({
-				templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
-				controller: 'DialogSelectController',
-				size: 'md',
-				resolve: {
-					params: function () {
-						return params;
-					},
-					collection: function(cdnService) {
-						return cdnService.getCDNs();
-					}
+	$scope.confirmCDNClearServerUpdates = function() {
+		const params = {
+			title: 'Clear Server Updates',
+			message: "Please select a CDN"
+		};
+		const modalInstance = $uibModal.open({
+			templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
+			controller: 'DialogSelectController',
+			size: 'md',
+			resolve: {
+				params: function () {
+					return params;
+				},
+				collection: function(cdnService) {
+					return cdnService.getCDNs();
 				}
-			});
-			modalInstance.result.then(function(cdn) {
-				cdnService.clearServerUpdates(cdn.id).then($scope.refresh);
-			}, function () {
-				// do nothing
-			});
-		}
+			}
+		});
+		modalInstance.result.then(function(cdn) {
+			cdnService.clearServerUpdates(cdn.id).then($scope.refresh);
+		}, function () {
+			// do nothing
+		});
 	};
 
 	$scope.onQuickSearchChanged = function() {
 		$scope.gridOptions.api.setQuickFilter($scope.quickSearch);
-		localStorage.setItem("servers_quick_search", $scope.quickSearch);
+		localStorage.setItem(tableName + "_quick_search", $scope.quickSearch);
 	};
 
 	$scope.onPageSizeChanged = function() {
 		const value = Number($scope.pageSize);
 		$scope.gridOptions.api.paginationSetPageSize(value);
-		localStorage.setItem("servers_page_size", value);
+		localStorage.setItem(tableName + "_page_size", value);
 	};
 
 	$scope.clearColFilters = function() {
@@ -585,7 +537,7 @@ var TableServersController = function(servers, $scope, $state, $uibModal, $windo
 	angular.element(document).ready(function () {
 		try {
 			// need to create the show/hide column checkboxes and bind to the current visibility
-			const colstates = JSON.parse(localStorage.getItem("servers_table_columns"));
+			const colstates = JSON.parse(localStorage.getItem(tableName + "_table_columns"));
 			if (colstates) {
 				if (!$scope.gridOptions.columnApi.setColumnState(colstates)) {
 					console.error("Failed to load stored column state: one or more columns not found");
@@ -594,36 +546,38 @@ var TableServersController = function(servers, $scope, $state, $uibModal, $windo
 				$scope.gridOptions.api.sizeColumnsToFit();
 			}
 		} catch (e) {
-			console.error("Failure to retrieve required column info from localStorage (key=servers_table_columns):", e);
+			console.error("Failure to retrieve required column info from localStorage (key=" + tableName + "_table_columns):", e);
 		}
 
 		try {
-			const filterState = JSON.parse(localStorage.getItem("servers_table_filters"));
+			const filterState = JSON.parse(localStorage.getItem(tableName + "_table_filters")) || {};
+			// apply any filter provided to the controller
+			Object.assign(filterState, filter);
 			$scope.gridOptions.api.setFilterModel(filterState);
 		} catch (e) {
 			console.error("Failure to load stored filter state:", e);
 		}
 
 		$scope.gridOptions.api.addEventListener("filterChanged", function() {
-			localStorage.setItem("servers_table_filters", JSON.stringify($scope.gridOptions.api.getFilterModel()));
+			localStorage.setItem(tableName + "_table_filters", JSON.stringify($scope.gridOptions.api.getFilterModel()));
 		});
 
 		try {
-			const sortState = JSON.parse(localStorage.getItem("servers_table_sort"));
+			const sortState = JSON.parse(localStorage.getItem(tableName + "_table_sort"));
 			$scope.gridOptions.api.setSortModel(sortState);
 		} catch (e) {
 			console.error("Failure to load stored sort state:", e);
 		}
 
 		try {
-			$scope.quickSearch = localStorage.getItem("servers_quick_search");
+			$scope.quickSearch = localStorage.getItem(tableName + "_quick_search");
 			$scope.gridOptions.api.setQuickFilter($scope.quickSearch);
 		} catch (e) {
 			console.error("Failure to load stored quick search:", e);
 		}
 
 		try {
-			const ps = localStorage.getItem("servers_page_size");
+			const ps = localStorage.getItem(tableName + "_page_size");
 			if (ps && ps > 0) {
 				$scope.pageSize = Number(ps);
 				$scope.gridOptions.api.paginationSetPageSize($scope.pageSize);
@@ -633,18 +587,18 @@ var TableServersController = function(servers, $scope, $state, $uibModal, $windo
 		}
 
 		$scope.gridOptions.api.addEventListener("sortChanged", function() {
-			localStorage.setItem("servers_table_sort", JSON.stringify($scope.gridOptions.api.getSortModel()));
+			localStorage.setItem(tableName + "_table_sort", JSON.stringify($scope.gridOptions.api.getSortModel()));
 		});
 
 		$scope.gridOptions.api.addEventListener("columnMoved", function() {
-			localStorage.setItem("servers_table_columns", JSON.stringify($scope.gridOptions.columnApi.getColumnState()));
+			localStorage.setItem(tableName + "_table_columns", JSON.stringify($scope.gridOptions.columnApi.getColumnState()));
 		});
 
 		$scope.gridOptions.api.addEventListener("columnVisible", function() {
 			$scope.gridOptions.api.sizeColumnsToFit();
 			try {
 				colStates = $scope.gridOptions.columnApi.getColumnState();
-				localStorage.setItem("servers_table_columns", JSON.stringify(colStates));
+				localStorage.setItem(tableName + "_table_columns", JSON.stringify(colStates));
 			} catch (e) {
 				console.error("Failed to store column defs to local storage:", e);
 			}
@@ -665,5 +619,5 @@ var TableServersController = function(servers, $scope, $state, $uibModal, $windo
 	});
 };
 
-TableServersController.$inject = ['servers', '$scope', '$state', '$uibModal', '$window', 'dateUtils', 'locationUtils', 'serverUtils', 'cdnService', 'serverService', 'statusService', 'propertiesModel', 'messageModel', "userModel", "$document"];
+TableServersController.$inject = ['tableName', 'servers', 'filter', '$scope', '$state', '$uibModal', '$window', 'dateUtils', 'locationUtils', 'serverUtils', 'cdnService', 'serverService', 'statusService', 'propertiesModel', 'messageModel', "userModel", "$document"];
 module.exports = TableServersController;
diff --git a/traffic_portal/app/src/common/modules/table/servers/index.js b/traffic_portal/app/src/common/modules/table/servers/index.js
index 2b5d9b5..e955714 100644
--- a/traffic_portal/app/src/common/modules/table/servers/index.js
+++ b/traffic_portal/app/src/common/modules/table/servers/index.js
@@ -18,5 +18,4 @@
  */
 
 module.exports = angular.module('trafficPortal.table.servers', [])
-    .controller('TableServersController', require('./TableServersController'))
-    .controller('TableParentServersController', require('./TableParentServersController'));
+    .controller('TableServersController', require('./TableServersController'));
diff --git a/traffic_portal/app/src/common/modules/table/statusServers/TableStatusServersController.js b/traffic_portal/app/src/common/modules/table/statusServers/TableStatusServersController.js
index b069705..baa71d2 100644
--- a/traffic_portal/app/src/common/modules/table/statusServers/TableStatusServersController.js
+++ b/traffic_portal/app/src/common/modules/table/statusServers/TableStatusServersController.js
@@ -17,39 +17,13 @@
  * under the License.
  */
 
-var TableStatusServersController = function(status, servers, $controller, $scope) {
+var TableStatusServersController = function(status, servers, filter, $controller, $scope) {
 
-	// extends the TableParentServersController to inherit common methods
-	angular.extend(this, $controller('TableParentServersController', { servers: servers, $scope: $scope }));
-
-	let statusServersTable;
+	// extends the TableServersController to inherit common methods
+	angular.extend(this, $controller('TableServersController', { tableName: 'statusServers', servers: servers, filter: filter, $scope: $scope }));
 
 	$scope.status = status;
-
-	$scope.toggleVisibility = function(colName) {
-		const col = statusServersTable.column(colName + ':name');
-		col.visible(!col.visible());
-		statusServersTable.rows().invalidate().draw();
-	};
-
-	angular.element(document).ready(function () {
-		statusServersTable = $('#statusServersTable').DataTable({
-			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": [],
-			"columns": $scope.columns,
-			"initComplete": function(settings, json) {
-				try {
-					// need to create the show/hide column checkboxes and bind to the current visibility
-					$scope.columns = JSON.parse(localStorage.getItem('DataTables_statusServersTable_/')).columns;
-				} catch (e) {
-					console.error("Failure to retrieve required column info from localStorage (key=DataTables_statusServersTable_/):", e);
-				}
-			}
-		});
-	});
-
 };
 
-TableStatusServersController.$inject = ['status', 'servers', '$controller', '$scope'];
+TableStatusServersController.$inject = ['status', 'servers', 'filter', '$controller', '$scope'];
 module.exports = TableStatusServersController;
diff --git a/traffic_portal/app/src/common/modules/table/statusServers/table.statusServers.tpl.html b/traffic_portal/app/src/common/modules/table/statusServers/table.statusServers.tpl.html
index 9975036..a4505a3 100644
--- a/traffic_portal/app/src/common/modules/table/statusServers/table.statusServers.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/statusServers/table.statusServers.tpl.html
@@ -20,113 +20,90 @@ under the License.
 <div class="x_panel">
     <div class="x_title">
         <ol class="breadcrumb pull-left">
-            <li><a ng-click="navigateToPath('/statuses')">Statuses</a></li>
-            <li><a ng-click="navigateToPath('/statuses/' + status.id)">{{::status.name}}</a></li>
+
+            <li><a href="#!/statuses">Statuses</a></li>
+            <li><a ng-href="#!/statuses/{{status.id}}">{{::status.name}}</a></li>
             <li class="active">Servers</li>
         </ol>
         <div class="pull-right">
-            <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
-            <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
-                <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
-                    <i class="fa fa-columns"></i>&nbsp;
-                    <span class="caret"></span>
-                </button>
-                <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
-                    <li role="menuitem" ng-repeat="c in columns | orderBy:'name'">
-                        <div class="checkbox">
-                            <label><input type="checkbox" ng-model="c.visible" ng-click="toggleVisibility(c.name)"> {{::c.name}}</label>
-                        </div>
-                    </li>
-                </menu>
+            <div class="form-inline" role="search">
+                <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
+                <div class="input-group text-input">
+                    <span class="input-group-addon">
+                        <label for="pageSize">Page size</label>
+                    </span>
+                    <input id="pageSize" name="pageSize" type="number" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
+                </div>
+                <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
+                    <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        <i class="fa fa-columns"></i>&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
+                            <div class="checkbox">
+                                <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
+                            </div>
+                        </li>
+                    </menu>
+                </div>
+                <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
+                    <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        More&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem"><a name="createServerMenuItem" href="#!/servers/new">Create New Server</a></li>
+                        <li class="divider"></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearColFilters()">Clear Column Filters</button></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
+                    </ul>
+                </div>
             </div>
         </div>
         <div class="clearfix"></div>
     </div>
     <div class="x_content">
-        <br>
-        <table id="statusServersTable" class="table responsive-utilities jambo_table">
-            <thead>
-                <tr class="headings">
-                    <th>Cache Group</th>
-                    <th>CDN</th>
-                    <th>Domain</th>
-                    <th>Host</th>
-                    <th>HTTPS Port</th>
-                    <th>ID</th>
-                    <th>ILO IP Address</th>
-                    <th>ILO IP Gateway</th>
-                    <th>ILO IP Netmask</th>
-                    <th>ILO Username</th>
-                    <th>Interface Name</th>
-                    <th>IPv6 Address</th>
-                    <th>IPv6 Gateway</th>
-                    <th>Last Updated</th>
-                    <th>Mgmt IP Address</th>
-                    <th>Mgmt IP Gateway</th>
-                    <th>Mgmt IP Netmask</th>
-                    <th>Network Gateway</th>
-                    <th>Network IP</th>
-                    <th>Network MTU</th>
-                    <th>Network Subnet</th>
-                    <th>Offline Reason</th>
-                    <th>Phys Location</th>
-                    <th>Profile</th>
-                    <th>Rack</th>
-                    <th>Reval Pending</th>
-                    <th>Router Hostname</th>
-                    <th>Router Port Name</th>
-                    <th>Status</th>
-                    <th>TCP Port</th>
-                    <th>Type</th>
-                    <th>Update Pending</th>
-                </tr>
-            </thead>
-            <tbody>
-                <tr ng-click="editServer(s.id)" ng-repeat="s in ::servers" ng-class="::{'active': s.updPending}" context-menu="contextMenuItems">
-                    <td data-search="^{{::s.cachegroup}}$">{{::s.cachegroup}}</td>
-                    <td data-search="^{{::s.cdnName}}$">{{::s.cdnName}}</td>
-                    <td data-search="^{{::s.domainName}}$">{{::s.domainName}}</td>
-                    <td data-search="^{{::s.hostName}}$">{{::s.hostName}}</td>
-                    <td data-search="^{{::s.httpsPort}}$">{{::s.httpsPort}}</td>
-                    <td data-search="^{{::s.id}}$">{{::s.id}}</td>
-                    <td data-search="^{{::s.iloIpAddress}}$"><a ng-click="ssh(s.iloIpAddress, $event)">{{::s.iloIpAddress}}</a></td>
-                    <td data-search="^{{::s.iloIpGateway}}$"><a ng-click="ssh(s.iloIpGateway, $event)">{{::s.iloIpGateway}}</a></td>
-                    <td data-search="^{{::s.iloIpNetmask}}$">{{::s.iloIpNetmask}}</td>
-                    <td data-search="^{{::s.iloUsername}}$">{{::s.iloUsername}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceName}}$">{{::serverNetInfo.get(s.id).interfaceName}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Address}}$">{{::serverNetInfo.get(s.id).ip6Address}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Gateway}}$">{{::serverNetInfo.get(s.id).ip6Gateway}}</td>
-                    <td data-search="^{{::getRelativeTime(s.lastUpdated)}}$" data-order="{{::s.lastUpdated}}">{{::getRelativeTime(s.lastUpdated)}}</td>
-                    <td data-search="^{{::s.mgmtIpAddress}}$"><a ng-click="ssh(s.mgmtIpAddress, $event)">{{::s.mgmtIpAddress}}</a></td>
-                    <td data-search="^{{::s.mgmtIpGateway}}$"><a ng-click="ssh(s.mgmtIpGateway, $event)">{{::s.mgmtIpGateway}}</a></td>
-                    <td data-search="^{{::s.mgmtIpNetmask}}$">{{::s.mgmtIpNetmask}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipGateway}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipGateway, $event)">{{::serverNetInfo.get(s.id).ipGateway}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipAddress}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipAddress, $event)">{{::serverNetInfo.get(s.id).ipAddress}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceMtu}}$">{{::serverNetInfo.get(s.id).interfaceMtu}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipNetmask}}$">{{::serverNetInfo.get(s.id).ipNetmask}}</td>
-                    <td data-search="^{{::s.offlineReason}}$">{{::s.offlineReason}}</td>
-                    <td data-search="^{{::s.physLocation}}$">{{::s.physLocation}}</td>
-                    <td data-search="^{{::s.profile}}$">{{::s.profile}}</td>
-                    <td data-search="^{{::s.rack}}$">{{::s.rack}}</td>
-                    <td data-search="{{(s.revalPending) ? 'RVL' : ''}}" data-order="{{::s.revalPending}}">
-                        <i title="Reval Pending (RVL)" ng-show="s.revalPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Reval Applied" ng-show="!s.revalPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                    <td data-search="^{{::s.routerHostName}}$">{{::s.routerHostName}}</td>
-                    <td data-search="^{{::s.routerPortName}}$">{{::s.routerPortName}}</td>
-                    <td data-search="^{{::s.status}}$">
-                        <span ng-if="!isOffline(s.status)">{{::s.status}}</span>
-                        <span ng-if="isOffline(s.status)" uib-popover="{{::offlineReason(s)}}" popover-title="Offline Reason" popover-trigger="mouseenter" popover-placement="bottom" popover-append-to-body="true">{{::s.status}}</span>
-                    </td>
-                    <td data-search="^{{::s.tcpPort}}$">{{::s.tcpPort}}</td>
-                    <td data-search="^{{::s.type}}$">{{::s.type}}</td>
-                    <td data-search="{{(s.updPending) ? 'UPD' : ''}}" data-order="{{::s.updPending}}">
-                        <i title="Updates Pending (UPD)" ng-show="s.updPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Updates Applied" ng-show="!s.updPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                </tr>
-            </tbody>
-        </table>
+        <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
     </div>
 </div>
 
+<menu class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
+    <ul>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}" target="_blank">Open in New Tab</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="http://{{server.hostName}}.{{server.domainName}}" target="_blank">Navigate To Server FQDN</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}">Edit</a>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmDelete(server, $event)">Delete</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmStatusUpdate(server, $event)">Update Status</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="queueServerUpdates(server, $event)" ng-disabled="!isCache(server) || server.updPending">Queue Server Updates</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="clearServerUpdates(server, $event)" ng-disabled="!isCache(server) || !server.updPending">Clear Server Updates</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-if="showCharts">
+            <a ng-href="{{chartsBase}}{{server.hostName}}" target="_blank">Show Charts</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-show="isCache(server)">
+            <a ng-href="#!/servers/{{server.id}}/capabilities">Manage Capabilities</a>
+        </li>
+        <li role="menuitem" ng-show="isEdge(server) || isOrigin(server)">
+            <a ng-href="#!/servers/{{server.id}}/delivery-services">Manage Delivery Services</a>
+        </li>
+    </ul>
+</menu>
diff --git a/traffic_portal/app/src/common/modules/table/servers/index.js b/traffic_portal/app/src/common/modules/table/topologyServers/TableTopologyServersController.js
similarity index 61%
copy from traffic_portal/app/src/common/modules/table/servers/index.js
copy to traffic_portal/app/src/common/modules/table/topologyServers/TableTopologyServersController.js
index 2b5d9b5..21e9847 100644
--- a/traffic_portal/app/src/common/modules/table/servers/index.js
+++ b/traffic_portal/app/src/common/modules/table/topologyServers/TableTopologyServersController.js
@@ -17,6 +17,13 @@
  * under the License.
  */
 
-module.exports = angular.module('trafficPortal.table.servers', [])
-    .controller('TableServersController', require('./TableServersController'))
-    .controller('TableParentServersController', require('./TableParentServersController'));
+var TableTopologyServersController = function(topologies, servers, filter, $controller, $scope) {
+
+	// extends the TableServersController to inherit common methods
+	angular.extend(this, $controller('TableServersController', { tableName: 'topologyServers', servers: servers, filter: filter, $scope: $scope }));
+
+	$scope.topology = topologies[0];
+};
+
+TableTopologyServersController.$inject = ['topologies', 'servers', 'filter', '$controller', '$scope'];
+module.exports = TableTopologyServersController;
diff --git a/traffic_portal/app/src/common/modules/table/servers/index.js b/traffic_portal/app/src/common/modules/table/topologyServers/index.js
similarity index 77%
copy from traffic_portal/app/src/common/modules/table/servers/index.js
copy to traffic_portal/app/src/common/modules/table/topologyServers/index.js
index 2b5d9b5..0841a15 100644
--- a/traffic_portal/app/src/common/modules/table/servers/index.js
+++ b/traffic_portal/app/src/common/modules/table/topologyServers/index.js
@@ -1,3 +1,4 @@
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -17,6 +18,5 @@
  * under the License.
  */
 
-module.exports = angular.module('trafficPortal.table.servers', [])
-    .controller('TableServersController', require('./TableServersController'))
-    .controller('TableParentServersController', require('./TableParentServersController'));
+module.exports = angular.module('trafficPortal.table.topologyServers', [])
+	.controller('TableTopologyServersController', require('./TableTopologyServersController'));
diff --git a/traffic_portal/app/src/common/modules/table/topologyServers/table.topologyServers.tpl.html b/traffic_portal/app/src/common/modules/table/topologyServers/table.topologyServers.tpl.html
new file mode 100644
index 0000000..bb36013
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/table/topologyServers/table.topologyServers.tpl.html
@@ -0,0 +1,103 @@
+<!--
+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 href="#!/topologies">Topologies</a></li>
+            <li><a ng-href="#!/topologies/edit?name={{topology.name}}">{{::topology.name}}</a></li>
+            <li class="active">Servers</li>
+        </ol>
+        <div class="pull-right">
+            <div class="form-inline" role="search">
+                <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
+                <div class="input-group text-input">
+                    <span class="input-group-addon">
+                        <label for="pageSize">Page size</label>
+                    </span>
+                    <input id="pageSize" name="pageSize" type="number" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
+                </div>
+                <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
+                    <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        <i class="fa fa-columns"></i>&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
+                            <div class="checkbox">
+                                <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
+                            </div>
+                        </li>
+                    </menu>
+                </div>
+                <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
+                    <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        More&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearColFilters()">Clear Column Filters</button></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+        <div class="clearfix"></div>
+    </div>
+    <div class="x_content">
+        <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
+    </div>
+</div>
+
+<menu class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
+    <ul>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}" target="_blank">Open in New Tab</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="http://{{server.hostName}}.{{server.domainName}}" target="_blank">Navigate To Server FQDN</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}">Edit</a>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmDelete(server, $event)">Delete</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmStatusUpdate(server, $event)">Update Status</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="queueServerUpdates(server, $event)" ng-disabled="!isCache(server) || server.updPending">Queue Server Updates</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="clearServerUpdates(server, $event)" ng-disabled="!isCache(server) || !server.updPending">Clear Server Updates</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-if="showCharts">
+            <a ng-href="{{chartsBase}}{{server.hostName}}" target="_blank">Show Charts</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-show="isCache(server)">
+            <a ng-href="#!/servers/{{server.id}}/capabilities">Manage Capabilities</a>
+        </li>
+    </ul>
+</menu>
diff --git a/traffic_portal/app/src/common/modules/table/typeServers/TableTypeServersController.js b/traffic_portal/app/src/common/modules/table/typeServers/TableTypeServersController.js
index 2930c9d..50ef3ef 100644
--- a/traffic_portal/app/src/common/modules/table/typeServers/TableTypeServersController.js
+++ b/traffic_portal/app/src/common/modules/table/typeServers/TableTypeServersController.js
@@ -17,39 +17,13 @@
  * under the License.
  */
 
-var TableTypeServersController = function(type, servers, $controller, $scope) {
+var TableTypeServersController = function(type, servers, filter, $controller, $scope) {
 
-	// extends the TableParentServersController to inherit common methods
-	angular.extend(this, $controller('TableParentServersController', { servers: servers, $scope: $scope }));
-
-	let typeServersTable;
+	// extends the TableServersController to inherit common methods
+	angular.extend(this, $controller('TableServersController', { tableName: 'typeServers', servers: servers, filter: filter, $scope: $scope }));
 
 	$scope.type = type;
-
-	$scope.toggleVisibility = function(colName) {
-		const col = typeServersTable.column(colName + ':name');
-		col.visible(!col.visible());
-		typeServersTable.rows().invalidate().draw();
-	};
-
-	angular.element(document).ready(function () {
-		typeServersTable = $('#typeServersTable').DataTable({
-			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
-			"iDisplayLength": 25,
-			"aaSorting": [],
-			"columns": $scope.columns,
-			"initComplete": function(settings, json) {
-				try {
-					// need to create the show/hide column checkboxes and bind to the current visibility
-					$scope.columns = JSON.parse(localStorage.getItem('DataTables_typeServersTable_/')).columns;
-				} catch (e) {
-					console.error("Failure to retrieve required column info from localStorage (key=DataTables_typeServersTable_/):", e);
-				}
-			}
-		});
-	});
-
 };
 
-TableTypeServersController.$inject = ['type', 'servers', '$controller', '$scope'];
+TableTypeServersController.$inject = ['type', 'servers', 'filter', '$controller', '$scope'];
 module.exports = TableTypeServersController;
diff --git a/traffic_portal/app/src/common/modules/table/typeServers/table.typeServers.tpl.html b/traffic_portal/app/src/common/modules/table/typeServers/table.typeServers.tpl.html
index 86128e4..12b3604 100644
--- a/traffic_portal/app/src/common/modules/table/typeServers/table.typeServers.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/typeServers/table.typeServers.tpl.html
@@ -20,113 +20,89 @@ under the License.
 <div class="x_panel">
     <div class="x_title">
         <ol class="breadcrumb pull-left">
-            <li><a ng-click="navigateToPath('/types')">Types</a></li>
-            <li><a ng-click="navigateToPath('/types/' + type.id)">{{::type.name}}</a></li>
+            <li><a href="#!/types">Types</a></li>
+            <li><a ng-href="#!/types/{{type.id}}">{{::type.name}}</a></li>
             <li class="active">Servers</li>
         </ol>
         <div class="pull-right">
-            <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
-            <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
-                <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
-                    <i class="fa fa-columns"></i>&nbsp;
-                    <span class="caret"></span>
-                </button>
-                <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
-                    <li role="menuitem" ng-repeat="c in columns | orderBy:'name'">
-                        <div class="checkbox">
-                            <label><input type="checkbox" ng-model="c.visible" ng-click="toggleVisibility(c.name)"> {{::c.name}}</label>
-                        </div>
-                    </li>
-                </menu>
+            <div class="form-inline" role="search">
+                <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
+                <div class="input-group text-input">
+                    <span class="input-group-addon">
+                        <label for="pageSize">Page size</label>
+                    </span>
+                    <input id="pageSize" name="pageSize" type="number" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
+                </div>
+                <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
+                    <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        <i class="fa fa-columns"></i>&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
+                            <div class="checkbox">
+                                <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
+                            </div>
+                        </li>
+                    </menu>
+                </div>
+                <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
+                    <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+                        More&nbsp;
+                        <span class="caret"></span>
+                    </button>
+                    <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+                        <li role="menuitem"><a name="createServerMenuItem" href="#!/servers/new">Create New Server</a></li>
+                        <li class="divider"></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearColFilters()">Clear Column Filters</button></li>
+                        <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
+                    </ul>
+                </div>
             </div>
         </div>
         <div class="clearfix"></div>
     </div>
     <div class="x_content">
-        <br>
-        <table id="typeServersTable" class="table responsive-utilities jambo_table">
-            <thead>
-                <tr class="headings">
-                    <th>Cache Group</th>
-                    <th>CDN</th>
-                    <th>Domain</th>
-                    <th>Host</th>
-                    <th>HTTPS Port</th>
-                    <th>ID</th>
-                    <th>ILO IP Address</th>
-                    <th>ILO IP Gateway</th>
-                    <th>ILO IP Netmask</th>
-                    <th>ILO Username</th>
-                    <th>Interface Name</th>
-                    <th>IPv6 Address</th>
-                    <th>IPv6 Gateway</th>
-                    <th>Last Updated</th>
-                    <th>Mgmt IP Address</th>
-                    <th>Mgmt IP Gateway</th>
-                    <th>Mgmt IP Netmask</th>
-                    <th>Network Gateway</th>
-                    <th>Network IP</th>
-                    <th>Network MTU</th>
-                    <th>Network Subnet</th>
-                    <th>Offline Reason</th>
-                    <th>Phys Location</th>
-                    <th>Profile</th>
-                    <th>Rack</th>
-                    <th>Reval Pending</th>
-                    <th>Router Hostname</th>
-                    <th>Router Port Name</th>
-                    <th>Status</th>
-                    <th>TCP Port</th>
-                    <th>Type</th>
-                    <th>Update Pending</th>
-                </tr>
-            </thead>
-            <tbody>
-                <tr ng-click="editServer(s.id)" ng-repeat="s in ::servers" ng-class="::{'active': s.updPending}" context-menu="contextMenuItems">
-                    <td data-search="^{{::s.cachegroup}}$">{{::s.cachegroup}}</td>
-                    <td data-search="^{{::s.cdnName}}$">{{::s.cdnName}}</td>
-                    <td data-search="^{{::s.domainName}}$">{{::s.domainName}}</td>
-                    <td data-search="^{{::s.hostName}}$">{{::s.hostName}}</td>
-                    <td data-search="^{{::s.httpsPort}}$">{{::s.httpsPort}}</td>
-                    <td data-search="^{{::s.id}}$">{{::s.id}}</td>
-                    <td data-search="^{{::s.iloIpAddress}}$"><a ng-click="ssh(s.iloIpAddress, $event)">{{::s.iloIpAddress}}</a></td>
-                    <td data-search="^{{::s.iloIpGateway}}$"><a ng-click="ssh(s.iloIpGateway, $event)">{{::s.iloIpGateway}}</a></td>
-                    <td data-search="^{{::s.iloIpNetmask}}$">{{::s.iloIpNetmask}}</td>
-                    <td data-search="^{{::s.iloUsername}}$">{{::s.iloUsername}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceName}}$">{{::serverNetInfo.get(s.id).interfaceName}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Address}}$">{{::serverNetInfo.get(s.id).ip6Address}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ip6Gateway}}$">{{::serverNetInfo.get(s.id).ip6Gateway}}</td>
-                    <td data-search="^{{::getRelativeTime(s.lastUpdated)}}$" data-order="{{::s.lastUpdated}}">{{::getRelativeTime(s.lastUpdated)}}</td>
-                    <td data-search="^{{::s.mgmtIpAddress}}$"><a ng-click="ssh(s.mgmtIpAddress, $event)">{{::s.mgmtIpAddress}}</a></td>
-                    <td data-search="^{{::s.mgmtIpGateway}}$"><a ng-click="ssh(s.mgmtIpGateway, $event)">{{::s.mgmtIpGateway}}</a></td>
-                    <td data-search="^{{::s.mgmtIpNetmask}}$">{{::s.mgmtIpNetmask}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipGateway}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipGateway, $event)">{{::serverNetInfo.get(s.id).ipGateway}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipAddress}}$"><a ng-click="ssh(serverNetInfo.get(s.id).ipAddress, $event)">{{::serverNetInfo.get(s.id).ipAddress}}</a></td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).interfaceMtu}}$">{{::serverNetInfo.get(s.id).interfaceMtu}}</td>
-                    <td data-search="^{{::serverNetInfo.get(s.id).ipNetmask}}$">{{::serverNetInfo.get(s.id).ipNetmask}}</td>
-                    <td data-search="^{{::s.offlineReason}}$">{{::s.offlineReason}}</td>
-                    <td data-search="^{{::s.physLocation}}$">{{::s.physLocation}}</td>
-                    <td data-search="^{{::s.profile}}$">{{::s.profile}}</td>
-                    <td data-search="^{{::s.rack}}$">{{::s.rack}}</td>
-                    <td data-search="{{(s.revalPending) ? 'RVL' : ''}}" data-order="{{::s.revalPending}}">
-                        <i title="Reval Pending (RVL)" ng-show="s.revalPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Reval Applied" ng-show="!s.revalPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                    <td data-search="^{{::s.routerHostName}}$">{{::s.routerHostName}}</td>
-                    <td data-search="^{{::s.routerPortName}}$">{{::s.routerPortName}}</td>
-                    <td data-search="^{{::s.status}}$">
-                        <span ng-if="!isOffline(s.status)">{{::s.status}}</span>
-                        <span ng-if="isOffline(s.status)" uib-popover="{{::offlineReason(s)}}" popover-title="Offline Reason" popover-trigger="mouseenter" popover-placement="bottom" popover-append-to-body="true">{{::s.status}}</span>
-                    </td>
-                    <td data-search="^{{::s.tcpPort}}$">{{::s.tcpPort}}</td>
-                    <td data-search="^{{::s.type}}$">{{::s.type}}</td>
-                    <td data-search="{{(s.updPending) ? 'UPD' : ''}}" data-order="{{::s.updPending}}">
-                        <i title="Updates Pending (UPD)" ng-show="s.updPending" class="fa fa-clock-o fa-lg" aria-hidden="true"></i>
-                        <i title="Updates Applied" ng-show="!s.updPending" class="fa fa-check fa-lg" aria-hidden="true"></i>
-                    </td>
-                </tr>
-            </tbody>
-        </table>
+        <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
     </div>
 </div>
 
+<menu class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
+    <ul>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}" target="_blank">Open in New Tab</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="http://{{server.hostName}}.{{server.domainName}}" target="_blank">Navigate To Server FQDN</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <a ng-href="#!/servers/{{server.id}}">Edit</a>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmDelete(server, $event)">Delete</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem">
+            <button type="button" ng-click="confirmStatusUpdate(server, $event)">Update Status</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="queueServerUpdates(server, $event)" ng-disabled="!isCache(server) || server.updPending">Queue Server Updates</button>
+        </li>
+        <li role="menuitem">
+            <button type="button" ng-click="clearServerUpdates(server, $event)" ng-disabled="!isCache(server) || !server.updPending">Clear Server Updates</button>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-if="showCharts">
+            <a ng-href="{{chartsBase}}{{server.hostName}}" target="_blank">Show Charts</a>
+        </li>
+        <hr class="divider"/>
+        <li role="menuitem" ng-show="isCache(server)">
+            <a ng-href="#!/servers/{{server.id}}/capabilities">Manage Capabilities</a>
+        </li>
+        <li role="menuitem" ng-show="isEdge(server) || isOrigin(server)">
+            <a ng-href="#!/servers/{{server.id}}/delivery-services">Manage Delivery Services</a>
+        </li>
+    </ul>
+</menu>
diff --git a/traffic_portal/app/src/modules/private/cacheGroups/servers/index.js b/traffic_portal/app/src/modules/private/cacheGroups/servers/index.js
index 7f25214..94b491c 100644
--- a/traffic_portal/app/src/modules/private/cacheGroups/servers/index.js
+++ b/traffic_portal/app/src/modules/private/cacheGroups/servers/index.js
@@ -30,8 +30,17 @@ module.exports = angular.module('trafficPortal.private.cacheGroups.servers', [])
 							cacheGroup: function($stateParams, cacheGroupService) {
 								return cacheGroupService.getCacheGroup($stateParams.cacheGroupId);
 							},
-							servers: function($stateParams, serverService) {
-								return serverService.getServers({ cachegroup: $stateParams.cacheGroupId, orderby: 'hostName' });
+							servers: function(cacheGroup, $stateParams, serverService) {
+								return serverService.getServers({ cachegroup: cacheGroup.id, orderby: 'hostName' });
+							},
+							filter: function(cacheGroup) {
+								return {
+									cachegroup: {
+										filterType: "text",
+										type: "equals",
+										filter: cacheGroup.name
+									}
+								}
 							}
 						}
 					}
diff --git a/traffic_portal/app/src/modules/private/cdns/servers/index.js b/traffic_portal/app/src/modules/private/cdns/servers/index.js
index 57e76ee..3db9c0b 100644
--- a/traffic_portal/app/src/modules/private/cdns/servers/index.js
+++ b/traffic_portal/app/src/modules/private/cdns/servers/index.js
@@ -30,8 +30,17 @@ module.exports = angular.module('trafficPortal.private.cdns.servers', [])
 							cdn: function($stateParams, cdnService) {
 								return cdnService.getCDN($stateParams.cdnId);
 							},
-							servers: function($stateParams, serverService) {
-								return serverService.getServers({ cdn: $stateParams.cdnId, orderby: 'hostName' });
+							servers: function(cdn, $stateParams, serverService) {
+								return serverService.getServers({ cdn: cdn.id, orderby: 'hostName' });
+							},
+							filter: function(cdn) {
+								return {
+									cdnName: {
+										filterType: "text",
+										type: "equals",
+										filter: cdn.name
+									}
+								}
 							}
 						}
 					}
diff --git a/traffic_portal/app/src/modules/private/deliveryServices/servers/index.js b/traffic_portal/app/src/modules/private/deliveryServices/servers/index.js
index 8d9712a..f54b518 100644
--- a/traffic_portal/app/src/modules/private/deliveryServices/servers/index.js
+++ b/traffic_portal/app/src/modules/private/deliveryServices/servers/index.js
@@ -36,6 +36,9 @@ module.exports = angular.module('trafficPortal.private.deliveryServices.servers'
 								} else {
 									return serverService.getServers({ dsId: $stateParams.deliveryServiceId });
 								}
+							},
+							filter: function() {
+								return null;
 							}
 						}
 					}
diff --git a/traffic_portal/app/src/modules/private/physLocations/servers/index.js b/traffic_portal/app/src/modules/private/physLocations/servers/index.js
index ac83d64..4d44137 100644
--- a/traffic_portal/app/src/modules/private/physLocations/servers/index.js
+++ b/traffic_portal/app/src/modules/private/physLocations/servers/index.js
@@ -30,8 +30,17 @@ module.exports = angular.module('trafficPortal.private.physLocations.servers', [
 							physLocation: function($stateParams, physLocationService) {
 								return physLocationService.getPhysLocation($stateParams.physLocationId);
 							},
-							servers: function($stateParams, serverService) {
-								return serverService.getServers({ physLocation: $stateParams.physLocationId, orderby: 'hostName' });
+							servers: function(physLocation, $stateParams, serverService) {
+								return serverService.getServers({ physLocation: physLocation.id, orderby: 'hostName' });
+							},
+							filter: function(physLocation) {
+								return {
+									physLocation: {
+										filterType: "text",
+										type: "equals",
+										filter: physLocation.name
+									}
+								}
 							}
 						}
 					}
diff --git a/traffic_portal/app/src/modules/private/profiles/servers/index.js b/traffic_portal/app/src/modules/private/profiles/servers/index.js
index 3dde5eb..2859c13 100644
--- a/traffic_portal/app/src/modules/private/profiles/servers/index.js
+++ b/traffic_portal/app/src/modules/private/profiles/servers/index.js
@@ -30,8 +30,17 @@ module.exports = angular.module('trafficPortal.private.profiles.servers', [])
 							profile: function($stateParams, profileService) {
 								return profileService.getProfile($stateParams.profileId);
 							},
-							servers: function($stateParams, serverService) {
-								return serverService.getServers({ profileId: $stateParams.profileId, orderby: 'hostName' });
+							servers: function(profile, $stateParams, serverService) {
+								return serverService.getServers({ profileId: profile.id, orderby: 'hostName' });
+							},
+							filter: function(profile) {
+								return {
+									profile: {
+										filterType: "text",
+										type: "equals",
+										filter: profile.name
+									}
+								}
 							}
 						}
 					}
diff --git a/traffic_portal/app/src/modules/private/servers/list/index.js b/traffic_portal/app/src/modules/private/servers/list/index.js
index 4025e2a..29fa700 100644
--- a/traffic_portal/app/src/modules/private/servers/list/index.js
+++ b/traffic_portal/app/src/modules/private/servers/list/index.js
@@ -27,8 +27,14 @@ module.exports = angular.module('trafficPortal.private.servers.list', [])
                         templateUrl: 'common/modules/table/servers/table.servers.tpl.html',
                         controller: 'TableServersController',
                         resolve: {
+                            tableName: function() {
+                                return 'servers';
+                            },
                             servers: function(serverService) {
                                 return serverService.getServers({ orderby: 'hostName' });
+                            },
+                            filter: function() {
+                                return null;
                             }
                         }
                     }
diff --git a/traffic_portal/app/src/modules/private/statuses/servers/index.js b/traffic_portal/app/src/modules/private/statuses/servers/index.js
index eacbd6c..4b66688 100644
--- a/traffic_portal/app/src/modules/private/statuses/servers/index.js
+++ b/traffic_portal/app/src/modules/private/statuses/servers/index.js
@@ -32,6 +32,15 @@ module.exports = angular.module('trafficPortal.private.statuses.servers', [])
 							},
 							servers: function(status, serverService) {
 								return serverService.getServers({ status: status.name, orderby: 'hostName' });
+							},
+							filter: function(status) {
+								return {
+									status: {
+										filterType: "text",
+										type: "equals",
+										filter: status.name
+									}
+								}
 							}
 						}
 					}
diff --git a/traffic_portal/app/src/modules/private/profiles/servers/index.js b/traffic_portal/app/src/modules/private/topologies/servers/index.js
similarity index 60%
copy from traffic_portal/app/src/modules/private/profiles/servers/index.js
copy to traffic_portal/app/src/modules/private/topologies/servers/index.js
index 3dde5eb..c2891d1 100644
--- a/traffic_portal/app/src/modules/private/profiles/servers/index.js
+++ b/traffic_portal/app/src/modules/private/topologies/servers/index.js
@@ -17,21 +17,24 @@
  * under the License.
  */
 
-module.exports = angular.module('trafficPortal.private.profiles.servers', [])
+module.exports = angular.module('trafficPortal.private.topologies.servers', [])
 	.config(function($stateProvider, $urlRouterProvider) {
 		$stateProvider
-			.state('trafficPortal.private.profiles.servers', {
-				url: '/{profileId}/servers',
+			.state('trafficPortal.private.topologies.servers', {
+				url: '/servers?name',
 				views: {
-					profilesContent: {
-						templateUrl: 'common/modules/table/profileServers/table.profileServers.tpl.html',
-						controller: 'TableProfileServersController',
+					topologiesContent: {
+						templateUrl: 'common/modules/table/topologyServers/table.topologyServers.tpl.html',
+						controller: 'TableTopologyServersController',
 						resolve: {
-							profile: function($stateParams, profileService) {
-								return profileService.getProfile($stateParams.profileId);
+							topologies: function($stateParams, topologyService) {
+								return topologyService.getTopologies({ name: $stateParams.name });
 							},
-							servers: function($stateParams, serverService) {
-								return serverService.getServers({ profileId: $stateParams.profileId, orderby: 'hostName' });
+							servers: function(topologies, serverService) {
+								return serverService.getServers({ topology: topologies[0].name });
+							},
+							filter: function() {
+								return null;
 							}
 						}
 					}
diff --git a/traffic_portal/app/src/modules/private/types/servers/index.js b/traffic_portal/app/src/modules/private/types/servers/index.js
index 1625b93..4b5021f 100644
--- a/traffic_portal/app/src/modules/private/types/servers/index.js
+++ b/traffic_portal/app/src/modules/private/types/servers/index.js
@@ -32,6 +32,15 @@ module.exports = angular.module('trafficPortal.private.types.servers', [])
 							},
 							servers: function(type, serverService) {
 								return serverService.getServers({ type: type.name, orderby: 'hostName' });
+							},
+							filter: function(type) {
+								return {
+									type: {
+										filterType: "text",
+										type: "equals",
+										filter: type.name
+									}
+								}
 							}
 						}
 					}
diff --git a/traffic_portal/app/src/styles/main.scss b/traffic_portal/app/src/styles/main.scss
index 6f10a5f..37dc352 100644
--- a/traffic_portal/app/src/styles/main.scss
+++ b/traffic_portal/app/src/styles/main.scss
@@ -95,6 +95,24 @@ body.nav-sm .container.body .main-content {
   min-width: 200px;
   left: auto !important; // Reset the default from `.dropdown-menu`
   right: 0 !important;
+
+  button {
+    color: #333333;
+    text-decoration: none;
+    display: block;
+    clear: both;
+    background: transparent;
+    border: none;
+    width: 100%;
+    text-align: inherit;
+    padding: 3px 20px;
+
+    &[disabled] {
+      color: gray;
+      background-color: #f5f5f5;
+    }
+  }
+
 }
 
 .input-error {
diff --git a/traffic_portal/test/end_to_end/deliveryServices/delivery-services-spec.js b/traffic_portal/test/end_to_end/deliveryServices/delivery-services-spec.js
index 54d0f5d..6b9281e 100644
--- a/traffic_portal/test/end_to_end/deliveryServices/delivery-services-spec.js
+++ b/traffic_portal/test/end_to_end/deliveryServices/delivery-services-spec.js
@@ -219,7 +219,8 @@ describe('Traffic Portal Delivery Services Suite', function() {
 		pageData.moreBtn.click();
 		pageData.manageServersMenuItem.click();
 		expect(browser.getCurrentUrl().then(commonFunctions.urlPath)).toMatch(commonFunctions.urlPath(browser.baseUrl)+"#!/delivery-services/[0-9]+/servers");
-		pageData.selectServersBtn.click();
+		pageData.moreBtn.click();
+		pageData.selectServersMenuItem.click();
 		browser.wait(ec.presenceOf(pageData.selectAllCB), 5000);
 		pageData.selectAllCB.click();
 		pageData.selectFormSubmitButton.click();
diff --git a/traffic_portal/test/end_to_end/deliveryServices/pageData.js b/traffic_portal/test/end_to_end/deliveryServices/pageData.js
index 9df8a01..d30ef04 100644
--- a/traffic_portal/test/end_to_end/deliveryServices/pageData.js
+++ b/traffic_portal/test/end_to_end/deliveryServices/pageData.js
@@ -22,7 +22,7 @@ module.exports = function(){
 	this.viewStaticCapabilitiesMenuItem=element(by.css('a[ng-click*=viewStaticDnsEntries]'));
 	this.addCapabilityBtn=element(by.name('addCapabilityBtn'));
 	this.manageServersMenuItem=element(by.css('a[ng-click*=viewServers]'));
-	this.selectServersBtn=element(by.name('selectServersBtn'));
+	this.selectServersMenuItem=element(by.name('selectServersMenuItem'));
 	this.selectAllCB=element(by.id('selectAllCB'));
 	this.dsLink=element(by.name('dsLink'));
 	this.selectFormDropdown=element(by.name('selectFormDropdown'));