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 2019/08/02 15:02:50 UTC

[trafficcontrol] branch master updated: TP: adds the ability to rearrange delivery service table columns as well as toggle column visibility/searchability (#3739)

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 0573362  TP: adds the ability to rearrange delivery service table columns as well as toggle column visibility/searchability (#3739)
0573362 is described below

commit 05733621707c958da7ebd28b830c951332344bb0
Author: Jeremy Mitchell <mi...@users.noreply.github.com>
AuthorDate: Fri Aug 2 09:02:44 2019 -0600

    TP: adds the ability to rearrange delivery service table columns as well as toggle column visibility/searchability (#3739)
    
    * removes the actions column from the ds tables to prep for configurable ds columns (order, search, visiblity)
    
    * adds ability to reorder and toggle visibility/searchability of ds table columns
    
    * adds changelog and documentation updates
    
    * adds a UI test to test hiding a visible ds column
    
    * changes per PR review
    
    * adds overflows for appearance/usability
    
    * leveraging a jquery datatable property to enable horizontal scrolling when too many columns are added.
---
 CHANGELOG.md                                       |   1 +
 .../admin/traffic_portal/images/tp_table_ds.png    | Bin 0 -> 154797 bytes
 .../admin/traffic_portal/usingtrafficportal.rst    | 113 +++++++++------
 .../app/src/common/modules/table/_table.scss       |   3 +-
 .../TableCDNDeliveryServicesController.js          |  29 +++-
 .../table.cdnDeliveryServices.tpl.html             | 157 +++++++++++++++-----
 .../TableDeliveryServicesController.js             | 124 ++++++++++++++--
 .../table.deliveryServices.tpl.html                | 133 ++++++++++++++---
 .../TableProfileDeliveryServicesController.js      |  29 +++-
 .../table.profileDeliveryServices.tpl.html         | 157 +++++++++++++++-----
 .../TableServerDeliveryServicesController.js       |  79 +++++++----
 .../table.serverDeliveryServices.tpl.html          | 158 ++++++++++++++++-----
 .../TableTenantDeliveryServicesController.js       |  29 +++-
 .../table.tenantDeliveryServices.tpl.html          | 157 +++++++++++++++-----
 .../TableTypeDeliveryServicesController.js         |  29 +++-
 .../table.typeDeliveryServices.tpl.html            | 157 +++++++++++++++-----
 .../TableUserDeliveryServicesController.js         |  26 +++-
 .../table.userDeliveryServices.tpl.html            | 157 +++++++++++++++-----
 .../service/application/ApplicationService.js      |   3 +-
 .../common/service/utils/DeliveryServiceUtils.js   |  17 +++
 .../DeliveryServices/delivery-services-spec.js     |  10 ++
 21 files changed, 1244 insertions(+), 324 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f12da5b..0d17ecd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,6 +31,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 - In Traffic Portal, removes the need to specify line breaks using `__RETURN__` in delivery service edge/mid header rewrite rules, regex remap expressions, raw remap text and traffic router additional request/response headers.
 - In Traffic Portal, provides the ability to clone delivery service assignments from one cache to another cache of the same type. Issue #2963.
 - Traffic Ops now allows each delivery service to have a set of query parameter keys to be retained for consistent hash generation by Traffic Router.
+- In Traffic Portal, delivery service table columns can now be rearranged and their visibility toggled on/off as desired by the user. Hidden table columns are excluded from the table search. These settings are persisted in the browser.
 
 ### Changed
 - Traffic Router, added TLS certificate validation on certificates imported from Traffic Ops
diff --git a/docs/source/admin/traffic_portal/images/tp_table_ds.png b/docs/source/admin/traffic_portal/images/tp_table_ds.png
new file mode 100644
index 0000000..b4eae53
Binary files /dev/null and b/docs/source/admin/traffic_portal/images/tp_table_ds.png differ
diff --git a/docs/source/admin/traffic_portal/usingtrafficportal.rst b/docs/source/admin/traffic_portal/usingtrafficportal.rst
index 792f002..8e4a879 100644
--- a/docs/source/admin/traffic_portal/usingtrafficportal.rst
+++ b/docs/source/admin/traffic_portal/usingtrafficportal.rst
@@ -137,55 +137,80 @@ A table showing the results of the periodic :ref:`to-check-ext` that are run. Th
 
 Services
 ========
-:guilabel:`Services` groups the functionality to modify :term:`Delivery Service`\ s - for those users with the necessary permissions - or make Requests for such changes - for uses without necessary permissions.
+:guilabel:`Services` groups the functionality to modify :term:`Delivery Service`\ s - for those users with the necessary permissions - or make Delivery Service Requests for such changes - for users without necessary permissions.
 
-.. figure:: images/tp_table_ds_requests.png
+
+.. figure:: ./images/tp_menu_services.png
 	:align: center
-	:alt: An example table of Delivery Service Requests
+	:alt: The Traffic Portal 'Services' Menu
 
-	Table of Delivery Service Requests
+	The 'Services' Menu
 
 .. _tp-services-delivery-service:
 
-Delivery Service
+Delivery Services
 -----------------
-This page contains a table displaying all :term:`Delivery Service`\ s visible to the user. Each entry in this table has the following fields:
-
-:Key (XML ID): A unique string that identifies this :term:`Delivery Service`
-:Tenant:       The tenant to which the :term:`Delivery Service` is assigned
-:Origin:       The Origin Server's base URL. This includes the protocol (HTTP or HTTPS). Example: ``http://movies.origin.com``
-:Active:       When this is set to 'false', Traffic Router will not serve DNS or HTTP responses for this :term:`Delivery Service`
-:Type:         The type of content routing this :term:`Delivery Service` will use
-
-	.. seealso:: :ref:`ds-types`
-
-:Protocol: The protocol which which this :term:`Delivery Service` serves clients. Its value is one of:
-
-	HTTP
-		Only insecure requests will be serviced
-	HTTPS
-		Only secure requests will be serviced
-	HTTP and HTTPS
-		Both secure and insecure requests will be serviced
-	HTTP to HTTPS
-		Insecure requests will be redirected to secure locations and secure requests are serviced normally
-
-:CDN:                   The CDN to which the :term:`Delivery Service` belongs
-:IPv6 Enabled:          When set to 'true', the Traffic Router will respond to AAAA DNS requests for the routed name of this :term:`Delivery Service`, Otherwise, only A records will be served
-:DSCP:                  The :abbr:`DSCP (Differentiated Services Code Point)` value with which to mark IP packets sent to the client
-:Signing Algorithm:     The algorithm used to sign URLs used by the Delivery Service
-:Query String Handling: Describes how the :term:`Delivery Service` treats query strings. It has one of the following possible values:
+This page contains a table displaying all :term:`Delivery Services` visible to the user as determined by their :term:`Tenant`.
 
-	USE
-		The query string will be used in the :abbr:`ATS (Apache Traffic Server)` `'cache key' <https://docs.trafficserver.apache.org/en/7.1.x/appendices/glossary.en.html#term-cache-key>`_ and is passed in requests to the origin (each unique query string is treated as a unique URL)
-	IGNORE
-		The query string will *not* be used in the :abbr:`ATS (Apache Traffic Server)` `'cache key' <https://docs.trafficserver.apache.org/en/7.1.x/appendices/glossary.en.html#term-cache-key>`_, but *will* be passed in requests to the origin
-	DROP
-		The query string is stripped from the request URL at the Edge-tier cache, and so is not used in the :abbr:`ATS (Apache Traffic Server)` `'cache key' <https://docs.trafficserver.apache.org/en/7.1.x/appendices/glossary.en.html#term-cache-key>`_, and is not passed in requests to the origin
-
-	.. seealso:: :ref:`ds-qstring-handling`
-
-:Last Updated: The time at which the :term:`Delivery Service` was last updated
+.. figure:: images/tp_table_ds.png
+	:align: center
+	:alt: An example table of Delivery Services
+
+	Table of Delivery Services
+
+Use the `Select Columns` menu to select the delivery service columns to view and search. Columns can also be rearranged using drag-and-drop. Available delivery service columns include:
+
+- :ref:`ds-active` (visible by default)
+- :ref:`ds-anonymous-blocking`
+- :ref:`ds-cdn` (visible by default)
+- :ref:`ds-check-path`
+- :ref:`ds-consistent-hashing-qparams`
+- :ref:`ds-consistent-hashing-regex`
+- :ref:`ds-deep-caching`
+- :ref:`ds-display-name`
+- :ref:`ds-dns-bypass-cname`
+- :ref:`ds-dns-bypass-ip`
+- :ref:`ds-dns-bypass-ipv6`
+- :ref:`ds-dns-bypass-ttl`
+- :ref:`ds-dns-ttl`
+- :ref:`ds-dscp` (visible by default)
+- :ref:`ds-edge-header-rw-rules`
+- :ref:`ds-fqpr`
+- :ref:`ds-geo-limit`
+- :ref:`ds-geo-limit-countries`
+- :ref:`ds-geo-limit-redirect-url`
+- :ref:`ds-geo-provider`
+- :ref:`ds-geo-miss-default-latitude`
+- :ref:`ds-geo-miss-default-longitude`
+- :ref:`ds-global-max-mbps`
+- :ref:`ds-global-max-tps`
+- :ref:`ds-http-bypass-fqdn`
+- :ref:`ds-info-url`
+- :ref:`ds-initial-dispersion`
+- :ref:`ds-ipv6-routing` (visible by default)
+- :ref:`ds-longdesc`
+- :ref:`ds-longdesc2`
+- :ref:`ds-longdesc3`
+- :ref:`ds-max-dns-answers`
+- :ref:`ds-max-origin-connections`
+- :ref:`ds-mid-header-rw-rules`
+- :ref:`ds-origin-shield`
+- :ref:`ds-origin-url` (visible by default)
+- :ref:`ds-profile`
+- :ref:`ds-protocol` (visible by default)
+- :ref:`ds-qstring-handling` (visible by default)
+- :ref:`ds-range-request-handling`
+- :ref:`ds-raw-remap`
+- :ref:`ds-regex-remap`
+- :ref:`ds-regionalgeo`
+- :ref:`ds-routing-name`
+- :ref:`ds-signing-algorithm` (visible by default)
+- :ref:`ds-tenant` (visible by default)
+- :ref:`ds-tr-resp-headers`
+- :ref:`ds-tr-req-headers`
+- :ref:`ds-types` (visible by default)
+- :ref:`ds-multi-site-origin`
+- :ref:`ds-xmlid` (visible by default)
 
 :term:`Delivery Service` management includes the ability to (where applicable):
 
@@ -210,6 +235,12 @@ Delivery Service Requests
 -------------------------
 If enabled in the :file:`traffic_portal_properties.json` configuration file, all :term:`Delivery Service` changes (create, update and delete) are captured as a Delivery Service Request and must be reviewed before fulfillment/deployment.
 
+.. figure:: images/tp_table_ds_requests.png
+	:align: center
+	:alt: An example table of Delivery Service Requests
+
+	Table of Delivery Service Requests
+
 :term:`Delivery Service`: A unique string that identifies the :term:`Delivery Service` with which the request is associated. This unique string is also known (and ofter referred to within documentation and source code) as a :term:`Delivery Service` key' or 'XML ID'/'xml_id'/'xmlid'
 :Type:             The type of Delivery Service Request: 'create', 'update', or 'delete' according to what was requested
 :Status:           The status of the Delivery Service Request. Has the following possible values:
diff --git a/traffic_portal/app/src/common/modules/table/_table.scss b/traffic_portal/app/src/common/modules/table/_table.scss
index 73ebf07..6b38f9d 100644
--- a/traffic_portal/app/src/common/modules/table/_table.scss
+++ b/traffic_portal/app/src/common/modules/table/_table.scss
@@ -92,6 +92,7 @@ td span {
     }
 }
 .column-settings {
+    max-height: 300px;
     padding: 10px 20px;
+    overflow-y: auto;
 }
-
diff --git a/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/TableCDNDeliveryServicesController.js b/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/TableCDNDeliveryServicesController.js
index 1e09f7f..ae08579 100644
--- a/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/TableCDNDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/TableCDNDeliveryServicesController.js
@@ -22,16 +22,33 @@ var TableCDNDeliveryServicesController = function(cdn, deliveryServices, $contro
 	// extends the TableDeliveryServicesController to inherit common methods
 	angular.extend(this, $controller('TableDeliveryServicesController', { deliveryServices: deliveryServices, $scope: $scope }));
 
+	let cdnDeliveryServicesTable;
+
 	$scope.cdn = cdn;
 
+	$scope.toggleVisibility = function(colName) {
+		const col = cdnDeliveryServicesTable.column(colName + ':name');
+		col.visible(!col.visible());
+		cdnDeliveryServicesTable.rows().invalidate().draw();
+	};
+
 	angular.element(document).ready(function () {
-		$('#cdnDeliveryServicesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
+		cdnDeliveryServicesTable = $('#cdnDeliveryServicesTable').DataTable({
+			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
 			"iDisplayLength": 25,
-			"columnDefs": [
-				{ 'orderable': false, 'targets': 12 }
-			],
-			"aaSorting": []
+			"aaSorting": [],
+			"columns": $scope.columns,
+			"colReorder": {
+				realtime: 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_cdnDeliveryServicesTable_/')).columns;
+				} catch (e) {
+					console.error("Failure to retrieve required column info from localStorage (key=DataTables_cdnDeliveryServicesTable_/):", e);
+				}
+			}
 		});
 	});
 
diff --git a/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/table.cdnDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/table.cdnDeliveryServices.tpl.html
index d262eb7..f75e754 100644
--- a/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/table.cdnDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/table.cdnDeliveryServices.tpl.html
@@ -26,6 +26,19 @@ under the License.
         </ol>
         <div class="pull-right">
             <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
+            <div 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>
         </div>
         <div class="clearfix"></div>
     </div>
@@ -33,40 +46,120 @@ under the License.
         <br>
         <table id="cdnDeliveryServicesTable" class="table responsive-utilities jambo_table">
             <thead>
-            <tr class="headings">
-                <th>Key (XML ID)</th>
-                <th>Tenant</th>
-                <th>Origin</th>
-                <th>Active</th>
-                <th>Type</th>
-                <th>Protocol</th>
-                <th>CDN</th>
-                <th>IPv6 Enabled</th>
-                <th>DSCP</th>
-                <th>Signing Algorithm</th>
-                <th>Qstring Handling</th>
-                <th>Last Updated</th>
-                <th style="text-align: right;">Actions</th>
-            </tr>
+                <tr class="headings">
+                    <th>Active</th>
+                    <th>Anonymous Blocking</th>
+                    <th>CDN</th>
+                    <th>Check Path</th>
+                    <th>Consistent Hash Query Params</th>
+                    <th>Consistent Hash Regex</th>
+                    <th>Deep Caching Type</th>
+                    <th>Display Name</th>
+                    <th>DNS Bypass CNAME</th>
+                    <th>DNS Bypass IP</th>
+                    <th>DNS Bypass IPv6</th>
+                    <th>DNS Bypass TTL</th>
+                    <th>DNS TTL</th>
+                    <th>DSCP</th>
+                    <th>Edge Header Rewrite Rules</th>
+                    <th>FQ Pacing Rate</th>
+                    <th>Geo Limit</th>
+                    <th>Geo Limit Countries</th>
+                    <th>Geo Limit Redirect URL</th>
+                    <th>Geolocation Provider</th>
+                    <th>Geo Miss Latitude</th>
+                    <th>Geo Miss Longitude</th>
+                    <th>Global Max Mbps</th>
+                    <th>Global Max TPS</th>
+                    <th>HTTP Bypass FQDN</th>
+                    <th>ID</th>
+                    <th>Info URL</th>
+                    <th>Initial Dispersion</th>
+                    <th>IPv6 Routing</th>
+                    <th>Last Updated</th>
+                    <th>Long Desc 1</th>
+                    <th>Long Desc 2</th>
+                    <th>Long Desc 3</th>
+                    <th>Max DNS Answers</th>
+                    <th>Max Origin Connections</th>
+                    <th>Mid Header Rewrite Rules</th>
+                    <th>Multi-Site Origin</th>
+                    <th>Origin Shield</th>
+                    <th>Origin FQDN</th>
+                    <th>Profile</th>
+                    <th>Protocol</th>
+                    <th>Qstring Handling</th>
+                    <th>Range Request Handling</th>
+                    <th>Regex Remap Expression</th>
+                    <th>Regional Geoblocking</th>
+                    <th>Raw Remap Text</th>
+                    <th>Routing Name</th>
+                    <th>Signed</th>
+                    <th>Signing Algorithm</th>
+                    <th>Tenant</th>
+                    <th>TR Request Headers</th>
+                    <th>TR Response Headers</th>
+                    <th>Type</th>
+                    <th>XML ID (Key)</th>
+                </tr>
             </thead>
             <tbody>
-            <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
-                <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
-                <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
-                <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
-                <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
-                <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
-                <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
-                <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
-                <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
-                <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
-                <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
-                <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
-                <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
-                <td style="text-align: right;">
-                    <span ng-if="showChartsButton"><a class="link action-link" title="View Charts" ng-click="openCharts(ds, $event)"><i class="fa fa-sm fa-bar-chart"></i></a></span>
-                </td>
-            </tr>
+                <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
+                    <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
+                    <td data-search="^{{::ds.anonymousBlockingEnabled}}$">{{::ds.anonymousBlockingEnabled}}</td>
+                    <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
+                    <td data-search="^{{::ds.checkPath}}$">{{::ds.checkPath}}</td>
+                    <td data-search="^{{::ds.consistentHashQueryParams}}$">{{::ds.consistentHashQueryParams.join(', ')}}</td>
+                    <td data-search="^{{::ds.consistentHashRegex}}$">{{::ds.consistentHashRegex}}</td>
+                    <td data-search="^{{::ds.deepCachingType}}$">{{::ds.deepCachingType}}</td>
+                    <td data-search="^{{::ds.displayName}}$">{{::ds.displayName}}</td>
+                    <td data-search="^{{::ds.dnsBypassCname}}$">{{::ds.dnsBypassCname}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp}}$">{{::ds.dnsBypassIp}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp6}}$">{{::ds.dnsBypassIp6}}</td>
+                    <td data-search="^{{::ds.dnsBypassTtl}}$">{{::ds.dnsBypassTtl}}</td>
+                    <td data-search="^{{::ds.ccrDnsTtl}}$">{{::ds.ccrDnsTtl}}</td>
+                    <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
+                    <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
+                    <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
+                    <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
+                    <td data-search="^{{::ds.geoLimitRedirectURL}}$">{{::ds.geoLimitRedirectURL}}</td>
+                    <td data-search="^{{::geoProvider(ds)}}$">{{::geoProvider(ds)}}</td>
+                    <td data-search="^{{::ds.missLat}}$">{{::ds.missLat}}</td>
+                    <td data-search="^{{::ds.missLong}}$">{{::ds.missLong}}</td>
+                    <td data-search="^{{::ds.globalMaxMbps}}$">{{::ds.globalMaxMbps}}</td>
+                    <td data-search="^{{::ds.globalMaxTps}}$">{{::ds.globalMaxTps}}</td>
+                    <td data-search="^{{::ds.httpBypassFqdn}}$">{{::ds.httpBypassFqdn}}</td>
+                    <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
+                    <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
+                    <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
+                    <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
+                    <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
+                    <td data-search="^{{::ds.longDesc2}}$">{{::ds.longDesc2}}</td>
+                    <td data-search="^{{::ds.maxDnsAnswers}}$">{{::ds.maxDnsAnswers}}</td>
+                    <td data-search="^{{::ds.maxOriginConnections}}$">{{::ds.maxOriginConnections}}</td>
+                    <td data-search="^{{::ds.midHeaderRewrite}}$">{{::ds.midHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.multiSiteOrigin}}$">{{::ds.multiSiteOrigin}}</td>
+                    <td data-search="^{{::ds.originShield}}$">{{::ds.originShield}}</td>
+                    <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
+                    <td data-search="^{{::ds.profileName}}$">{{::ds.profileName}}</td>
+                    <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
+                    <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
+                    <td data-search="^{{::rrh(ds)}}$">{{::rrh(ds)}}</td>
+                    <td data-search="^{{::ds.regexRemap}}$">{{::ds.regexRemap}}</td>
+                    <td data-search="^{{::ds.regionalGeoBlocking}}$">{{::ds.regionalGeoBlocking}}</td>
+                    <td data-search="^{{::ds.remapText}}$">{{::ds.remapText}}</td>
+                    <td data-search="^{{::ds.routingName}}$">{{::ds.routingName}}</td>
+                    <td data-search="^{{::ds.signed}}$">{{::ds.signed}}</td>
+                    <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
+                    <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
+                    <td data-search="^{{::ds.trResponseHeaders}}$">{{::ds.trResponseHeaders}}</td>
+                    <td data-search="^{{::ds.trRequestHeaders}}$">{{::ds.trRequestHeaders}}</td>
+                    <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
+                    <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
+                </tr>
             </tbody>
         </table>
     </div>
diff --git a/traffic_portal/app/src/common/modules/table/deliveryServices/TableDeliveryServicesController.js b/traffic_portal/app/src/common/modules/table/deliveryServices/TableDeliveryServicesController.js
index 827eecd..57a3b93 100644
--- a/traffic_portal/app/src/common/modules/table/deliveryServices/TableDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/deliveryServices/TableDeliveryServicesController.js
@@ -19,12 +19,22 @@
 
 var TableDeliveryServicesController = function(deliveryServices, $anchorScroll, $scope, $state, $location, $uibModal, $window, deliveryServiceService, deliveryServiceRequestService, dateUtils, deliveryServiceUtils, locationUtils, messageModel, propertiesModel, userModel) {
 
+    let deliveryServicesTable;
+
     var protocols = deliveryServiceUtils.protocols;
 
     var qstrings = deliveryServiceUtils.qstrings;
 
+    var geoProviders = deliveryServiceUtils.geoProviders;
+
+    var geoLimits = deliveryServiceUtils.geoLimits;
+
+    var rrhs = deliveryServiceUtils.rrhs;
+
     var dsRequestsEnabled = propertiesModel.properties.dsRequests.enabled;
 
+    var showCustomCharts = propertiesModel.properties.deliveryServices.charts.customLink.show;
+
     var createDeliveryService = function(typeName) {
         var path = '/delivery-services/new?type=' + typeName;
         locationUtils.navigateToPath(path);
@@ -192,10 +202,6 @@ var TableDeliveryServicesController = function(deliveryServices, $anchorScroll,
 
     $scope.deliveryServices = deliveryServices;
 
-    $scope.showChartsButton = propertiesModel.properties.deliveryServices.charts.customLink.show;
-
-    $scope.openCharts = deliveryServiceUtils.openCharts;
-
     $scope.getRelativeTime = dateUtils.getRelativeTime;
 
     $scope.navigateToPath = locationUtils.navigateToPath;
@@ -206,6 +212,63 @@ var TableDeliveryServicesController = function(deliveryServices, $anchorScroll,
     $scope.PENDING = 3;
     $scope.COMPLETE = 4;
 
+    $scope.columns = [
+        { "name": "Active", "visible": true, "searchable": true },
+        { "name": "Anonymous Blocking", "visible": false, "searchable": false },
+        { "name": "CDN", "visible": true, "searchable": true },
+        { "name": "Check Path", "visible": false, "searchable": false },
+        { "name": "Consistent Hash Query Params", "visible": false, "searchable": false },
+        { "name": "Consistent Hash Regex", "visible": false, "searchable": false },
+        { "name": "Deep Caching Type", "visible": false, "searchable": false },
+        { "name": "Display Name", "visible": false, "searchable": false },
+        { "name": "DNS Bypass CNAME", "visible": false, "searchable": false },
+        { "name": "DNS Bypass IP", "visible": false, "searchable": false },
+        { "name": "DNS Bypass IPv6", "visible": false, "searchable": false },
+        { "name": "DNS Bypass TTL", "visible": false, "searchable": false },
+        { "name": "DNS TTL", "visible": false, "searchable": false },
+        { "name": "DSCP", "visible": true, "searchable": true },
+        { "name": "Edge Header Rewrite Rules", "visible": false, "searchable": false },
+        { "name": "FQ Pacing Rate", "visible": false, "searchable": false },
+        { "name": "Geo Limit", "visible": false, "searchable": false },
+        { "name": "Geo Limit Countries", "visible": false, "searchable": false },
+        { "name": "Geo Limit Redirect URL", "visible": false, "searchable": false },
+        { "name": "Geolocation Provider", "visible": false, "searchable": false },
+        { "name": "Geo Miss Latitude", "visible": false, "searchable": false },
+        { "name": "Geo Miss Longitude", "visible": false, "searchable": false },
+        { "name": "Global Max Mbps", "visible": false, "searchable": false },
+        { "name": "Global Max TPS", "visible": false, "searchable": false },
+        { "name": "HTTP Bypass FQDN", "visible": false, "searchable": false },
+        { "name": "ID", "visible": false, "searchable": false },
+        { "name": "Info URL", "visible": false, "searchable": false },
+        { "name": "Initial Dispersion", "visible": false, "searchable": false },
+        { "name": "IPv6 Routing", "visible": true, "searchable": true },
+        { "name": "Last Updated", "visible": false, "searchable": false },
+        { "name": "Long Desc 1", "visible": false, "searchable": false },
+        { "name": "Long Desc 2", "visible": false, "searchable": false },
+        { "name": "Long Desc 3", "visible": false, "searchable": false },
+        { "name": "Max DNS Answers", "visible": false, "searchable": false },
+        { "name": "Max Origin Connections", "visible": false, "searchable": false },
+        { "name": "Mid Header Rewrite Rules", "visible": false, "searchable": false },
+        { "name": "Multi-Site Origin", "visible": false, "searchable": false },
+        { "name": "Origin Shield", "visible": false, "searchable": false },
+        { "name": "Origin FQDN", "visible": true, "searchable": true },
+        { "name": "Profile", "visible": false, "searchable": false },
+        { "name": "Protocol", "visible": true, "searchable": true },
+        { "name": "Qstring Handling", "visible": true, "searchable": true },
+        { "name": "Range Request Handling", "visible": false, "searchable": false },
+        { "name": "Regex Remap Expression", "visible": false, "searchable": false },
+        { "name": "Regional Geoblocking", "visible": false, "searchable": false },
+        { "name": "Raw Remap Text", "visible": false, "searchable": false },
+        { "name": "Routing Name", "visible": false, "searchable": false },
+        { "name": "Signed", "visible": false, "searchable": false },
+        { "name": "Signing Algorithm", "visible": true, "searchable": true },
+        { "name": "Tenant", "visible": true, "searchable": true },
+        { "name": "TR Request Headers", "visible": false, "searchable": false },
+        { "name": "TR Response Headers", "visible": false, "searchable": false },
+        { "name": "Type", "visible": true, "searchable": true },
+        { "name": "XML ID (Key)", "visible": true, "searchable": true }
+    ];
+
     $scope.contextMenuItems = [
         {
             text: 'Open in New Tab',
@@ -235,10 +298,24 @@ var TableDeliveryServicesController = function(deliveryServices, $anchorScroll,
         null, // Divider
         {
             text: 'View Charts',
+            displayed: function () {
+                // only show if custom ds charts link is NOT configured
+                return !showCustomCharts;
+            },
             click: function ($itemScope) {
                 locationUtils.navigateToPath('/delivery-services/' + $itemScope.ds.id + '/charts?type=' + $itemScope.ds.type);
             }
         },
+        {
+            text: 'View Charts',
+            displayed: function () {
+                // only show if custom ds charts link IS configured
+                return showCustomCharts;
+            },
+            click: function ($itemScope, evt) {
+                deliveryServiceUtils.openCharts($itemScope.ds, evt);
+            }
+        },
         null, // Divider
         {
             text: 'Manage SSL Keys',
@@ -322,6 +399,18 @@ var TableDeliveryServicesController = function(deliveryServices, $anchorScroll,
         return qstrings[ds.qstringIgnore];
     };
 
+    $scope.geoProvider = function(ds) {
+        return geoProviders[ds.geoProvider];
+    };
+
+    $scope.geoLimit = function(ds) {
+        return geoLimits[ds.geoLimit];
+    };
+
+    $scope.rrh = function(ds) {
+        return rrhs[ds.rangeRequestHandling];
+    };
+
     $scope.selectDSType = function() {
         var params = {
             title: 'Create Delivery Service',
@@ -380,14 +469,29 @@ var TableDeliveryServicesController = function(deliveryServices, $anchorScroll,
         });
     };
 
+    $scope.toggleVisibility = function(colName) {
+        const col = deliveryServicesTable.column(colName + ':name');
+        col.visible(!col.visible());
+        deliveryServicesTable.rows().invalidate().draw();
+    };
+
     angular.element(document).ready(function () {
-        $('#deliveryServicesTable').dataTable({
-            "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
+        deliveryServicesTable = $('#deliveryServicesTable').DataTable({
+            "lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
             "iDisplayLength": 25,
-            "columnDefs": [
-                { 'orderable': false, 'targets': 12 }
-            ],
-            "aaSorting": []
+            "aaSorting": [],
+            "columns": $scope.columns,
+            "colReorder": {
+                realtime: 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_deliveryServicesTable_/')).columns;
+                } catch (e) {
+                    console.error("Failure to retrieve required column info from localStorage (key=DataTables_deliveryServicesTable_/):", e);
+                }
+            }
         });
     });
 
diff --git a/traffic_portal/app/src/common/modules/table/deliveryServices/table.deliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/deliveryServices/table.deliveryServices.tpl.html
index c46c65f..6b4a662 100644
--- a/traffic_portal/app/src/common/modules/table/deliveryServices/table.deliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/deliveryServices/table.deliveryServices.tpl.html
@@ -25,6 +25,19 @@ under the License.
         <div class="pull-right" role="group">
             <button class="btn btn-primary" name="createDeliveryServiceButton" title="Create Delivery Service" ng-click="selectDSType()"><i class="fa fa-plus"></i></button>
             <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
+            <div 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>
             <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
                 <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
                     More
@@ -42,38 +55,118 @@ under the License.
         <table id="deliveryServicesTable" class="table responsive-utilities jambo_table">
             <thead>
                 <tr class="headings">
-                    <th>Key (XML ID)</th>
-                    <th>Tenant</th>
-                    <th>Origin</th>
                     <th>Active</th>
-                    <th>Type</th>
-                    <th>Protocol</th>
+                    <th>Anonymous Blocking</th>
                     <th>CDN</th>
-                    <th>IPv6 Enabled</th>
+                    <th>Check Path</th>
+                    <th>Consistent Hash Query Params</th>
+                    <th>Consistent Hash Regex</th>
+                    <th>Deep Caching Type</th>
+                    <th>Display Name</th>
+                    <th>DNS Bypass CNAME</th>
+                    <th>DNS Bypass IP</th>
+                    <th>DNS Bypass IPv6</th>
+                    <th>DNS Bypass TTL</th>
+                    <th>DNS TTL</th>
                     <th>DSCP</th>
-                    <th>Signing Algorithm</th>
-                    <th>Qstring Handling</th>
+                    <th>Edge Header Rewrite Rules</th>
+                    <th>FQ Pacing Rate</th>
+                    <th>Geo Limit</th>
+                    <th>Geo Limit Countries</th>
+                    <th>Geo Limit Redirect URL</th>
+                    <th>Geolocation Provider</th>
+                    <th>Geo Miss Latitude</th>
+                    <th>Geo Miss Longitude</th>
+                    <th>Global Max Mbps</th>
+                    <th>Global Max TPS</th>
+                    <th>HTTP Bypass FQDN</th>
+                    <th>ID</th>
+                    <th>Info URL</th>
+                    <th>Initial Dispersion</th>
+                    <th>IPv6 Routing</th>
                     <th>Last Updated</th>
-                    <th style="text-align: right;">Actions</th>
+                    <th>Long Desc 1</th>
+                    <th>Long Desc 2</th>
+                    <th>Long Desc 3</th>
+                    <th>Max DNS Answers</th>
+                    <th>Max Origin Connections</th>
+                    <th>Mid Header Rewrite Rules</th>
+                    <th>Multi-Site Origin</th>
+                    <th>Origin Shield</th>
+                    <th>Origin FQDN</th>
+                    <th>Profile</th>
+                    <th>Protocol</th>
+                    <th>Qstring Handling</th>
+                    <th>Range Request Handling</th>
+                    <th>Regex Remap Expression</th>
+                    <th>Regional Geoblocking</th>
+                    <th>Raw Remap Text</th>
+                    <th>Routing Name</th>
+                    <th>Signed</th>
+                    <th>Signing Algorithm</th>
+                    <th>Tenant</th>
+                    <th>TR Request Headers</th>
+                    <th>TR Response Headers</th>
+                    <th>Type</th>
+                    <th>XML ID (Key)</th>
                 </tr>
             </thead>
             <tbody>
                 <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
-                    <td name="xmlId" data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
-                    <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
-                    <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
                     <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
-                    <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
-                    <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
+                    <td data-search="^{{::ds.anonymousBlockingEnabled}}$">{{::ds.anonymousBlockingEnabled}}</td>
                     <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
-                    <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::ds.checkPath}}$">{{::ds.checkPath}}</td>
+                    <td data-search="^{{::ds.consistentHashQueryParams}}$">{{::ds.consistentHashQueryParams.join(', ')}}</td>
+                    <td data-search="^{{::ds.consistentHashRegex}}$">{{::ds.consistentHashRegex}}</td>
+                    <td data-search="^{{::ds.deepCachingType}}$">{{::ds.deepCachingType}}</td>
+                    <td data-search="^{{::ds.displayName}}$">{{::ds.displayName}}</td>
+                    <td data-search="^{{::ds.dnsBypassCname}}$">{{::ds.dnsBypassCname}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp}}$">{{::ds.dnsBypassIp}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp6}}$">{{::ds.dnsBypassIp6}}</td>
+                    <td data-search="^{{::ds.dnsBypassTtl}}$">{{::ds.dnsBypassTtl}}</td>
+                    <td data-search="^{{::ds.ccrDnsTtl}}$">{{::ds.ccrDnsTtl}}</td>
                     <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
-                    <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
-                    <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
+                    <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
+                    <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
+                    <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
+                    <td data-search="^{{::ds.geoLimitRedirectURL}}$">{{::ds.geoLimitRedirectURL}}</td>
+                    <td data-search="^{{::geoProvider(ds)}}$">{{::geoProvider(ds)}}</td>
+                    <td data-search="^{{::ds.missLat}}$">{{::ds.missLat}}</td>
+                    <td data-search="^{{::ds.missLong}}$">{{::ds.missLong}}</td>
+                    <td data-search="^{{::ds.globalMaxMbps}}$">{{::ds.globalMaxMbps}}</td>
+                    <td data-search="^{{::ds.globalMaxTps}}$">{{::ds.globalMaxTps}}</td>
+                    <td data-search="^{{::ds.httpBypassFqdn}}$">{{::ds.httpBypassFqdn}}</td>
+                    <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
+                    <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
+                    <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
                     <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
-                    <td style="text-align: right;">
-                        <span ng-if="showChartsButton"><a class="link action-link" title="View Charts" ng-click="openCharts(ds, $event)"><i class="fa fa-sm fa-bar-chart"></i></a></span>
-                    </td>
+                    <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
+                    <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
+                    <td data-search="^{{::ds.longDesc2}}$">{{::ds.longDesc2}}</td>
+                    <td data-search="^{{::ds.maxDnsAnswers}}$">{{::ds.maxDnsAnswers}}</td>
+                    <td data-search="^{{::ds.maxOriginConnections}}$">{{::ds.maxOriginConnections}}</td>
+                    <td data-search="^{{::ds.midHeaderRewrite}}$">{{::ds.midHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.multiSiteOrigin}}$">{{::ds.multiSiteOrigin}}</td>
+                    <td data-search="^{{::ds.originShield}}$">{{::ds.originShield}}</td>
+                    <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
+                    <td data-search="^{{::ds.profileName}}$">{{::ds.profileName}}</td>
+                    <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
+                    <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
+                    <td data-search="^{{::rrh(ds)}}$">{{::rrh(ds)}}</td>
+                    <td data-search="^{{::ds.regexRemap}}$">{{::ds.regexRemap}}</td>
+                    <td data-search="^{{::ds.regionalGeoBlocking}}$">{{::ds.regionalGeoBlocking}}</td>
+                    <td data-search="^{{::ds.remapText}}$">{{::ds.remapText}}</td>
+                    <td data-search="^{{::ds.routingName}}$">{{::ds.routingName}}</td>
+                    <td data-search="^{{::ds.signed}}$">{{::ds.signed}}</td>
+                    <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
+                    <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
+                    <td data-search="^{{::ds.trResponseHeaders}}$">{{::ds.trResponseHeaders}}</td>
+                    <td data-search="^{{::ds.trRequestHeaders}}$">{{::ds.trRequestHeaders}}</td>
+                    <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
+                    <td name="xmlId" data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
                 </tr>
             </tbody>
         </table>
diff --git a/traffic_portal/app/src/common/modules/table/profileDeliveryServices/TableProfileDeliveryServicesController.js b/traffic_portal/app/src/common/modules/table/profileDeliveryServices/TableProfileDeliveryServicesController.js
index 578b0d1..ca7f254 100644
--- a/traffic_portal/app/src/common/modules/table/profileDeliveryServices/TableProfileDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/profileDeliveryServices/TableProfileDeliveryServicesController.js
@@ -22,16 +22,33 @@ var TableProfileDeliveryServicesController = function(profile, deliveryServices,
 	// extends the TableDeliveryServicesController to inherit common methods
 	angular.extend(this, $controller('TableDeliveryServicesController', { deliveryServices: deliveryServices, $scope: $scope }));
 
+	let profileDeliveryServicesTable;
+
 	$scope.profile = profile;
 
+	$scope.toggleVisibility = function(colName) {
+		const col = profileDeliveryServicesTable.column(colName + ':name');
+		col.visible(!col.visible());
+		profileDeliveryServicesTable.rows().invalidate().draw();
+	};
+
 	angular.element(document).ready(function () {
-		$('#profileDeliveryServicesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
+		profileDeliveryServicesTable = $('#profileDeliveryServicesTable').DataTable({
+			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
 			"iDisplayLength": 25,
-			"columnDefs": [
-				{ 'orderable': false, 'targets': 12 }
-			],
-			"aaSorting": []
+			"aaSorting": [],
+			"columns": $scope.columns,
+			"colReorder": {
+				realtime: 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_profileDeliveryServicesTable_/')).columns;
+				} catch (e) {
+					console.error("Failure to retrieve required column info from localStorage (key=DataTables_profileDeliveryServicesTable_/):", e);
+				}
+			}
 		});
 	});
 
diff --git a/traffic_portal/app/src/common/modules/table/profileDeliveryServices/table.profileDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/profileDeliveryServices/table.profileDeliveryServices.tpl.html
index 4acce14..5872b3b 100644
--- a/traffic_portal/app/src/common/modules/table/profileDeliveryServices/table.profileDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/profileDeliveryServices/table.profileDeliveryServices.tpl.html
@@ -26,6 +26,19 @@ under the License.
         </ol>
         <div class="pull-right">
             <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
+            <div 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>
         </div>
         <div class="clearfix"></div>
     </div>
@@ -33,40 +46,120 @@ under the License.
         <br>
         <table id="profileDeliveryServicesTable" class="table responsive-utilities jambo_table">
             <thead>
-            <tr class="headings">
-                <th>Key (XML ID)</th>
-                <th>Tenant</th>
-                <th>Origin</th>
-                <th>Active</th>
-                <th>Type</th>
-                <th>Protocol</th>
-                <th>CDN</th>
-                <th>IPv6 Enabled</th>
-                <th>DSCP</th>
-                <th>Signing Algorithm</th>
-                <th>Qstring Handling</th>
-                <th>Last Updated</th>
-                <th style="text-align: right;">Actions</th>
-            </tr>
+                <tr class="headings">
+                    <th>Active</th>
+                    <th>Anonymous Blocking</th>
+                    <th>CDN</th>
+                    <th>Check Path</th>
+                    <th>Consistent Hash Query Params</th>
+                    <th>Consistent Hash Regex</th>
+                    <th>Deep Caching Type</th>
+                    <th>Display Name</th>
+                    <th>DNS Bypass CNAME</th>
+                    <th>DNS Bypass IP</th>
+                    <th>DNS Bypass IPv6</th>
+                    <th>DNS Bypass TTL</th>
+                    <th>DNS TTL</th>
+                    <th>DSCP</th>
+                    <th>Edge Header Rewrite Rules</th>
+                    <th>FQ Pacing Rate</th>
+                    <th>Geo Limit</th>
+                    <th>Geo Limit Countries</th>
+                    <th>Geo Limit Redirect URL</th>
+                    <th>Geolocation Provider</th>
+                    <th>Geo Miss Latitude</th>
+                    <th>Geo Miss Longitude</th>
+                    <th>Global Max Mbps</th>
+                    <th>Global Max TPS</th>
+                    <th>HTTP Bypass FQDN</th>
+                    <th>ID</th>
+                    <th>Info URL</th>
+                    <th>Initial Dispersion</th>
+                    <th>IPv6 Routing</th>
+                    <th>Last Updated</th>
+                    <th>Long Desc 1</th>
+                    <th>Long Desc 2</th>
+                    <th>Long Desc 3</th>
+                    <th>Max DNS Answers</th>
+                    <th>Max Origin Connections</th>
+                    <th>Mid Header Rewrite Rules</th>
+                    <th>Multi-Site Origin</th>
+                    <th>Origin Shield</th>
+                    <th>Origin FQDN</th>
+                    <th>Profile</th>
+                    <th>Protocol</th>
+                    <th>Qstring Handling</th>
+                    <th>Range Request Handling</th>
+                    <th>Regex Remap Expression</th>
+                    <th>Regional Geoblocking</th>
+                    <th>Raw Remap Text</th>
+                    <th>Routing Name</th>
+                    <th>Signed</th>
+                    <th>Signing Algorithm</th>
+                    <th>Tenant</th>
+                    <th>TR Request Headers</th>
+                    <th>TR Response Headers</th>
+                    <th>Type</th>
+                    <th>XML ID (Key)</th>
+                </tr>
             </thead>
             <tbody>
-            <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
-                <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
-                <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
-                <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
-                <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
-                <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
-                <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
-                <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
-                <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
-                <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
-                <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
-                <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
-                <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
-                <td style="text-align: right;">
-                    <span ng-if="showChartsButton"><a class="link action-link" title="View Charts" ng-click="openCharts(ds, $event)"><i class="fa fa-sm fa-bar-chart"></i></a></span>
-                </td>
-            </tr>
+                <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
+                    <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
+                    <td data-search="^{{::ds.anonymousBlockingEnabled}}$">{{::ds.anonymousBlockingEnabled}}</td>
+                    <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
+                    <td data-search="^{{::ds.checkPath}}$">{{::ds.checkPath}}</td>
+                    <td data-search="^{{::ds.consistentHashQueryParams}}$">{{::ds.consistentHashQueryParams.join(', ')}}</td>
+                    <td data-search="^{{::ds.consistentHashRegex}}$">{{::ds.consistentHashRegex}}</td>
+                    <td data-search="^{{::ds.deepCachingType}}$">{{::ds.deepCachingType}}</td>
+                    <td data-search="^{{::ds.displayName}}$">{{::ds.displayName}}</td>
+                    <td data-search="^{{::ds.dnsBypassCname}}$">{{::ds.dnsBypassCname}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp}}$">{{::ds.dnsBypassIp}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp6}}$">{{::ds.dnsBypassIp6}}</td>
+                    <td data-search="^{{::ds.dnsBypassTtl}}$">{{::ds.dnsBypassTtl}}</td>
+                    <td data-search="^{{::ds.ccrDnsTtl}}$">{{::ds.ccrDnsTtl}}</td>
+                    <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
+                    <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
+                    <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
+                    <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
+                    <td data-search="^{{::ds.geoLimitRedirectURL}}$">{{::ds.geoLimitRedirectURL}}</td>
+                    <td data-search="^{{::geoProvider(ds)}}$">{{::geoProvider(ds)}}</td>
+                    <td data-search="^{{::ds.missLat}}$">{{::ds.missLat}}</td>
+                    <td data-search="^{{::ds.missLong}}$">{{::ds.missLong}}</td>
+                    <td data-search="^{{::ds.globalMaxMbps}}$">{{::ds.globalMaxMbps}}</td>
+                    <td data-search="^{{::ds.globalMaxTps}}$">{{::ds.globalMaxTps}}</td>
+                    <td data-search="^{{::ds.httpBypassFqdn}}$">{{::ds.httpBypassFqdn}}</td>
+                    <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
+                    <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
+                    <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
+                    <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
+                    <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
+                    <td data-search="^{{::ds.longDesc2}}$">{{::ds.longDesc2}}</td>
+                    <td data-search="^{{::ds.maxDnsAnswers}}$">{{::ds.maxDnsAnswers}}</td>
+                    <td data-search="^{{::ds.maxOriginConnections}}$">{{::ds.maxOriginConnections}}</td>
+                    <td data-search="^{{::ds.midHeaderRewrite}}$">{{::ds.midHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.multiSiteOrigin}}$">{{::ds.multiSiteOrigin}}</td>
+                    <td data-search="^{{::ds.originShield}}$">{{::ds.originShield}}</td>
+                    <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
+                    <td data-search="^{{::ds.profileName}}$">{{::ds.profileName}}</td>
+                    <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
+                    <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
+                    <td data-search="^{{::rrh(ds)}}$">{{::rrh(ds)}}</td>
+                    <td data-search="^{{::ds.regexRemap}}$">{{::ds.regexRemap}}</td>
+                    <td data-search="^{{::ds.regionalGeoBlocking}}$">{{::ds.regionalGeoBlocking}}</td>
+                    <td data-search="^{{::ds.remapText}}$">{{::ds.remapText}}</td>
+                    <td data-search="^{{::ds.routingName}}$">{{::ds.routingName}}</td>
+                    <td data-search="^{{::ds.signed}}$">{{::ds.signed}}</td>
+                    <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
+                    <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
+                    <td data-search="^{{::ds.trResponseHeaders}}$">{{::ds.trResponseHeaders}}</td>
+                    <td data-search="^{{::ds.trRequestHeaders}}$">{{::ds.trRequestHeaders}}</td>
+                    <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
+                    <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
+                </tr>
             </tbody>
         </table>
     </div>
diff --git a/traffic_portal/app/src/common/modules/table/serverDeliveryServices/TableServerDeliveryServicesController.js b/traffic_portal/app/src/common/modules/table/serverDeliveryServices/TableServerDeliveryServicesController.js
index 5cb52f5..dcf7c87 100644
--- a/traffic_portal/app/src/common/modules/table/serverDeliveryServices/TableServerDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/serverDeliveryServices/TableServerDeliveryServicesController.js
@@ -22,6 +22,8 @@ var TableServerDeliveryServicesController = function(server, deliveryServices, $
 	// extends the TableDeliveryServicesController to inherit common methods
 	angular.extend(this, $controller('TableDeliveryServicesController', { deliveryServices: deliveryServices, $scope: $scope }));
 
+	let serverDeliveryServicesTable;
+
 	var removeDeliveryService = function(dsId) {
 		deliveryServiceService.deleteDeliveryServiceServer(dsId, $scope.server.id)
 			.then(
@@ -31,6 +33,32 @@ var TableServerDeliveryServicesController = function(server, deliveryServices, $
 			);
 	};
 
+	var confirmRemoveDS = function(ds, $event) {
+		if ($event) {
+			$event.stopPropagation(); // this kills the click event so it doesn't trigger anything else
+		}
+
+		var params = {
+			title: 'Remove Delivery Service from Server?',
+			message: 'Are you sure you want to remove ' + ds.xmlId + ' from this server?'
+		};
+		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() {
+			removeDeliveryService(ds.id);
+		}, function () {
+			// do nothing
+		});
+	};
+
 	$scope.server = server;
 
 	// adds some items to the base delivery services context menu
@@ -41,7 +69,7 @@ var TableServerDeliveryServicesController = function(server, deliveryServices, $
 				return true;
 			},
 			click: function ($itemScope) {
-				$scope.confirmRemoveDS($itemScope.ds);
+				confirmRemoveDS($itemScope.ds);
 			}
 		}
 	);
@@ -109,40 +137,29 @@ var TableServerDeliveryServicesController = function(server, deliveryServices, $
 		});
 	};
 
-	$scope.confirmRemoveDS = function(ds, $event) {
-		if ($event) {
-			$event.stopPropagation(); // this kills the click event so it doesn't trigger anything else
-		}
-
-		var params = {
-			title: 'Remove Delivery Service from Server?',
-			message: 'Are you sure you want to remove ' + ds.xmlId + ' from this server?'
-		};
-		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() {
-			removeDeliveryService(ds.id);
-		}, function () {
-			// do nothing
-		});
+	$scope.toggleVisibility = function(colName) {
+		const col = serverDeliveryServicesTable.column(colName + ':name');
+		col.visible(!col.visible());
+		serverDeliveryServicesTable.rows().invalidate().draw();
 	};
 
 	angular.element(document).ready(function () {
-		$('#serverDeliveryServicesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
+		serverDeliveryServicesTable = $('#serverDeliveryServicesTable').DataTable({
+			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
 			"iDisplayLength": 25,
-			"columnDefs": [
-				{ 'orderable': false, 'targets': 12 }
-			],
-			"aaSorting": []
+			"aaSorting": [],
+			"columns": $scope.columns,
+			"colReorder": {
+				realtime: 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_serverDeliveryServicesTable_/')).columns;
+				} catch (e) {
+					console.error("Failure to retrieve required column info from localStorage (key=DataTables_serverDeliveryServicesTable_/):", e);
+				}
+			}
 		});
 	});
 
diff --git a/traffic_portal/app/src/common/modules/table/serverDeliveryServices/table.serverDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/serverDeliveryServices/table.serverDeliveryServices.tpl.html
index 1599dff..7cabf61 100644
--- a/traffic_portal/app/src/common/modules/table/serverDeliveryServices/table.serverDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/serverDeliveryServices/table.serverDeliveryServices.tpl.html
@@ -27,6 +27,19 @@ under the License.
         <div class="pull-right" role="group">
             <button class="btn btn-primary" title="Link Delivery Services to Server" ng-show="isEdge(server)" ng-click="selectDeliveryServices()"><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 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>
             <div class="btn-group" role="group" ng-show="isEdge(server)" uib-dropdown is-open="more.isopen">
                 <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
                     More&nbsp;
@@ -43,41 +56,120 @@ under the License.
         <br>
         <table id="serverDeliveryServicesTable" class="table responsive-utilities jambo_table">
             <thead>
-            <tr class="headings">
-                <th>Key (XML ID)</th>
-                <th>Tenant</th>
-                <th>Origin</th>
-                <th>Active</th>
-                <th>Type</th>
-                <th>Protocol</th>
-                <th>CDN</th>
-                <th>IPv6 Enabled</th>
-                <th>DSCP</th>
-                <th>Signing Algorithm</th>
-                <th>Qstring Handling</th>
-                <th>Last Updated</th>
-                <th style="text-align: right;">Actions</th>
-            </tr>
+                <tr class="headings">
+                    <th>Active</th>
+                    <th>Anonymous Blocking</th>
+                    <th>CDN</th>
+                    <th>Check Path</th>
+                    <th>Consistent Hash Query Params</th>
+                    <th>Consistent Hash Regex</th>
+                    <th>Deep Caching Type</th>
+                    <th>Display Name</th>
+                    <th>DNS Bypass CNAME</th>
+                    <th>DNS Bypass IP</th>
+                    <th>DNS Bypass IPv6</th>
+                    <th>DNS Bypass TTL</th>
+                    <th>DNS TTL</th>
+                    <th>DSCP</th>
+                    <th>Edge Header Rewrite Rules</th>
+                    <th>FQ Pacing Rate</th>
+                    <th>Geo Limit</th>
+                    <th>Geo Limit Countries</th>
+                    <th>Geo Limit Redirect URL</th>
+                    <th>Geolocation Provider</th>
+                    <th>Geo Miss Latitude</th>
+                    <th>Geo Miss Longitude</th>
+                    <th>Global Max Mbps</th>
+                    <th>Global Max TPS</th>
+                    <th>HTTP Bypass FQDN</th>
+                    <th>ID</th>
+                    <th>Info URL</th>
+                    <th>Initial Dispersion</th>
+                    <th>IPv6 Routing</th>
+                    <th>Last Updated</th>
+                    <th>Long Desc 1</th>
+                    <th>Long Desc 2</th>
+                    <th>Long Desc 3</th>
+                    <th>Max DNS Answers</th>
+                    <th>Max Origin Connections</th>
+                    <th>Mid Header Rewrite Rules</th>
+                    <th>Multi-Site Origin</th>
+                    <th>Origin Shield</th>
+                    <th>Origin FQDN</th>
+                    <th>Profile</th>
+                    <th>Protocol</th>
+                    <th>Qstring Handling</th>
+                    <th>Range Request Handling</th>
+                    <th>Regex Remap Expression</th>
+                    <th>Regional Geoblocking</th>
+                    <th>Raw Remap Text</th>
+                    <th>Routing Name</th>
+                    <th>Signed</th>
+                    <th>Signing Algorithm</th>
+                    <th>Tenant</th>
+                    <th>TR Request Headers</th>
+                    <th>TR Response Headers</th>
+                    <th>Type</th>
+                    <th>XML ID (Key)</th>
+                </tr>
             </thead>
             <tbody>
-            <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
-                <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
-                <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
-                <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
-                <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
-                <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
-                <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
-                <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
-                <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
-                <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
-                <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
-                <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
-                <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
-                <td style="text-align: right;">
-                    <a class="link action-link" title="Unlink Delivery Service from Server" ng-click="confirmRemoveDS(ds, $event)"><i class="fa fa-sm fa-chain-broken"></i></a>
-                    <span ng-if="showChartsButton"><a class="link action-link" title="View Charts" ng-click="openCharts(ds, $event)"><i class="fa fa-sm fa-bar-chart"></i></a></span>
-                </td>
-            </tr>
+                <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
+                    <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
+                    <td data-search="^{{::ds.anonymousBlockingEnabled}}$">{{::ds.anonymousBlockingEnabled}}</td>
+                    <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
+                    <td data-search="^{{::ds.checkPath}}$">{{::ds.checkPath}}</td>
+                    <td data-search="^{{::ds.consistentHashQueryParams}}$">{{::ds.consistentHashQueryParams.join(', ')}}</td>
+                    <td data-search="^{{::ds.consistentHashRegex}}$">{{::ds.consistentHashRegex}}</td>
+                    <td data-search="^{{::ds.deepCachingType}}$">{{::ds.deepCachingType}}</td>
+                    <td data-search="^{{::ds.displayName}}$">{{::ds.displayName}}</td>
+                    <td data-search="^{{::ds.dnsBypassCname}}$">{{::ds.dnsBypassCname}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp}}$">{{::ds.dnsBypassIp}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp6}}$">{{::ds.dnsBypassIp6}}</td>
+                    <td data-search="^{{::ds.dnsBypassTtl}}$">{{::ds.dnsBypassTtl}}</td>
+                    <td data-search="^{{::ds.ccrDnsTtl}}$">{{::ds.ccrDnsTtl}}</td>
+                    <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
+                    <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
+                    <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
+                    <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
+                    <td data-search="^{{::ds.geoLimitRedirectURL}}$">{{::ds.geoLimitRedirectURL}}</td>
+                    <td data-search="^{{::geoProvider(ds)}}$">{{::geoProvider(ds)}}</td>
+                    <td data-search="^{{::ds.missLat}}$">{{::ds.missLat}}</td>
+                    <td data-search="^{{::ds.missLong}}$">{{::ds.missLong}}</td>
+                    <td data-search="^{{::ds.globalMaxMbps}}$">{{::ds.globalMaxMbps}}</td>
+                    <td data-search="^{{::ds.globalMaxTps}}$">{{::ds.globalMaxTps}}</td>
+                    <td data-search="^{{::ds.httpBypassFqdn}}$">{{::ds.httpBypassFqdn}}</td>
+                    <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
+                    <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
+                    <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
+                    <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
+                    <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
+                    <td data-search="^{{::ds.longDesc2}}$">{{::ds.longDesc2}}</td>
+                    <td data-search="^{{::ds.maxDnsAnswers}}$">{{::ds.maxDnsAnswers}}</td>
+                    <td data-search="^{{::ds.maxOriginConnections}}$">{{::ds.maxOriginConnections}}</td>
+                    <td data-search="^{{::ds.midHeaderRewrite}}$">{{::ds.midHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.multiSiteOrigin}}$">{{::ds.multiSiteOrigin}}</td>
+                    <td data-search="^{{::ds.originShield}}$">{{::ds.originShield}}</td>
+                    <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
+                    <td data-search="^{{::ds.profileName}}$">{{::ds.profileName}}</td>
+                    <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
+                    <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
+                    <td data-search="^{{::rrh(ds)}}$">{{::rrh(ds)}}</td>
+                    <td data-search="^{{::ds.regexRemap}}$">{{::ds.regexRemap}}</td>
+                    <td data-search="^{{::ds.regionalGeoBlocking}}$">{{::ds.regionalGeoBlocking}}</td>
+                    <td data-search="^{{::ds.remapText}}$">{{::ds.remapText}}</td>
+                    <td data-search="^{{::ds.routingName}}$">{{::ds.routingName}}</td>
+                    <td data-search="^{{::ds.signed}}$">{{::ds.signed}}</td>
+                    <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
+                    <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
+                    <td data-search="^{{::ds.trResponseHeaders}}$">{{::ds.trResponseHeaders}}</td>
+                    <td data-search="^{{::ds.trRequestHeaders}}$">{{::ds.trRequestHeaders}}</td>
+                    <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
+                    <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
+                </tr>
             </tbody>
         </table>
     </div>
diff --git a/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/TableTenantDeliveryServicesController.js b/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/TableTenantDeliveryServicesController.js
index 8bca537..b9d3b9d 100644
--- a/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/TableTenantDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/TableTenantDeliveryServicesController.js
@@ -22,16 +22,33 @@ var TableTenantDeliveryServicesController = function(tenant, deliveryServices, $
 	// extends the TableDeliveryServicesController to inherit common methods
 	angular.extend(this, $controller('TableDeliveryServicesController', { deliveryServices: deliveryServices, $scope: $scope }));
 
+	let tenantDSsTable;
+
 	$scope.tenant = tenant;
 
+	$scope.toggleVisibility = function(colName) {
+		const col = tenantDSsTable.column(colName + ':name');
+		col.visible(!col.visible());
+		tenantDSsTable.rows().invalidate().draw();
+	};
+
 	angular.element(document).ready(function () {
-		$('#tenantDSsTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
+		tenantDSsTable = $('#tenantDSsTable').DataTable({
+			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
 			"iDisplayLength": 25,
-			"columnDefs": [
-				{ 'orderable': false, 'targets': 12 }
-			],
-			"aaSorting": []
+			"aaSorting": [],
+			"columns": $scope.columns,
+			"colReorder": {
+				realtime: 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_tenantDeliveryServicesTable_/')).columns;
+				} catch (e) {
+					console.error("Failure to retrieve required column info from localStorage (key=DataTables_tenantDeliveryServicesTable_/):", e);
+				}
+			}
 		});
 	});
 
diff --git a/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/table.tenantDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/table.tenantDeliveryServices.tpl.html
index e584830..7de74b6 100644
--- a/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/table.tenantDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/table.tenantDeliveryServices.tpl.html
@@ -26,6 +26,19 @@ under the License.
         </ol>
         <div class="pull-right">
             <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
+            <div 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>
         </div>
         <div class="clearfix"></div>
     </div>
@@ -33,40 +46,120 @@ under the License.
         <br>
         <table id="tenantDSsTable" class="table responsive-utilities jambo_table">
             <thead>
-            <tr class="headings">
-                <th>Key (XML ID)</th>
-                <th>Tenant</th>
-                <th>Origin</th>
-                <th>Active</th>
-                <th>Type</th>
-                <th>Protocol</th>
-                <th>CDN</th>
-                <th>IPv6 Enabled</th>
-                <th>DSCP</th>
-                <th>Signing Algorithm</th>
-                <th>Qstring Handling</th>
-                <th>Last Updated</th>
-                <th style="text-align: right;">Actions</th>
-            </tr>
+                <tr class="headings">
+                    <th>Active</th>
+                    <th>Anonymous Blocking</th>
+                    <th>CDN</th>
+                    <th>Check Path</th>
+                    <th>Consistent Hash Query Params</th>
+                    <th>Consistent Hash Regex</th>
+                    <th>Deep Caching Type</th>
+                    <th>Display Name</th>
+                    <th>DNS Bypass CNAME</th>
+                    <th>DNS Bypass IP</th>
+                    <th>DNS Bypass IPv6</th>
+                    <th>DNS Bypass TTL</th>
+                    <th>DNS TTL</th>
+                    <th>DSCP</th>
+                    <th>Edge Header Rewrite Rules</th>
+                    <th>FQ Pacing Rate</th>
+                    <th>Geo Limit</th>
+                    <th>Geo Limit Countries</th>
+                    <th>Geo Limit Redirect URL</th>
+                    <th>Geolocation Provider</th>
+                    <th>Geo Miss Latitude</th>
+                    <th>Geo Miss Longitude</th>
+                    <th>Global Max Mbps</th>
+                    <th>Global Max TPS</th>
+                    <th>HTTP Bypass FQDN</th>
+                    <th>ID</th>
+                    <th>Info URL</th>
+                    <th>Initial Dispersion</th>
+                    <th>IPv6 Routing</th>
+                    <th>Last Updated</th>
+                    <th>Long Desc 1</th>
+                    <th>Long Desc 2</th>
+                    <th>Long Desc 3</th>
+                    <th>Max DNS Answers</th>
+                    <th>Max Origin Connections</th>
+                    <th>Mid Header Rewrite Rules</th>
+                    <th>Multi-Site Origin</th>
+                    <th>Origin Shield</th>
+                    <th>Origin FQDN</th>
+                    <th>Profile</th>
+                    <th>Protocol</th>
+                    <th>Qstring Handling</th>
+                    <th>Range Request Handling</th>
+                    <th>Regex Remap Expression</th>
+                    <th>Regional Geoblocking</th>
+                    <th>Raw Remap Text</th>
+                    <th>Routing Name</th>
+                    <th>Signed</th>
+                    <th>Signing Algorithm</th>
+                    <th>Tenant</th>
+                    <th>TR Request Headers</th>
+                    <th>TR Response Headers</th>
+                    <th>Type</th>
+                    <th>XML ID (Key)</th>
+                </tr>
             </thead>
             <tbody>
-            <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
-                <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
-                <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
-                <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
-                <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
-                <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
-                <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
-                <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
-                <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
-                <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
-                <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
-                <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
-                <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
-                <td style="text-align: right;">
-                    <span ng-if="showChartsButton"><a class="link action-link" title="View Charts" ng-click="openCharts(ds, $event)"><i class="fa fa-sm fa-bar-chart"></i></a></span>
-                </td>
-            </tr>
+                <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
+                    <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
+                    <td data-search="^{{::ds.anonymousBlockingEnabled}}$">{{::ds.anonymousBlockingEnabled}}</td>
+                    <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
+                    <td data-search="^{{::ds.checkPath}}$">{{::ds.checkPath}}</td>
+                    <td data-search="^{{::ds.consistentHashQueryParams}}$">{{::ds.consistentHashQueryParams.join(', ')}}</td>
+                    <td data-search="^{{::ds.consistentHashRegex}}$">{{::ds.consistentHashRegex}}</td>
+                    <td data-search="^{{::ds.deepCachingType}}$">{{::ds.deepCachingType}}</td>
+                    <td data-search="^{{::ds.displayName}}$">{{::ds.displayName}}</td>
+                    <td data-search="^{{::ds.dnsBypassCname}}$">{{::ds.dnsBypassCname}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp}}$">{{::ds.dnsBypassIp}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp6}}$">{{::ds.dnsBypassIp6}}</td>
+                    <td data-search="^{{::ds.dnsBypassTtl}}$">{{::ds.dnsBypassTtl}}</td>
+                    <td data-search="^{{::ds.ccrDnsTtl}}$">{{::ds.ccrDnsTtl}}</td>
+                    <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
+                    <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
+                    <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
+                    <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
+                    <td data-search="^{{::ds.geoLimitRedirectURL}}$">{{::ds.geoLimitRedirectURL}}</td>
+                    <td data-search="^{{::geoProvider(ds)}}$">{{::geoProvider(ds)}}</td>
+                    <td data-search="^{{::ds.missLat}}$">{{::ds.missLat}}</td>
+                    <td data-search="^{{::ds.missLong}}$">{{::ds.missLong}}</td>
+                    <td data-search="^{{::ds.globalMaxMbps}}$">{{::ds.globalMaxMbps}}</td>
+                    <td data-search="^{{::ds.globalMaxTps}}$">{{::ds.globalMaxTps}}</td>
+                    <td data-search="^{{::ds.httpBypassFqdn}}$">{{::ds.httpBypassFqdn}}</td>
+                    <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
+                    <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
+                    <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
+                    <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
+                    <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
+                    <td data-search="^{{::ds.longDesc2}}$">{{::ds.longDesc2}}</td>
+                    <td data-search="^{{::ds.maxDnsAnswers}}$">{{::ds.maxDnsAnswers}}</td>
+                    <td data-search="^{{::ds.maxOriginConnections}}$">{{::ds.maxOriginConnections}}</td>
+                    <td data-search="^{{::ds.midHeaderRewrite}}$">{{::ds.midHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.multiSiteOrigin}}$">{{::ds.multiSiteOrigin}}</td>
+                    <td data-search="^{{::ds.originShield}}$">{{::ds.originShield}}</td>
+                    <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
+                    <td data-search="^{{::ds.profileName}}$">{{::ds.profileName}}</td>
+                    <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
+                    <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
+                    <td data-search="^{{::rrh(ds)}}$">{{::rrh(ds)}}</td>
+                    <td data-search="^{{::ds.regexRemap}}$">{{::ds.regexRemap}}</td>
+                    <td data-search="^{{::ds.regionalGeoBlocking}}$">{{::ds.regionalGeoBlocking}}</td>
+                    <td data-search="^{{::ds.remapText}}$">{{::ds.remapText}}</td>
+                    <td data-search="^{{::ds.routingName}}$">{{::ds.routingName}}</td>
+                    <td data-search="^{{::ds.signed}}$">{{::ds.signed}}</td>
+                    <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
+                    <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
+                    <td data-search="^{{::ds.trResponseHeaders}}$">{{::ds.trResponseHeaders}}</td>
+                    <td data-search="^{{::ds.trRequestHeaders}}$">{{::ds.trRequestHeaders}}</td>
+                    <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
+                    <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
+                </tr>
             </tbody>
         </table>
     </div>
diff --git a/traffic_portal/app/src/common/modules/table/typeDeliveryServices/TableTypeDeliveryServicesController.js b/traffic_portal/app/src/common/modules/table/typeDeliveryServices/TableTypeDeliveryServicesController.js
index 530e905..8ae2ab2 100644
--- a/traffic_portal/app/src/common/modules/table/typeDeliveryServices/TableTypeDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/typeDeliveryServices/TableTypeDeliveryServicesController.js
@@ -22,16 +22,33 @@ var TableTypeDeliveryServicesController = function(type, deliveryServices, $cont
 	// extends the TableDeliveryServicesController to inherit common methods
 	angular.extend(this, $controller('TableDeliveryServicesController', { deliveryServices: deliveryServices, $scope: $scope }));
 
+	let typeDeliveryServicesTable;
+
 	$scope.type = type;
 
+	$scope.toggleVisibility = function(colName) {
+		const col = typeDeliveryServicesTable.column(colName + ':name');
+		col.visible(!col.visible());
+		typeDeliveryServicesTable.rows().invalidate().draw();
+	};
+
 	angular.element(document).ready(function () {
-		$('#typeDeliveryServicesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
+		typeDeliveryServicesTable = $('#typeDeliveryServicesTable').DataTable({
+			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
 			"iDisplayLength": 25,
-			"columnDefs": [
-				{ 'orderable': false, 'targets': 12 }
-			],
-			"aaSorting": []
+			"aaSorting": [],
+			"columns": $scope.columns,
+			"colReorder": {
+				realtime: 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_typeDeliveryServicesTable_/')).columns;
+				} catch (e) {
+					console.error("Failure to retrieve required column info from localStorage (key=DataTables_typeDeliveryServicesTable_/):", e);
+				}
+			}
 		});
 	});
 
diff --git a/traffic_portal/app/src/common/modules/table/typeDeliveryServices/table.typeDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/typeDeliveryServices/table.typeDeliveryServices.tpl.html
index 410cf87..8ac1b86 100644
--- a/traffic_portal/app/src/common/modules/table/typeDeliveryServices/table.typeDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/typeDeliveryServices/table.typeDeliveryServices.tpl.html
@@ -26,6 +26,19 @@ under the License.
         </ol>
         <div class="pull-right">
             <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
+            <div 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>
         </div>
         <div class="clearfix"></div>
     </div>
@@ -33,40 +46,120 @@ under the License.
         <br>
         <table id="typeDeliveryServicesTable" class="table responsive-utilities jambo_table">
             <thead>
-            <tr class="headings">
-                <th>Key (XML ID)</th>
-                <th>Tenant</th>
-                <th>Origin</th>
-                <th>Active</th>
-                <th>Type</th>
-                <th>Protocol</th>
-                <th>CDN</th>
-                <th>IPv6 Enabled</th>
-                <th>DSCP</th>
-                <th>Signing Algorithm</th>
-                <th>Qstring Handling</th>
-                <th>Last Updated</th>
-                <th style="text-align: right;">Actions</th>
-            </tr>
+                <tr class="headings">
+                    <th>Active</th>
+                    <th>Anonymous Blocking</th>
+                    <th>CDN</th>
+                    <th>Check Path</th>
+                    <th>Consistent Hash Query Params</th>
+                    <th>Consistent Hash Regex</th>
+                    <th>Deep Caching Type</th>
+                    <th>Display Name</th>
+                    <th>DNS Bypass CNAME</th>
+                    <th>DNS Bypass IP</th>
+                    <th>DNS Bypass IPv6</th>
+                    <th>DNS Bypass TTL</th>
+                    <th>DNS TTL</th>
+                    <th>DSCP</th>
+                    <th>Edge Header Rewrite Rules</th>
+                    <th>FQ Pacing Rate</th>
+                    <th>Geo Limit</th>
+                    <th>Geo Limit Countries</th>
+                    <th>Geo Limit Redirect URL</th>
+                    <th>Geolocation Provider</th>
+                    <th>Geo Miss Latitude</th>
+                    <th>Geo Miss Longitude</th>
+                    <th>Global Max Mbps</th>
+                    <th>Global Max TPS</th>
+                    <th>HTTP Bypass FQDN</th>
+                    <th>ID</th>
+                    <th>Info URL</th>
+                    <th>Initial Dispersion</th>
+                    <th>IPv6 Routing</th>
+                    <th>Last Updated</th>
+                    <th>Long Desc 1</th>
+                    <th>Long Desc 2</th>
+                    <th>Long Desc 3</th>
+                    <th>Max DNS Answers</th>
+                    <th>Max Origin Connections</th>
+                    <th>Mid Header Rewrite Rules</th>
+                    <th>Multi-Site Origin</th>
+                    <th>Origin Shield</th>
+                    <th>Origin FQDN</th>
+                    <th>Profile</th>
+                    <th>Protocol</th>
+                    <th>Qstring Handling</th>
+                    <th>Range Request Handling</th>
+                    <th>Regex Remap Expression</th>
+                    <th>Regional Geoblocking</th>
+                    <th>Raw Remap Text</th>
+                    <th>Routing Name</th>
+                    <th>Signed</th>
+                    <th>Signing Algorithm</th>
+                    <th>Tenant</th>
+                    <th>TR Request Headers</th>
+                    <th>TR Response Headers</th>
+                    <th>Type</th>
+                    <th>XML ID (Key)</th>
+                </tr>
             </thead>
             <tbody>
-            <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
-                <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
-                <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
-                <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
-                <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
-                <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
-                <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
-                <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
-                <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
-                <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
-                <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
-                <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
-                <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
-                <td style="text-align: right;">
-                    <span ng-if="showChartsButton"><a class="link action-link" title="View Charts" ng-click="openCharts(ds, $event)"><i class="fa fa-sm fa-bar-chart"></i></a></span>
-                </td>
-            </tr>
+                <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
+                    <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
+                    <td data-search="^{{::ds.anonymousBlockingEnabled}}$">{{::ds.anonymousBlockingEnabled}}</td>
+                    <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
+                    <td data-search="^{{::ds.checkPath}}$">{{::ds.checkPath}}</td>
+                    <td data-search="^{{::ds.consistentHashQueryParams}}$">{{::ds.consistentHashQueryParams.join(', ')}}</td>
+                    <td data-search="^{{::ds.consistentHashRegex}}$">{{::ds.consistentHashRegex}}</td>
+                    <td data-search="^{{::ds.deepCachingType}}$">{{::ds.deepCachingType}}</td>
+                    <td data-search="^{{::ds.displayName}}$">{{::ds.displayName}}</td>
+                    <td data-search="^{{::ds.dnsBypassCname}}$">{{::ds.dnsBypassCname}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp}}$">{{::ds.dnsBypassIp}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp6}}$">{{::ds.dnsBypassIp6}}</td>
+                    <td data-search="^{{::ds.dnsBypassTtl}}$">{{::ds.dnsBypassTtl}}</td>
+                    <td data-search="^{{::ds.ccrDnsTtl}}$">{{::ds.ccrDnsTtl}}</td>
+                    <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
+                    <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
+                    <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
+                    <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
+                    <td data-search="^{{::ds.geoLimitRedirectURL}}$">{{::ds.geoLimitRedirectURL}}</td>
+                    <td data-search="^{{::geoProvider(ds)}}$">{{::geoProvider(ds)}}</td>
+                    <td data-search="^{{::ds.missLat}}$">{{::ds.missLat}}</td>
+                    <td data-search="^{{::ds.missLong}}$">{{::ds.missLong}}</td>
+                    <td data-search="^{{::ds.globalMaxMbps}}$">{{::ds.globalMaxMbps}}</td>
+                    <td data-search="^{{::ds.globalMaxTps}}$">{{::ds.globalMaxTps}}</td>
+                    <td data-search="^{{::ds.httpBypassFqdn}}$">{{::ds.httpBypassFqdn}}</td>
+                    <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
+                    <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
+                    <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
+                    <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
+                    <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
+                    <td data-search="^{{::ds.longDesc2}}$">{{::ds.longDesc2}}</td>
+                    <td data-search="^{{::ds.maxDnsAnswers}}$">{{::ds.maxDnsAnswers}}</td>
+                    <td data-search="^{{::ds.maxOriginConnections}}$">{{::ds.maxOriginConnections}}</td>
+                    <td data-search="^{{::ds.midHeaderRewrite}}$">{{::ds.midHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.multiSiteOrigin}}$">{{::ds.multiSiteOrigin}}</td>
+                    <td data-search="^{{::ds.originShield}}$">{{::ds.originShield}}</td>
+                    <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
+                    <td data-search="^{{::ds.profileName}}$">{{::ds.profileName}}</td>
+                    <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
+                    <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
+                    <td data-search="^{{::rrh(ds)}}$">{{::rrh(ds)}}</td>
+                    <td data-search="^{{::ds.regexRemap}}$">{{::ds.regexRemap}}</td>
+                    <td data-search="^{{::ds.regionalGeoBlocking}}$">{{::ds.regionalGeoBlocking}}</td>
+                    <td data-search="^{{::ds.remapText}}$">{{::ds.remapText}}</td>
+                    <td data-search="^{{::ds.routingName}}$">{{::ds.routingName}}</td>
+                    <td data-search="^{{::ds.signed}}$">{{::ds.signed}}</td>
+                    <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
+                    <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
+                    <td data-search="^{{::ds.trResponseHeaders}}$">{{::ds.trResponseHeaders}}</td>
+                    <td data-search="^{{::ds.trRequestHeaders}}$">{{::ds.trRequestHeaders}}</td>
+                    <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
+                    <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
+                </tr>
             </tbody>
         </table>
     </div>
diff --git a/traffic_portal/app/src/common/modules/table/userDeliveryServices/TableUserDeliveryServicesController.js b/traffic_portal/app/src/common/modules/table/userDeliveryServices/TableUserDeliveryServicesController.js
index ce17d1c..f338eca 100644
--- a/traffic_portal/app/src/common/modules/table/userDeliveryServices/TableUserDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/userDeliveryServices/TableUserDeliveryServicesController.js
@@ -22,13 +22,33 @@ var TableUserDeliveryServicesController = function (user, deliveryServices, $con
 	// extends the TableDeliveryServicesController to inherit common methods
 	angular.extend(this, $controller('TableDeliveryServicesController', { deliveryServices: deliveryServices, $scope: $scope }));
 
+	let userDeliveryServicesTable;
+
 	$scope.user = user;
 
+	$scope.toggleVisibility = function(colName) {
+		const col = userDeliveryServicesTable.column(colName + ':name');
+		col.visible(!col.visible());
+		userDeliveryServicesTable.rows().invalidate().draw();
+	};
+
 	angular.element(document).ready(function () {
-		$('#userDeliveryServicesTable').dataTable({
-			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
+		userDeliveryServicesTable = $('#userDeliveryServicesTable').DataTable({
+			"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
 			"iDisplayLength": 25,
-			"aaSorting": []
+			"aaSorting": [],
+			"columns": $scope.columns,
+			"colReorder": {
+				realtime: 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_userDeliveryServicesTable_/')).columns;
+				} catch (e) {
+					console.error("Failure to retrieve required column info from localStorage (key=DataTables_userDeliveryServicesTable_/):", e);
+				}
+			}
 		});
 	});
 
diff --git a/traffic_portal/app/src/common/modules/table/userDeliveryServices/table.userDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/userDeliveryServices/table.userDeliveryServices.tpl.html
index 4a69663..4fb2b52 100644
--- a/traffic_portal/app/src/common/modules/table/userDeliveryServices/table.userDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/userDeliveryServices/table.userDeliveryServices.tpl.html
@@ -26,6 +26,19 @@ under the License.
         </ol>
         <div class="pull-right">
             <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
+            <div 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>
         </div>
         <div class="clearfix"></div>
     </div>
@@ -33,40 +46,120 @@ under the License.
         <br>
         <table id="userDeliveryServicesTable" class="table responsive-utilities jambo_table">
             <thead>
-            <tr class="headings">
-                <th>Key (XML ID)</th>
-                <th>Tenant</th>
-                <th>Origin</th>
-                <th>Active</th>
-                <th>Type</th>
-                <th>Protocol</th>
-                <th>CDN</th>
-                <th>IPv6 Enabled</th>
-                <th>DSCP</th>
-                <th>Signing Algorithm</th>
-                <th>Qstring Handling</th>
-                <th>Last Updated</th>
-                <th style="text-align: right;">Actions</th>
-            </tr>
+                <tr class="headings">
+                    <th>Active</th>
+                    <th>Anonymous Blocking</th>
+                    <th>CDN</th>
+                    <th>Check Path</th>
+                    <th>Consistent Hash Query Params</th>
+                    <th>Consistent Hash Regex</th>
+                    <th>Deep Caching Type</th>
+                    <th>Display Name</th>
+                    <th>DNS Bypass CNAME</th>
+                    <th>DNS Bypass IP</th>
+                    <th>DNS Bypass IPv6</th>
+                    <th>DNS Bypass TTL</th>
+                    <th>DNS TTL</th>
+                    <th>DSCP</th>
+                    <th>Edge Header Rewrite Rules</th>
+                    <th>FQ Pacing Rate</th>
+                    <th>Geo Limit</th>
+                    <th>Geo Limit Countries</th>
+                    <th>Geo Limit Redirect URL</th>
+                    <th>Geolocation Provider</th>
+                    <th>Geo Miss Latitude</th>
+                    <th>Geo Miss Longitude</th>
+                    <th>Global Max Mbps</th>
+                    <th>Global Max TPS</th>
+                    <th>HTTP Bypass FQDN</th>
+                    <th>ID</th>
+                    <th>Info URL</th>
+                    <th>Initial Dispersion</th>
+                    <th>IPv6 Routing</th>
+                    <th>Last Updated</th>
+                    <th>Long Desc 1</th>
+                    <th>Long Desc 2</th>
+                    <th>Long Desc 3</th>
+                    <th>Max DNS Answers</th>
+                    <th>Max Origin Connections</th>
+                    <th>Mid Header Rewrite Rules</th>
+                    <th>Multi-Site Origin</th>
+                    <th>Origin Shield</th>
+                    <th>Origin FQDN</th>
+                    <th>Profile</th>
+                    <th>Protocol</th>
+                    <th>Qstring Handling</th>
+                    <th>Range Request Handling</th>
+                    <th>Regex Remap Expression</th>
+                    <th>Regional Geoblocking</th>
+                    <th>Raw Remap Text</th>
+                    <th>Routing Name</th>
+                    <th>Signed</th>
+                    <th>Signing Algorithm</th>
+                    <th>Tenant</th>
+                    <th>TR Request Headers</th>
+                    <th>TR Response Headers</th>
+                    <th>Type</th>
+                    <th>XML ID (Key)</th>
+                </tr>
             </thead>
             <tbody>
-            <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
-                <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
-                <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
-                <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
-                <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
-                <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
-                <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
-                <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
-                <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
-                <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
-                <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
-                <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
-                <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
-                <td style="text-align: right;">
-                    <span ng-if="showChartsButton"><a class="link action-link" title="View Charts" ng-click="openCharts(ds, $event)"><i class="fa fa-sm fa-bar-chart"></i></a></span>
-                </td>
-            </tr>
+                <tr ng-click="editDeliveryService(ds)" ng-repeat="ds in ::deliveryServices" context-menu="contextMenuItems">
+                    <td data-search="^{{::ds.active}}$">{{::ds.active}}</td>
+                    <td data-search="^{{::ds.anonymousBlockingEnabled}}$">{{::ds.anonymousBlockingEnabled}}</td>
+                    <td data-search="^{{::ds.cdnName}}$">{{::ds.cdnName}}</td>
+                    <td data-search="^{{::ds.checkPath}}$">{{::ds.checkPath}}</td>
+                    <td data-search="^{{::ds.consistentHashQueryParams}}$">{{::ds.consistentHashQueryParams.join(', ')}}</td>
+                    <td data-search="^{{::ds.consistentHashRegex}}$">{{::ds.consistentHashRegex}}</td>
+                    <td data-search="^{{::ds.deepCachingType}}$">{{::ds.deepCachingType}}</td>
+                    <td data-search="^{{::ds.displayName}}$">{{::ds.displayName}}</td>
+                    <td data-search="^{{::ds.dnsBypassCname}}$">{{::ds.dnsBypassCname}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp}}$">{{::ds.dnsBypassIp}}</td>
+                    <td data-search="^{{::ds.dnsBypassIp6}}$">{{::ds.dnsBypassIp6}}</td>
+                    <td data-search="^{{::ds.dnsBypassTtl}}$">{{::ds.dnsBypassTtl}}</td>
+                    <td data-search="^{{::ds.ccrDnsTtl}}$">{{::ds.ccrDnsTtl}}</td>
+                    <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
+                    <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
+                    <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
+                    <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
+                    <td data-search="^{{::ds.geoLimitRedirectURL}}$">{{::ds.geoLimitRedirectURL}}</td>
+                    <td data-search="^{{::geoProvider(ds)}}$">{{::geoProvider(ds)}}</td>
+                    <td data-search="^{{::ds.missLat}}$">{{::ds.missLat}}</td>
+                    <td data-search="^{{::ds.missLong}}$">{{::ds.missLong}}</td>
+                    <td data-search="^{{::ds.globalMaxMbps}}$">{{::ds.globalMaxMbps}}</td>
+                    <td data-search="^{{::ds.globalMaxTps}}$">{{::ds.globalMaxTps}}</td>
+                    <td data-search="^{{::ds.httpBypassFqdn}}$">{{::ds.httpBypassFqdn}}</td>
+                    <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
+                    <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
+                    <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
+                    <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
+                    <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
+                    <td data-search="^{{::ds.longDesc2}}$">{{::ds.longDesc2}}</td>
+                    <td data-search="^{{::ds.maxDnsAnswers}}$">{{::ds.maxDnsAnswers}}</td>
+                    <td data-search="^{{::ds.maxOriginConnections}}$">{{::ds.maxOriginConnections}}</td>
+                    <td data-search="^{{::ds.midHeaderRewrite}}$">{{::ds.midHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.multiSiteOrigin}}$">{{::ds.multiSiteOrigin}}</td>
+                    <td data-search="^{{::ds.originShield}}$">{{::ds.originShield}}</td>
+                    <td data-search="^{{::ds.orgServerFqdn}}$">{{::ds.orgServerFqdn}}</td>
+                    <td data-search="^{{::ds.profileName}}$">{{::ds.profileName}}</td>
+                    <td data-search="^{{::protocol(ds)}}$">{{::protocol(ds)}}</td>
+                    <td data-search="^{{::qstring(ds)}}$">{{::qstring(ds)}}</td>
+                    <td data-search="^{{::rrh(ds)}}$">{{::rrh(ds)}}</td>
+                    <td data-search="^{{::ds.regexRemap}}$">{{::ds.regexRemap}}</td>
+                    <td data-search="^{{::ds.regionalGeoBlocking}}$">{{::ds.regionalGeoBlocking}}</td>
+                    <td data-search="^{{::ds.remapText}}$">{{::ds.remapText}}</td>
+                    <td data-search="^{{::ds.routingName}}$">{{::ds.routingName}}</td>
+                    <td data-search="^{{::ds.signed}}$">{{::ds.signed}}</td>
+                    <td data-search="^{{::ds.signingAlgorithm}}$">{{::ds.signingAlgorithm}}</td>
+                    <td data-search="^{{::ds.tenant}}$">{{::ds.tenant}}</td>
+                    <td data-search="^{{::ds.trResponseHeaders}}$">{{::ds.trResponseHeaders}}</td>
+                    <td data-search="^{{::ds.trRequestHeaders}}$">{{::ds.trRequestHeaders}}</td>
+                    <td data-search="^{{::ds.type}}$">{{::ds.type}}</td>
+                    <td data-search="^{{::ds.xmlId}}$">{{::ds.xmlId}}</td>
+                </tr>
             </tbody>
         </table>
     </div>
diff --git a/traffic_portal/app/src/common/service/application/ApplicationService.js b/traffic_portal/app/src/common/service/application/ApplicationService.js
index 6dc2572..c064568 100644
--- a/traffic_portal/app/src/common/service/application/ApplicationService.js
+++ b/traffic_portal/app/src/common/service/application/ApplicationService.js
@@ -38,7 +38,8 @@ var ApplicationService = function($rootScope, $anchorScroll, $http, messageModel
 
         // jquery DataTables default overrides
         $.extend(true, $.fn.dataTable.defaults, {
-            "stateSave": true
+            "stateSave": true,
+            "scrollX": true
         });
 
         if (!storageAvailable('localStorage')) {
diff --git a/traffic_portal/app/src/common/service/utils/DeliveryServiceUtils.js b/traffic_portal/app/src/common/service/utils/DeliveryServiceUtils.js
index 8b647a3..028ce2e 100644
--- a/traffic_portal/app/src/common/service/utils/DeliveryServiceUtils.js
+++ b/traffic_portal/app/src/common/service/utils/DeliveryServiceUtils.js
@@ -32,6 +32,23 @@ var DeliveryServiceUtils = function($window, propertiesModel) {
 		2: "DROP"
 	};
 
+	this.geoProviders = {
+		0: "MaxMind",
+		1: "Neustar"
+	};
+
+	this.geoLimits = {
+		0: "None",
+		1: "CZF Only",
+		2: "CZF + Country Code(s)",
+	};
+
+	this.rrhs = {
+		0: "no cache",
+		1: "background_fetch",
+		2: "cache_range_requests"
+	};
+
 	this.openCharts = function(ds, $event) {
 		if ($event) {
 			$event.stopPropagation(); // this kills the click event so it doesn't trigger anything else
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 0dbc684..30267d8 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
@@ -99,6 +99,16 @@ describe('Traffic Portal Delivery Services Suite', function() {
 		expect(browser.getCurrentUrl().then(commonFunctions.urlPath)).toEqual(commonFunctions.urlPath(browser.baseUrl)+"#!/delivery-services");
 	});
 
+	it('should toggle the visibility of the first table column ', function() {
+		browser.driver.findElement(by.id('toggleColumns')).click();
+		let first = element.all(by.css('input[type=checkbox]')).first();
+		expect(first.isSelected()).toBe(true);
+		first.click();
+		expect(first.isSelected()).toBe(false);
+		let tableColumns = element.all(by.css('#deliveryServicesTable tr:first-child td'));
+		expect(tableColumns.count()).toBe(10);
+	});
+
 	it('should update the ANY_MAP delivery service', function() {
 		console.log('Updating the ANY_MAP delivery service for ' + mockVals.anyMapXmlId);
 		pageData.searchFilter.clear().then(function() {