You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by sh...@apache.org on 2022/08/25 15:19:28 UTC
[trafficcontrol] branch master updated: Add the ability to toggle sensitive data fields to common grids (#6990)
This is an automated email from the ASF dual-hosted git repository.
shamrick 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 3bfe8e7e34 Add the ability to toggle sensitive data fields to common grids (#6990)
3bfe8e7e34 is described below
commit 3bfe8e7e34c47db06587a1716e1e1a99b1dcf64b
Author: ocket8888 <oc...@apache.org>
AuthorDate: Thu Aug 25 09:19:23 2022 -0600
Add the ability to toggle sensitive data fields to common grids (#6990)
* Add the ability to toggle sensitive data fields to common grids
(cherry picked from commit f4dc033306bc1f0450da770013773cef6a8fa197)
* Fix tests checking for non-existent attribute
* try getting a better error message
* Refactor DS tests to get better error messages on every failure
* Fix using non-existent expectation
* Remove function that typescript says exists but protractor disagrees
* Fix missing closing div tag
* Fix broken CDNs DS table
* Fix servers DSs table
* Fix Service Category DS table
(cherry picked from commit 72dd9edba6f2a63c1d8d2eeab68cf64ece8beff1)
* Fix tenant DS table
(cherry picked from commit a5d23cfecf40174ed29e20fe0b9fd60ccb8a6970)
* Fix topologies DS table
* Fix types DS table
* Revert bad logical inversion
---
.../FormServiceCategoryController.js | 4 -
.../serviceCategory/form.serviceCategory.tpl.html | 2 +-
.../modules/table/agGrid/CommonGridController.js | 1103 +++++++++++---------
.../src/common/modules/table/agGrid/grid.tpl.html | 136 +--
.../TableCDNDeliveryServicesController.js | 15 +-
.../table.cdnDeliveryServices.tpl.html | 109 +-
.../table.deliveryServices.tpl.html | 1 +
.../TableServerDeliveryServicesController.js | 200 ++--
.../table.serverDeliveryServices.tpl.html | 116 +-
...bleServiceCategoryDeliveryServicesController.js | 13 +
.../table.serviceCategoryDeliveryServices.tpl.html | 112 +-
.../TableTenantDeliveryServicesController.js | 13 +
.../table.tenantDeliveryServices.tpl.html | 110 +-
.../TableTopologyDeliveryServicesController.js | 21 +-
.../table.topologyDeliveryServices.tpl.html | 110 +-
.../TableTypeDeliveryServicesController.js | 26 +-
.../table.typeDeliveryServices.tpl.html | 110 +-
traffic_portal/app/src/styles/main.scss | 6 +
.../test/integration/Data/deliveryservices.ts | 156 ++-
.../test/integration/PageObjects/BasePage.po.ts | 12 +-
.../PageObjects/DeliveryServicePage.po.ts | 361 +++----
.../integration/specs/DeliveryServices.spec.ts | 123 +--
22 files changed, 1217 insertions(+), 1642 deletions(-)
diff --git a/traffic_portal/app/src/common/modules/form/serviceCategory/FormServiceCategoryController.js b/traffic_portal/app/src/common/modules/form/serviceCategory/FormServiceCategoryController.js
index 26014e8583..341ee1a447 100644
--- a/traffic_portal/app/src/common/modules/form/serviceCategory/FormServiceCategoryController.js
+++ b/traffic_portal/app/src/common/modules/form/serviceCategory/FormServiceCategoryController.js
@@ -29,10 +29,6 @@ var FormServiceCategoryController = function(serviceCategory, $scope, $location,
$scope.hasPropertyError = formUtils.hasPropertyError;
- $scope.viewDSs = function() {
- $location.path('/service-categories/' + encodeURIComponent(serviceCategory.name) + '/delivery-services');
- };
-
};
FormServiceCategoryController.$inject = ['serviceCategory', '$scope', '$location', 'formUtils', 'stringUtils', 'locationUtils'];
diff --git a/traffic_portal/app/src/common/modules/form/serviceCategory/form.serviceCategory.tpl.html b/traffic_portal/app/src/common/modules/form/serviceCategory/form.serviceCategory.tpl.html
index 44274416fe..0bb4fa36cf 100644
--- a/traffic_portal/app/src/common/modules/form/serviceCategory/form.serviceCategory.tpl.html
+++ b/traffic_portal/app/src/common/modules/form/serviceCategory/form.serviceCategory.tpl.html
@@ -24,7 +24,7 @@ under the License.
<li class="active">{{serviceCategoryName}}</li>
</ol>
<div class="pull-right" role="group" ng-show="!settings.isNew">
- <button type=button class="btn btn-primary" title="View Delivery Services" ng-click="viewDSs()">View Delivery Services</button>
+ <a class="btn btn-primary" title="View Delivery Services" ng-href="#!/service-categories/{{serviceCategory.name}}/delivery-services">View Delivery Services</a>
</div>
<div class="clearfix"></div>
</div>
diff --git a/traffic_portal/app/src/common/modules/table/agGrid/CommonGridController.js b/traffic_portal/app/src/common/modules/table/agGrid/CommonGridController.js
index c8571f4f7d..4bedb383de 100644
--- a/traffic_portal/app/src/common/modules/table/agGrid/CommonGridController.js
+++ b/traffic_portal/app/src/common/modules/table/agGrid/CommonGridController.js
@@ -29,529 +29,598 @@
* @param {GridApi} api
*/
function setUpQueryParamFilter(params, columns, api) {
- for (const col of columns) {
- if (!Object.prototype.hasOwnProperty.call(col, "field")) {
- continue;
- }
- const filter = api.getFilterInstance(col.field);
- if (!filter) {
- continue;
- }
- const values = params.getAll(col.field);
- if (values.length < 1) {
- continue;
- }
-
- /** @type {"string" | "number" | "date"} */
- let colType;
- if (!Object.prototype.hasOwnProperty.call(col, "filter")) {
- colType = "string";
- } else if (typeof(col.filter) !== "string") {
- continue;
- } else {
- let bail = false;
- switch(col.filter) {
- case "agTextColumnFilter":
- colType = "string";
- break;
- case "agNumberColumnFilter":
- colType = "number";
- break;
- case "agDateColumnFilter":
- colType = "date";
- break;
- default:
- bail = true;
- break;
- }
- if (bail) {
- continue;
- }
- }
-
- let filterModel;
- switch(colType) {
- case "string":
- if (values.length === 1) {
- filterModel = {
- filter: values[0],
- type: "equals"
- }
- } else {
- filterModel = {
- operator: "OR",
- condition1: {
- filter: values[0],
- type: "equals"
- },
- condition2: {
- filter: values[1],
- type: "equals"
- }
- }
- }
- break;
- case "number":
- if (values.length === 1) {
- filterModel = {
- filter: parseInt(values[0], 10),
- type: "equals"
- }
- if (isNaN(filterModel.filter)) {
- continue;
- }
- } else {
- filterModel = {
- operator: "OR",
- condition1: {
- filter: parseInt(values[0], 10),
- type: "equals"
- },
- condition2: {
- filter: parseInt(values[1], 10),
- type: "equals"
- }
- }
- if (isNaN(filterModel.condition1.filter) || isNaN(filterModel.condition2.filter)) {
- continue;
- }
- }
- break;
- case "date":
- const date = new Date(values[0]);
- if (isNaN(date)) {
- continue;
- }
- const pad = num => String(num).padStart(2,"0");
- filterModel = {
- dateFrom: `${date.getUTCFullYear()}-${pad(date.getUTCMonth()+1)}-${pad(date.getUTCDate())} ${pad(date.getUTCHours())}:${pad(date.getUTCMinutes())}:${pad(date.getUTCSeconds())}`,
- type: "equals"
- }
- break;
- }
- filter.setModel(filterModel);
- filter.applyModel();
- }
+ for (const col of columns) {
+ if (!Object.prototype.hasOwnProperty.call(col, "field")) {
+ continue;
+ }
+ const filter = api.getFilterInstance(col.field);
+ if (!filter) {
+ continue;
+ }
+ const values = params.getAll(col.field);
+ if (values.length < 1) {
+ continue;
+ }
+
+ /** @type {"string" | "number" | "date"} */
+ let colType;
+ if (!Object.prototype.hasOwnProperty.call(col, "filter")) {
+ colType = "string";
+ } else if (typeof(col.filter) !== "string") {
+ continue;
+ } else {
+ let bail = false;
+ switch(col.filter) {
+ case "agTextColumnFilter":
+ colType = "string";
+ break;
+ case "agNumberColumnFilter":
+ colType = "number";
+ break;
+ case "agDateColumnFilter":
+ colType = "date";
+ break;
+ default:
+ bail = true;
+ break;
+ }
+ if (bail) {
+ continue;
+ }
+ }
+
+ let filterModel;
+ switch(colType) {
+ case "string":
+ if (values.length === 1) {
+ filterModel = {
+ filter: values[0],
+ type: "equals"
+ }
+ } else {
+ filterModel = {
+ operator: "OR",
+ condition1: {
+ filter: values[0],
+ type: "equals"
+ },
+ condition2: {
+ filter: values[1],
+ type: "equals"
+ }
+ }
+ }
+ break;
+ case "number":
+ if (values.length === 1) {
+ filterModel = {
+ filter: parseInt(values[0], 10),
+ type: "equals"
+ }
+ if (isNaN(filterModel.filter)) {
+ continue;
+ }
+ } else {
+ filterModel = {
+ operator: "OR",
+ condition1: {
+ filter: parseInt(values[0], 10),
+ type: "equals"
+ },
+ condition2: {
+ filter: parseInt(values[1], 10),
+ type: "equals"
+ }
+ }
+ if (isNaN(filterModel.condition1.filter) || isNaN(filterModel.condition2.filter)) {
+ continue;
+ }
+ }
+ break;
+ case "date":
+ const date = new Date(values[0]);
+ if (Number.isNaN(date.getTime())) {
+ continue;
+ }
+ const pad = num => String(num).padStart(2,"0");
+ filterModel = {
+ dateFrom: `${date.getUTCFullYear()}-${pad(date.getUTCMonth()+1)}-${pad(date.getUTCDate())} ${pad(date.getUTCHours())}:${pad(date.getUTCMinutes())}:${pad(date.getUTCSeconds())}`,
+ type: "equals"
+ }
+ break;
+ }
+ filter.setModel(filterModel);
+ filter.applyModel();
+ }
}
let CommonGridController = function ($scope, $document, $state, userModel, dateUtils) {
- this.entry = null;
- this.quickSearch = "";
- this.pageSize = 100;
- this.showMenu = false;
- this.menuStyle = {
- left: 0,
- top: 0
- };
- this.mouseDownSelectionText = "";
-
- // Bound Variables
- /** @type string */
- this.tableName = "";
- /** @type CGC.GridSettings */
- this.options = {};
- /** @type any[] */
- this.columns = [];
- /** @type any[] */
- this.data = [];
- /** @type any[] */
- this.selectedData = [];
- /** @type any */
- this.defaultData = {};
- /** @type CGC.DropDownOption[] */
- this.dropDownOptions = [];
- /** @type CGC.ContextMenuOption[] */
- this.contextMenuOptions = [];
- /** @type CGC.TitleButton */
- this.titleButton = {};
- /** @type CGC.TitleBreadCrumbs */
- this.breadCrumbs = [];
-
- function HTTPSCellRenderer() {}
- HTTPSCellRenderer.prototype.init = function(params) {
- this.eGui = document.createElement("a");
- this.eGui.href = "https://" + params.value;
- this.eGui.setAttribute("class", "link");
- this.eGui.setAttribute("target", "_blank");
- this.eGui.textContent = params.value;
- };
- HTTPSCellRenderer.prototype.getGui = function() {return this.eGui;};
-
- // browserify can't handle classes...
- function SSHCellRenderer() {}
- SSHCellRenderer.prototype.init = function(params) {
- this.eGui = document.createElement("a");
- this.eGui.href = "ssh://" + userModel.user.username + "@" + params.value;
- this.eGui.setAttribute("class", "link");
- this.eGui.textContent = params.value;
- };
- SSHCellRenderer.prototype.getGui = function() {return this.eGui;};
-
- function CheckCellRenderer() {}
- CheckCellRenderer.prototype.init = function(params) {
- this.eGui = document.createElement("i");
- if (params.value === null || params.value === undefined) {
- return;
- }
-
- this.eGui.setAttribute("aria-hidden", "true");
- this.eGui.setAttribute("title", String(params.value));
- this.eGui.classList.add("fa", "fa-lg");
- if (params.value) {
- this.eGui.classList.add("fa-check");
- } else {
- this.eGui.classList.add("fa-times");
- }
- };
- CheckCellRenderer.prototype.getGui = function() {return this.eGui;};
-
- function UpdateCellRenderer() {}
- UpdateCellRenderer.prototype.init = function(params) {
- this.eGui = document.createElement("i");
-
- this.eGui.setAttribute("aria-hidden", "true");
- this.eGui.setAttribute("title", String(params.value));
- this.eGui.classList.add("fa", "fa-lg");
- if (params.value) {
- this.eGui.classList.add("fa-clock-o");
- } else {
- this.eGui.classList.add("fa-check");
- }
- };
- UpdateCellRenderer.prototype.getGui = function() {return this.eGui;};
-
- function defaultTooltip(params) {
- return params.value;
- }
-
- function dateCellFormatterRelative(params) {
- return params.value ? dateUtils.getRelativeTime(params.value) : params.value;
- }
-
- function dateCellFormatterUTC(params) {
- return params.value ? params.value.toUTCString() : params.value;
- }
-
- this.hasContextItems = function() {
- return this.contextMenuOptions.length > 0;
- };
-
- this.$onInit = function() {
- let tableName = this.tableName;
- let self = this;
-
- if (self.defaultData !== undefined) {
- self.entry = self.defaultData;
- }
-
- for(let i = 0; i < self.columns.length; ++i) {
- if (self.columns[i].filter === "agDateColumnFilter") {
- if (self.columns[i].relative !== undefined && self.columns[i].relative === true) {
- self.columns[i].tooltipValueGetter = dateCellFormatterRelative;
- self.columns[i].valueFormatter = dateCellFormatterRelative;
- }
- else {
- self.columns[i].tooltipValueGetter = dateCellFormatterUTC;
- self.columns[i].valueFormatter = dateCellFormatterUTC;
- }
- }
- }
-
- // clicks outside the context menu will hide it
- $document.bind("click", function(e) {
- self.showMenu = false;
- e.stopPropagation();
- $scope.$apply();
- });
-
- this.gridOptions = {
- components: {
- httpsCellRenderer: HTTPSCellRenderer,
- sshCellRenderer: SSHCellRenderer,
- updateCellRenderer: UpdateCellRenderer,
- checkCellRenderer: CheckCellRenderer,
- },
- columnDefs: self.columns,
- enableCellTextSelection: true,
- suppressMenuHide: true,
- multiSortKey: 'ctrl',
- alwaysShowVerticalScroll: true,
- defaultColDef: {
- filter: true,
- sortable: true,
- resizable: true,
- tooltipValueGetter: defaultTooltip
- },
- rowClassRules: self.options.rowClassRules,
- rowData: self.data,
- pagination: true,
- paginationPageSize: self.pageSize,
- rowBuffer: 0,
- onColumnResized: function() {
- localStorage.setItem(tableName + "_table_columns", JSON.stringify(self.gridOptions.columnApi.getColumnState()));
- },
- colResizeDefault: "shift",
- tooltipShowDelay: 500,
- allowContextMenuWithControlKey: true,
- preventDefaultOnContextMenu: self.hasContextItems(),
- onCellMouseDown: function() {
- self.mouseDownSelectionText = window.getSelection().toString();
- },
- onCellContextMenu: function(params) {
- if (!self.hasContextItems()){
- return;
- }
- self.showMenu = true;
- self.menuStyle.left = String(params.event.clientX) + "px";
- self.menuStyle.top = String(params.event.clientY) + "px";
- self.menuStyle.bottom = "unset";
- self.menuStyle.right = "unset";
- $scope.$apply();
- const boundingRect = document.getElementById("context-menu").getBoundingClientRect();
-
- if (boundingRect.bottom > window.innerHeight){
- self.menuStyle.bottom = String(window.innerHeight - params.event.clientY) + "px";
- self.menuStyle.top = "unset";
- }
- if (boundingRect.right > window.innerWidth) {
- self.menuStyle.right = String(window.innerWidth - params.event.clientX) + "px";
- self.menuStyle.left = "unset";
- }
- self.entry = params.data;
- $scope.$apply();
- },
- onColumnVisible: function(params) {
- if (params.visible){
- return;
- }
- for (let column of params.columns) {
- if (column.filterActive) {
- const filterModel = self.gridOptions.api.getFilterModel();
- if (column.colId in filterModel) {
- delete filterModel[column.colId];
- self.gridOptions.api.setFilterModel(filterModel);
- }
- }
- }
- },
- onRowSelected: function() {
- self.selectedData = self.gridOptions.api.getSelectedRows();
- $scope.$apply();
- },
- onSelectionChanged: function() {
- self.selectedData = self.gridOptions.api.getSelectedRows();
- $scope.$apply();
- },
- onRowClicked: function(params) {
- if (params.event.target instanceof HTMLAnchorElement) {
- return;
- }
- const selection = window.getSelection().toString();
- if(self.options.onRowClick !== undefined && (selection === "" || selection === $scope.mouseDownSelectionText)) {
- self.options.onRowClick(params);
- $scope.$apply();
- }
- $scope.mouseDownSelectionText = "";
- },
- onFirstDataRendered: function() {
- if(self.options.selectRows) {
- self.gridOptions.rowSelection = self.options.selectRows ? "multiple" : "";
- self.gridOptions.rowMultiSelectWithClick = self.options.selectRows;
- self.gridOptions.api.forEachNode(node => {
- if (node.data[self.options.selectionProperty] === true) {
- node.setSelected(true, false);
- }
- });
- }
- try {
- const filterState = JSON.parse(localStorage.getItem(tableName + "_table_filters")) || {};
- self.gridOptions.api.setFilterModel(filterState);
- } catch (e) {
- console.error("Failure to load stored filter state:", e);
- }
- // Set up filters from query string paramters.
- const params = new URLSearchParams(globalThis.location.hash.split("?").slice(1).join("?"));
- setUpQueryParamFilter(params, self.columns, self.gridOptions.api);
- self.gridOptions.api.onFilterChanged();
-
- self.gridOptions.api.addEventListener("filterChanged", function() {
- localStorage.setItem(tableName + "_table_filters", JSON.stringify(self.gridOptions.api.getFilterModel()));
- });
- },
- onGridReady: function() {
- try {
- // need to create the show/hide column checkboxes and bind to the current visibility
- const colstates = JSON.parse(localStorage.getItem(tableName + "_table_columns"));
- if (colstates) {
- if (!self.gridOptions.columnApi.setColumnState(colstates)) {
- console.error("Failed to load stored column state: one or more columns not found");
- }
- } else {
- self.gridOptions.api.sizeColumnsToFit();
- }
- } catch (e) {
- console.error("Failure to retrieve required column info from localStorage (key=" + tableName + "_table_columns):", e);
- }
-
- try {
- const sortState = JSON.parse(localStorage.getItem(tableName + "_table_sort"));
- self.gridOptions.api.setSortModel(sortState);
- } catch (e) {
- console.error("Failure to load stored sort state:", e);
- }
-
- try {
- self.quickSearch = localStorage.getItem(tableName + "_quick_search");
- self.gridOptions.api.setQuickFilter(self.quickSearch);
- } catch (e) {
- console.error("Failure to load stored quick search:", e);
- }
-
- try {
- const ps = localStorage.getItem(tableName + "_page_size");
- if (ps && ps > 0) {
- self.pageSize = Number(ps);
- self.gridOptions.api.paginationSetPageSize(self.pageSize);
- }
- } catch (e) {
- console.error("Failure to load stored page size:", e);
- }
-
- try {
- const page = parseInt(localStorage.getItem(tableName + "_table_page"));
- if (page !== undefined && page > 0 && page <= $scope.gridOptions.api.paginationGetTotalPages()-1) {
- $scope.gridOptions.api.paginationGoToPage(page);
- }
- } catch (e) {
- console.error("Failed to load stored page number:", e);
- }
-
- self.gridOptions.api.addEventListener("sortChanged", function() {
- localStorage.setItem(tableName + "_table_sort", JSON.stringify(self.gridOptions.api.getSortModel()));
- });
-
- self.gridOptions.api.addEventListener("columnMoved", function() {
- localStorage.setItem(tableName + "_table_columns", JSON.stringify(self.gridOptions.columnApi.getColumnState()));
- });
-
- self.gridOptions.api.addEventListener("columnVisible", function() {
- self.gridOptions.api.sizeColumnsToFit();
- try {
- const colStates = self.gridOptions.columnApi.getColumnState();
- localStorage.setItem(tableName + "_table_columns", JSON.stringify(colStates));
- } catch (e) {
- console.error("Failed to store column defs to local storage:", e);
- }
- });
- }
- };
-
- };
-
- this.exportCSV = function() {
- const params = {
- allColumns: true,
- fileName: this.tableName + ".csv",
- };
- this.gridOptions.api.exportDataAsCsv(params);
- };
-
- this.toggleVisibility = function(col) {
- const visible = this.gridOptions.columnApi.getColumn(col).isVisible();
- this.gridOptions.columnApi.setColumnVisible(col, !visible);
- };
-
- this.onQuickSearchChanged = function() {
- this.gridOptions.api.setQuickFilter(this.quickSearch);
- localStorage.setItem(this.tableName + "_quick_search", this.quickSearch);
- };
-
- this.onPageSizeChanged = function() {
- const value = Number(this.pageSize);
- this.gridOptions.api.paginationSetPageSize(value);
- localStorage.setItem(this.tableName + "_page_size", value);
- };
-
- this.clearTableFilters = function() {
- // clear the quick search
- this.quickSearch = '';
- this.onQuickSearchChanged();
- // clear any column filters
- this.gridOptions.api.setFilterModel(null);
- };
-
- this.contextMenuClick = function(menu, $event) {
- $event.stopPropagation();
- menu.onClick(this.entry);
- };
-
- this.getHref = function(menu) {
- if (menu.href !== undefined){
- return menu.href;
- }
- return menu.getHref(this.entry);
- };
-
- this.contextIsDisabled = function(menu) {
- if (menu.isDisabled !== undefined) {
- return menu.isDisabled(this.entry);
- }
- return false;
- };
-
- this.bcGetText = function (bc) {
- if(bc.text !== undefined){
- return bc.text;
- }
- return bc.getText();
- };
-
- this.bcHasHref = function(bc) {
- return bc.href !== undefined || bc.getHref !== undefined;
- };
-
- this.bcGetHref = function(bc) {
- if(bc.href !== undefined) {
- return bc.href;
- }
- return bc.getHref();
- };
-
- this.getText = function (menu) {
- if (menu.text !== undefined){
- return menu.text;
- }
- return menu.getText(this.entry);
- };
-
- this.isShown = function (menu) {
- if (menu.shown === undefined){
- return true;
- }
- return menu.shown(this.entry);
- };
-
- $scope.refresh = function() {
- $state.reload(); // reloads all the resolves for the view
- };
+ this.entry = null;
+ this.quickSearch = "";
+ this.pageSize = 100;
+ this.showMenu = false;
+ /**
+ * @type {{
+ * bottom?: string | 0;
+ * left: string | 0;
+ * right?: string | 0;
+ * top: string | 0;
+ * }}
+ */
+ this.menuStyle = {
+ left: 0,
+ top: 0
+ };
+ this.mouseDownSelectionText = "";
+
+ // Bound Variables
+ /** @type string */
+ this.tableTitle = "";
+ /** @type string */
+ this.tableName = "";
+ /** @type CGC.GridSettings */
+ this.options = {};
+ /** @type any */
+ this.gridOptions = {};
+ /** @type any[] */
+ this.columns = [];
+ /** @type string[] */
+ this.sensitiveColumns = [];
+ /** @type any[] */
+ this.data = [];
+ /** @type any[] */
+ this.selectedData = [];
+ /** @type any */
+ this.defaultData = {};
+ /** @type CGC.DropDownOption[] */
+ this.dropDownOptions = [];
+ /** @type CGC.ContextMenuOption[] */
+ this.contextMenuOptions = [];
+ /** @type CGC.TitleButton */
+ this.titleButton = {};
+ /** @type CGC.TitleBreadCrumbs */
+ this.breadCrumbs = [];
+
+ function HTTPSCellRenderer() {}
+ HTTPSCellRenderer.prototype.init = function(params) {
+ this.eGui = document.createElement("a");
+ this.eGui.href = "https://" + params.value;
+ this.eGui.setAttribute("class", "link");
+ this.eGui.setAttribute("target", "_blank");
+ this.eGui.textContent = params.value;
+ };
+ HTTPSCellRenderer.prototype.getGui = function() {return this.eGui;};
+
+ // browserify can't handle classes...
+ function SSHCellRenderer() {}
+ SSHCellRenderer.prototype.init = function(params) {
+ this.eGui = document.createElement("a");
+ this.eGui.href = "ssh://" + userModel.user.username + "@" + params.value;
+ this.eGui.setAttribute("class", "link");
+ this.eGui.textContent = params.value;
+ };
+ SSHCellRenderer.prototype.getGui = function() {return this.eGui;};
+
+ function CheckCellRenderer() {}
+ CheckCellRenderer.prototype.init = function(params) {
+ this.eGui = document.createElement("i");
+ if (params.value === null || params.value === undefined) {
+ return;
+ }
+
+ this.eGui.setAttribute("aria-hidden", "true");
+ this.eGui.setAttribute("title", String(params.value));
+ this.eGui.classList.add("fa", "fa-lg");
+ if (params.value) {
+ this.eGui.classList.add("fa-check");
+ } else {
+ this.eGui.classList.add("fa-times");
+ }
+ };
+ CheckCellRenderer.prototype.getGui = function() {return this.eGui;};
+
+ function UpdateCellRenderer() {}
+ UpdateCellRenderer.prototype.init = function(params) {
+ this.eGui = document.createElement("i");
+
+ this.eGui.setAttribute("aria-hidden", "true");
+ this.eGui.setAttribute("title", String(params.value));
+ this.eGui.classList.add("fa", "fa-lg");
+ if (params.value) {
+ this.eGui.classList.add("fa-clock-o");
+ } else {
+ this.eGui.classList.add("fa-check");
+ }
+ };
+ UpdateCellRenderer.prototype.getGui = function() {return this.eGui;};
+
+ function defaultTooltip(params) {
+ return params.value;
+ }
+
+ function dateCellFormatterRelative(params) {
+ return params.value ? dateUtils.getRelativeTime(params.value) : params.value;
+ }
+
+ function dateCellFormatterUTC(params) {
+ return params.value ? params.value.toUTCString() : params.value;
+ }
+
+ this.hasContextItems = function() {
+ return this.contextMenuOptions.length > 0;
+ };
+
+ this.hasSensitiveColumns = function() {
+ return this.sensitiveColumns.length > 0;
+ }
+
+ /**
+ * @param {string} colID
+ */
+ this.isSensitive = function(colID) {
+ return this.sensitiveColumns.includes(colID);
+ }
+
+ this.sensitiveColumnsShown = false;
+
+ this.toggleSensitiveFields = function() {
+ if (this.sensitiveColumnsShown) {
+ return;
+ }
+ for (const col of this.gridOptions.columnApi.getAllColumns()) {
+ const id = col.getColId();
+ if (this.isSensitive(id)) {
+ this.gridOptions.columnApi.setColumnVisible(id, false);
+ }
+ }
+ };
+
+ this.getColumns = () => {
+ /** @type {{colId: string}[]} */
+ const cols = this.gridOptions.columnApi.getAllColumns();
+ if (!this.hasSensitiveColumns || this.sensitiveColumnsShown) {
+ return cols;
+ }
+ return cols.filter(c => !this.isSensitive(c.colId));
+ }
+
+ this.$onInit = () => {
+ const tableName = this.tableName;
+
+ if (this.defaultData !== undefined) {
+ this.entry = this.defaultData;
+ }
+
+ for(let i = 0; i < this.columns.length; ++i) {
+ if (this.columns[i].filter === "agDateColumnFilter") {
+ if (this.columns[i].relative) {
+ this.columns[i].tooltipValueGetter = dateCellFormatterRelative;
+ this.columns[i].valueFormatter = dateCellFormatterRelative;
+ }
+ else {
+ this.columns[i].tooltipValueGetter = dateCellFormatterUTC;
+ this.columns[i].valueFormatter = dateCellFormatterUTC;
+ }
+ }
+ }
+
+ // clicks outside the context menu will hide it
+ $document.bind("click", e => {
+ this.showMenu = false;
+ e.stopPropagation();
+ $scope.$apply();
+ });
+
+ this.gridOptions = {
+ components: {
+ httpsCellRenderer: HTTPSCellRenderer,
+ sshCellRenderer: SSHCellRenderer,
+ updateCellRenderer: UpdateCellRenderer,
+ checkCellRenderer: CheckCellRenderer,
+ },
+ columnDefs: this.columns,
+ enableCellTextSelection: true,
+ suppressMenuHide: true,
+ multiSortKey: 'ctrl',
+ alwaysShowVerticalScroll: true,
+ defaultColDef: {
+ filter: true,
+ sortable: true,
+ resizable: true,
+ tooltipValueGetter: defaultTooltip
+ },
+ rowClassRules: this.options.rowClassRules,
+ rowData: this.data,
+ pagination: true,
+ paginationPageSize: this.pageSize,
+ rowBuffer: 0,
+ onColumnResized: () => {
+ /** @type {{colId: string; hide?: boolean | null}[]} */
+ const states = this.gridOptions.columnApi.getColumnState();
+ for (const state of states) {
+ state.hide = state.hide || this.isSensitive(state.colId);
+ }
+ localStorage.setItem(tableName + "_table_columns", JSON.stringify(states));
+ },
+ colResizeDefault: "shift",
+ tooltipShowDelay: 500,
+ allowContextMenuWithControlKey: true,
+ preventDefaultOnContextMenu: this.hasContextItems(),
+ onCellMouseDown: () => {
+ const selection = window.getSelection();
+ if (!selection) {
+ this.mouseDownSelectionText = "";
+ } else {
+ this.mouseDownSelectionText = selection.toString();
+ }
+ },
+ onCellContextMenu: params => {
+ if (!this.hasContextItems()){
+ return;
+ }
+ this.showMenu = true;
+ this.menuStyle.left = String(params.event.clientX) + "px";
+ this.menuStyle.top = String(params.event.clientY) + "px";
+ this.menuStyle.bottom = "unset";
+ this.menuStyle.right = "unset";
+ $scope.$apply();
+ const boundingRect = document.getElementById("context-menu")?.getBoundingClientRect();
+ if (!boundingRect) {
+ throw new Error("no bounding rectangle for context-menu; element possibly missing");
+ }
+
+ if (boundingRect.bottom > window.innerHeight){
+ this.menuStyle.bottom = String(window.innerHeight - params.event.clientY) + "px";
+ this.menuStyle.top = "unset";
+ }
+ if (boundingRect.right > window.innerWidth) {
+ this.menuStyle.right = String(window.innerWidth - params.event.clientX) + "px";
+ this.menuStyle.left = "unset";
+ }
+ this.entry = params.data;
+ $scope.$apply();
+ },
+ onColumnVisible: params => {
+ if (params.visible){
+ return;
+ }
+ for (let column of params.columns) {
+ if (column.filterActive) {
+ const filterModel = this.gridOptions.api.getFilterModel();
+ if (column.colId in filterModel) {
+ delete filterModel[column.colId];
+ this.gridOptions.api.setFilterModel(filterModel);
+ }
+ }
+ }
+ },
+ onRowSelected: () => {
+ this.selectedData = this.gridOptions.api.getSelectedRows();
+ $scope.$apply();
+ },
+ onSelectionChanged: () => {
+ this.selectedData = this.gridOptions.api.getSelectedRows();
+ $scope.$apply();
+ },
+ onRowClicked: params => {
+ if (params.event.target instanceof HTMLAnchorElement) {
+ return;
+ }
+ const selection = window.getSelection();
+ if (this.options.onRowClick !== undefined) {
+ if (!selection || selection.toString() === "" || selection === $scope.mouseDownSelectionText) {
+ this.options.onRowClick(params);
+ $scope.$apply();
+ }
+ }
+ $scope.mouseDownSelectionText = "";
+ },
+ onFirstDataRendered: () => {
+ if(this.options.selectRows) {
+ this.gridOptions.rowSelection = this.options.selectRows ? "multiple" : "";
+ this.gridOptions.rowMultiSelectWithClick = this.options.selectRows;
+ this.gridOptions.api.forEachNode(node => {
+ if (node.data[this.options.selectionProperty] === true) {
+ node.setSelected(true, false);
+ }
+ });
+ }
+ try {
+ const filterState = JSON.parse(localStorage.getItem(tableName + "_table_filters") ?? "{}") || {};
+ this.gridOptions.api.setFilterModel(filterState);
+ } catch (e) {
+ console.error("Failure to load stored filter state:", e);
+ }
+ // Set up filters from query string paramters.
+ const params = new URLSearchParams(globalThis.location.hash.split("?").slice(1).join("?"));
+ setUpQueryParamFilter(params, this.columns, this.gridOptions.api);
+ this.gridOptions.api.onFilterChanged();
+
+ this.gridOptions.api.addEventListener("filterChanged", () => {
+ localStorage.setItem(tableName + "_table_filters", JSON.stringify(this.gridOptions.api.getFilterModel()));
+ });
+ },
+ onGridReady: () => {
+ try {
+ // need to create the show/hide column checkboxes and bind to the current visibility
+ const colstates = JSON.parse(localStorage.getItem(tableName + "_table_columns") ?? "null");
+ if (colstates) {
+ if (!this.gridOptions.columnApi.setColumnState(colstates)) {
+ console.error("Failed to load stored column state: one or more columns not found");
+ }
+ } else {
+ this.gridOptions.api.sizeColumnsToFit();
+ }
+ } catch (e) {
+ console.error("Failure to retrieve required column info from localStorage (key=" + tableName + "_table_columns):", e);
+ }
+
+ try {
+ const sortState = JSON.parse(localStorage.getItem(tableName + "_table_sort") ?? "{}");
+ this.gridOptions.api.setSortModel(sortState);
+ } catch (e) {
+ console.error("Failure to load stored sort state:", e);
+ }
+
+ try {
+ this.quickSearch = localStorage.getItem(tableName + "_quick_search") ?? "";
+ this.gridOptions.api.setQuickFilter(this.quickSearch);
+ } catch (e) {
+ console.error("Failure to load stored quick search:", e);
+ }
+
+ try {
+ const ps = Number(localStorage.getItem(tableName + "_page_size"));
+ if (ps > 0) {
+ this.pageSize = Number(ps);
+ this.gridOptions.api.paginationSetPageSize(this.pageSize);
+ }
+ } catch (e) {
+ console.error("Failure to load stored page size:", e);
+ }
+
+ try {
+ const page = parseInt(localStorage.getItem(tableName + "_table_page") ?? "0", 10);
+ if (page > 0 && page <= $scope.gridOptions.api.paginationGetTotalPages()-1) {
+ $scope.gridOptions.api.paginationGoToPage(page);
+ }
+ } catch (e) {
+ console.error("Failed to load stored page number:", e);
+ }
+
+ this.gridOptions.api.addEventListener("sortChanged", () => {
+ localStorage.setItem(tableName + "_table_sort", JSON.stringify(this.gridOptions.api.getSortModel()));
+ });
+
+ this.gridOptions.api.addEventListener("columnMoved", () => {
+ /** @type {{colId: string; hide?: boolean | null}[]} */
+ const states = this.gridOptions.columnApi.getColumnState();
+ for (const state of states) {
+ state.hide = state.hide || this.isSensitive(state.colId);
+ }
+
+ localStorage.setItem(tableName + "_table_columns", JSON.stringify(this.gridOptions.columnApi.getColumnState()));
+ });
+
+ this.gridOptions.api.addEventListener("columnVisible", () => {
+ this.gridOptions.api.sizeColumnsToFit();
+ try {
+ const colStates = this.gridOptions.columnApi.getColumnState();
+ localStorage.setItem(tableName + "_table_columns", JSON.stringify(colStates));
+ } catch (e) {
+ console.error("Failed to store column defs to local storage:", e);
+ }
+ });
+ }
+ };
+
+ };
+
+ this.exportCSV = function() {
+ const params = {
+ allColumns: true,
+ fileName: this.tableName + ".csv",
+ };
+ this.gridOptions.api.exportDataAsCsv(params);
+ };
+
+ this.toggleVisibility = function(col) {
+ const visible = this.gridOptions.columnApi.getColumn(col).isVisible();
+ this.gridOptions.columnApi.setColumnVisible(col, !visible);
+ };
+
+ this.onQuickSearchChanged = function() {
+ this.gridOptions.api.setQuickFilter(this.quickSearch);
+ localStorage.setItem(this.tableName + "_quick_search", this.quickSearch);
+ };
+
+ this.onPageSizeChanged = function() {
+ const value = Number(this.pageSize);
+ this.gridOptions.api.paginationSetPageSize(value);
+ localStorage.setItem(this.tableName + "_page_size", value.toString());
+ };
+
+ this.clearTableFilters = () => {
+ // clear the quick search
+ this.quickSearch = '';
+ this.onQuickSearchChanged();
+ // clear any column filters
+ this.gridOptions.api.setFilterModel(null);
+ };
+
+ this.contextMenuClick = function(menu, $event) {
+ $event.stopPropagation();
+ menu.onClick(this.entry);
+ };
+
+ this.getHref = function(menu) {
+ if (menu.href !== undefined){
+ return menu.href;
+ }
+ return menu.getHref(this.entry);
+ };
+
+ this.contextIsDisabled = function(menu) {
+ if (menu.isDisabled !== undefined) {
+ return menu.isDisabled(this.entry);
+ }
+ return false;
+ };
+
+ this.bcGetText = function (bc) {
+ if(bc.text !== undefined){
+ return bc.text;
+ }
+ return bc.getText();
+ };
+
+ this.bcHasHref = function(bc) {
+ return bc.href !== undefined || bc.getHref !== undefined;
+ };
+
+ this.bcGetHref = function(bc) {
+ if(bc.href !== undefined) {
+ return bc.href;
+ }
+ return bc.getHref();
+ };
+
+ this.getText = function (menu) {
+ if (menu.text !== undefined){
+ return menu.text;
+ }
+ return menu.getText(this.entry);
+ };
+
+ this.isShown = function (menu) {
+ if (menu.shown === undefined){
+ return true;
+ }
+ return menu.shown(this.entry);
+ };
+
+ $scope.refresh = function() {
+ $state.reload(); // reloads all the resolves for the view
+ };
};
angular.module("trafficPortal.table").component("commonGridController", {
- templateUrl: "common/modules/table/agGrid/grid.tpl.html",
- controller: CommonGridController,
- bindings: {
- tableTitle: "@",
- tableName: "@",
- options: "<",
- columns: "<",
- data: "<",
- selectedData: "=?",
- dropDownOptions: "<?",
- contextMenuOptions: "<?",
- defaultData: "<?",
- titleButton: "<?",
- breadCrumbs: "<?"
- }
+ templateUrl: "common/modules/table/agGrid/grid.tpl.html",
+ controller: CommonGridController,
+ bindings: {
+ tableTitle: "@",
+ tableName: "@",
+ options: "<",
+ columns: "<",
+ data: "<",
+ selectedData: "=?",
+ dropDownOptions: "<?",
+ contextMenuOptions: "<?",
+ defaultData: "<?",
+ titleButton: "<?",
+ breadCrumbs: "<?",
+ sensitiveColumns: "<?"
+ }
});
CommonGridController.$inject = ["$scope", "$document", "$state", "userModel", "dateUtils"];
diff --git a/traffic_portal/app/src/common/modules/table/agGrid/grid.tpl.html b/traffic_portal/app/src/common/modules/table/agGrid/grid.tpl.html
index 9b8bda766b..68866af084 100644
--- a/traffic_portal/app/src/common/modules/table/agGrid/grid.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/agGrid/grid.tpl.html
@@ -18,75 +18,79 @@ under the License.
-->
<div class="x_title grid-comp">
- <div class="pull-left">
- <ol class="breadcrumb pull-left" ng-if="$ctrl.breadCrumbs !== undefined">
- <li ng-repeat="bc in $ctrl.breadCrumbs track by $index" ng-class="{'active': ($index+1 === $ctrl.breadCrumbs.length)}">
- <a ng-if="$ctrl.bcHasHref(bc)" ng-href="{{ $ctrl.bcGetHref(bc) }}">{{ $ctrl.bcGetText(bc) }}</a>
- <span class="bc" ng-if="!$ctrl.bcHasHref(bc)">{{ $ctrl.bcGetText(bc) }}</span>
- </li>
- </ol>
- <ol class="breadcrumb pull-left" ng-if="$ctrl.breadCrumbs === undefined || $ctrl.breadCrumbs.length < 1">
- <li class="active" ng-if="$ctrl.tableTitle">
- {{ $ctrl.tableTitle }}
- </li>
- </ol>
- <button ng-if="$ctrl.titleButton !== undefined" type="button" class="btn btn-link"
- ng-click="$ctrl.titleButton.onClick()">{{ $ctrl.titleButton.getText() }}</button>
- <span ng-if="$ctrl.options.selectRows">{{ $ctrl.selectedData.length }} row(s) selected</span>
- </div>
- <div class="pull-right">
- <div class="form-inline" role="search">
- <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="$ctrl.quickSearch" ng-change="$ctrl.onQuickSearchChanged()" aria-label="Search"/>
- <div class="input-group text-input">
- <span class="input-group-addon">
- <label for="pageSize">Page size</label>
- </span>
- <input id="pageSize" name="pageSize" type="number" min="1" class="form-control" placeholder="100" ng-model="$ctrl.pageSize" ng-change="$ctrl.onPageSizeChanged()" />
- </div>
- <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
- <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- <i class="fa fa-columns"></i>
- <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 $ctrl.gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
- <div class="checkbox">
- <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="$ctrl.toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
- </div>
- </li>
- </menu>
- </div>
- <button class="btn btn-default" title="Refresh" ng-if="$ctrl.options.refreshable" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
- <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
- <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- More
- <span class="caret"></span>
- </button>
- <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li ng-repeat="dd in $ctrl.dropDownOptions" name="{{ dd.name }}" role="menuitem" ng-class="{'divider': dd.type == 0}" ng-if="$ctrl.isShown(dd)">
- <button ng-if="dd.type == 1" class="menu-item-button" type="button" ng-click="dd.onClick($ctrl.entry)">{{ $ctrl.getText(dd) }}</button>
- <a ng-if="dd.type == 2" href="{{ $ctrl.getHref(dd) }}">{{ dd.text }}</a>
- </li>
- <li ng-if="$ctrl.dropDownOptions.length > 0" class="divider"></li>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="$ctrl.clearTableFilters()">Clear Table Filters</button></li>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="$ctrl.exportCSV()">Export CSV</button></li>
- </ul>
- </div>
- </div>
- </div>
- <div class="clearfix"></div>
+ <div class="pull-left">
+ <ol class="breadcrumb pull-left" ng-if="$ctrl.breadCrumbs !== undefined">
+ <li ng-repeat="bc in $ctrl.breadCrumbs track by $index" ng-class="{'active': ($index+1 === $ctrl.breadCrumbs.length)}">
+ <a ng-if="$ctrl.bcHasHref(bc)" ng-href="{{ $ctrl.bcGetHref(bc) }}">{{ $ctrl.bcGetText(bc) }}</a>
+ <span class="bc" ng-if="!$ctrl.bcHasHref(bc)">{{ $ctrl.bcGetText(bc) }}</span>
+ </li>
+ </ol>
+ <ol class="breadcrumb pull-left" ng-if="$ctrl.breadCrumbs === undefined || $ctrl.breadCrumbs.length < 1">
+ <li class="active" ng-if="$ctrl.tableTitle">
+ {{ $ctrl.tableTitle }}
+ </li>
+ </ol>
+ <button ng-if="$ctrl.titleButton !== undefined" type="button" class="btn btn-link"
+ ng-click="$ctrl.titleButton.onClick()">{{ $ctrl.titleButton.getText() }}</button>
+ <span ng-if="$ctrl.options.selectRows">{{ $ctrl.selectedData.length }} row(s) selected</span>
+ </div>
+ <div class="pull-right">
+ <div class="form-inline" role="search">
+ <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="$ctrl.quickSearch" ng-change="$ctrl.onQuickSearchChanged()" aria-label="Search"/>
+ <div class="input-group text-input">
+ <span class="input-group-addon">
+ <label for="pageSize">Page size</label>
+ </span>
+ <input id="pageSize" name="pageSize" type="number" min="1" class="form-control" placeholder="100" ng-model="$ctrl.pageSize" ng-change="$ctrl.onPageSizeChanged()" />
+ </div>
+ <div class="input-group text-input" ng-if="$ctrl.hasSensitiveColumns()">
+ <label for="showSensitive" style="color: #333; font-size: 14px">Show Sensitive Data Columns</label>
+ <input id="showSensitive" name="showSensitive" type="checkbox" ng-model="$ctrl.sensitiveColumnsShown" ng-change="$ctrl.toggleSensitiveFields()"/>
+ </div>
+ <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
+ <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+ <i class="fa fa-columns"></i>
+ <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 $ctrl.getColumns() | orderBy:'colDef.headerName'">
+ <div class="checkbox">
+ <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="$ctrl.toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
+ </div>
+ </li>
+ </menu>
+ </div>
+ <button class="btn btn-default" title="Refresh" ng-if="$ctrl.options.refreshable" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
+ <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
+ <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
+ More
+ <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
+ <li ng-repeat="dd in $ctrl.dropDownOptions" name="{{ dd.name }}" role="menuitem" ng-class="{'divider': dd.type == 0}" ng-if="$ctrl.isShown(dd)">
+ <button ng-if="dd.type == 1" class="menu-item-button" type="button" ng-click="dd.onClick($ctrl.entry)">{{ $ctrl.getText(dd) }}</button>
+ <a ng-if="dd.type == 2" href="{{ $ctrl.getHref(dd) }}">{{ dd.text }}</a>
+ </li>
+ <li ng-if="$ctrl.dropDownOptions.length > 0" class="divider"></li>
+ <li role="menuitem"><button class="menu-item-button" type="button" ng-click="$ctrl.clearTableFilters()">Clear Table Filters</button></li>
+ <li role="menuitem"><button class="menu-item-button" type="button" ng-click="$ctrl.exportCSV()">Export CSV</button></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ <div class="clearfix"></div>
</div>
<div class="x_content">
- <div style="height: 740px;" ag-grid="$ctrl.gridOptions" class="jobs-table ag-theme-alpine"></div>
+ <div style="height: 740px;" ag-grid="$ctrl.gridOptions" class="jobs-table ag-theme-alpine"></div>
</div>
<menu id="context-menu" class="dropdown-menu" ng-style="$ctrl.menuStyle" type="contextmenu" ng-show="$ctrl.showMenu">
- <ul>
- <li role="menuitem" ng-repeat="menu in $ctrl.contextMenuOptions" ng-if="$ctrl.isShown(menu)">
- <hr ng-if="menu.type == 0" class="divider"/>
- <button ng-if="menu.type == 1" type="button" ng-disabled="$ctrl.contextIsDisabled(menu)" type="button" ng-click="$ctrl.contextMenuClick(menu, $event)">{{ $ctrl.getText(menu) }}</button>
- <a ng-if="menu.type == 2 && !$ctrl.contextIsDisabled(menu)" href="{{ $ctrl.getHref(menu) }}" target="{{ menu.newTab ? '_blank' : '' }}">{{ $ctrl.getText(menu) }}</a>
- <button ng-if="menu.type == 2 && $ctrl.contextIsDisabled(menu)" type="button" disabled>{{ $ctrl.getText(menu) }}</a>
- </li>
- </ul>
+ <ul>
+ <li role="menuitem" ng-repeat="menu in $ctrl.contextMenuOptions" ng-if="$ctrl.isShown(menu)">
+ <hr ng-if="menu.type == 0" class="divider"/>
+ <button ng-if="menu.type == 1" type="button" ng-disabled="$ctrl.contextIsDisabled(menu)" type="button" ng-click="$ctrl.contextMenuClick(menu, $event)">{{ $ctrl.getText(menu) }}</button>
+ <a ng-if="menu.type == 2 && !$ctrl.contextIsDisabled(menu)" href="{{ $ctrl.getHref(menu) }}" target="{{ menu.newTab ? '_blank' : '' }}">{{ $ctrl.getText(menu) }}</a>
+ <button ng-if="menu.type == 2 && $ctrl.contextIsDisabled(menu)" type="button" disabled>{{ $ctrl.getText(menu) }}</a>
+ </li>
+ </ul>
</menu>
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 23a22e02c6..5c650c9fa1 100644
--- a/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/TableCDNDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/TableCDNDeliveryServicesController.js
@@ -17,12 +17,25 @@
* under the License.
*/
-var TableCDNDeliveryServicesController = function(cdn, deliveryServices, filter, $controller, $scope) {
+function TableCDNDeliveryServicesController(cdn, deliveryServices, filter, $controller, $scope) {
// extends the TableDeliveryServicesController to inherit common methods
angular.extend(this, $controller('TableDeliveryServicesController', { tableName: 'cdnDS', deliveryServices: deliveryServices, filter: filter, $scope: $scope }));
$scope.cdn = cdn;
+ $scope.breadCrumbs = [
+ {
+ href: "#!/cdns",
+ text: "CDNs"
+ },
+ {
+ href: `#!/cdns/${cdn.id}`,
+ text: cdn.name
+ },
+ {
+ text: "Delivery Services"
+ }
+ ];
};
TableCDNDeliveryServicesController.$inject = ['cdn', 'deliveryServices', 'filter', '$controller', '$scope'];
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 00dd7961f1..1f85e4352f 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
@@ -18,103 +18,14 @@ under the License.
-->
<div class="x_panel">
- <div class="x_title">
- <ol class="breadcrumb pull-left">
- <li><a href="#!/cdns">CDNs</a></li>
- <li><a ng-href="#!/cdns/{{cdn.id}}">{{::cdn.name}}</a></li>
- <li class="active">Delivery Services</li>
- </ol>
- <div class="pull-right">
- <div class="form-inline" role="search">
- <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
- <div class="input-group text-input">
- <span class="input-group-addon">
- <label for="pageSize">Page size</label>
- </span>
- <input id="pageSize" name="pageSize" type="number" min="1" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
- </div>
- <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
- <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- <i class="fa fa-columns"></i>
- <span class="caret"></span>
- </button>
- <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
- <div class="checkbox">
- <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
- </div>
- </li>
- </menu>
- </div>
- <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
- <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- More
- <span class="caret"></span>
- </button>
- <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearTableFilters()">Clear Table Filters</button></li>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
- </ul>
- </div>
- </div>
- </div>
- <div class="clearfix"></div>
- </div>
- <div class="x_content">
- <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
- </div>
+ <common-grid-controller
+ bread-crumbs="breadCrumbs"
+ table-name="{{tableName}}"
+ options="options"
+ data="deliveryServices"
+ columns="columns"
+ drop-down-options="dropDownOptions"
+ context-menu-options="contextMenuOptions"
+ >
+ </common-grid-controller>
</div>
-
-<menu id="context-menu" class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
- <ul>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}" target="_blank">Open {{ deliveryService.xmlId }} in New Tab</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}">Edit</a>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="clone(deliveryService, $event)">Clone</button>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="confirmDelete(deliveryService, $event)">Delete</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <button type="button" ng-click="viewCharts(deliveryService, $event)">View Charts</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/ssl-keys?dsType={{deliveryService.type}}">Manage SSL Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/url-sig-keys?dsType={{deliveryService.type}}">Manage URL Sig Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/uri-signing-keys?dsType={{deliveryService.type}}">Manage URI Signing Keys</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/jobs?dsType={{deliveryService.type}}">Manage Invalidation Requests</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') == -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/origins?dsType={{deliveryService.type}}">Manage Origins</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/regexes?dsType={{deliveryService.type}}">Manage Regexes</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('DNS') != -1 || deliveryService.type.indexOf('HTTP') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/required-server-capabilities?dsType={{deliveryService.type}}">Manage Required Server Capabilities</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/servers?dsType={{deliveryService.type}}">Manage Servers</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/targets?dsType={{deliveryService.type}}">Manage Targets</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/static-dns-entries?dsType={{deliveryService.type}}">Manage Static DNS Entries</a>
- </li>
- </ul>
-</menu>
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 b532ce2fbb..dd941b8fa9 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
@@ -28,3 +28,4 @@ under the License.
context-menu-options="contextMenuOptions"
>
</common-grid-controller>
+</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 98f0e788a6..8f5397c6d6 100644
--- a/traffic_portal/app/src/common/modules/table/serverDeliveryServices/TableServerDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/serverDeliveryServices/TableServerDeliveryServicesController.js
@@ -1,130 +1,162 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
+ * or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
+ * regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
+ * with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
+ * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
-var TableServerDeliveryServicesController = function(server, deliveryServices, filter, $controller, $scope, $state, $uibModal, dateUtils, deliveryServiceUtils, locationUtils, serverUtils, deliveryServiceService, serverService) {
+function TableServerDeliveryServicesController(server, deliveryServices, filter, $controller, $scope, $uibModal, locationUtils, serverUtils, deliveryServiceService, serverService) {
// extends the TableDeliveryServicesController to inherit common methods
- angular.extend(this, $controller('TableDeliveryServicesController', { tableName: 'serverDS', deliveryServices: deliveryServices, filter: filter, $scope: $scope }));
+ angular.extend(this, $controller("TableDeliveryServicesController", { tableName: "serverDS", deliveryServices, filter, $scope }));
- var removeDeliveryService = function(dsId) {
- deliveryServiceService.deleteDeliveryServiceServer(dsId, $scope.server.id)
- .then(
- function() {
- $scope.refresh();
- }
- );
+ server = Array.isArray(server) ? server[0] : server;
+
+ /**
+ * Removes the assignment of a Delivery Service to the table's server.
+ *
+ * @param {number} dsId The ID of the Delivery Service being removed.
+ */
+ async function removeDeliveryService(dsId) {
+ await deliveryServiceService.deleteDeliveryServiceServer(dsId, $scope.server.id);
+ $scope.refresh();
};
- $scope.server = server[0];
+ $scope.breadCrumbs = [
+ {
+ href: "#!/servers",
+ text: "Servers"
+ },
+ {
+ href: `#!/servers/${server.id}`,
+ text: server.hostName
+ },
+ {
+ text: "Delivery Services"
+ }
+ ];
- $scope.isEdge = serverUtils.isEdge;
+ $scope.dropDownOptions = [
+ {
+ onClick: cloneAssignments,
+ text: "Clone Delivery Service Assignments",
+ type: 1
+ }
+ ];
- $scope.isOrigin = serverUtils.isOrigin;
+ if (serverUtils.isEdge(server) || serverUtils.isOrigin(server)) {
+ $scope.dropDownOptions.unshift({
+ onClick: selectDeliveryServices,
+ text: "Assign Delivery Services",
+ type: 1
+ });
+ }
- $scope.confirmRemoveDS = function(ds, event) {
- event.stopPropagation();
- var params = {
- title: 'Remove Delivery Service from Server?',
- message: 'Are you sure you want to remove ' + ds.xmlId + ' from this server?'
+ /**
+ * Asks a user for confirmation before removing a Delivery Service assignment
+ * from the table's server.
+ *
+ * @param {{id: number; xmlId: string}} ds The Delivery Service being removed.
+ */
+ async function confirmRemoveDS(ds) {
+ const 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;
- }
- }
+ const modalInstance = $uibModal.open({
+ templateUrl: "common/modules/dialog/confirm/dialog.confirm.tpl.html",
+ controller: "DialogConfirmController",
+ size: "md",
+ resolve: { params }
});
- modalInstance.result.then(function() {
+ try {
+ await modalInstance.result;
removeDeliveryService(ds.id);
- }, function () {
+ } catch {
// do nothing
- });
+ }
};
- $scope.cloneDsAssignments = function() {
- var params = {
- title: 'Clone Delivery Service Assignments',
- message: "Please select another " + $scope.server.type + " cache to assign these " + deliveryServices.length + " delivery services to." +
+ $scope.contextMenuOptions.splice(1, 0, {
+ onClick: confirmRemoveDS,
+ getText: ds => `Remove ${ds.xmlId}`,
+ type: 1
+ });
+
+ async function cloneAssignments() {
+ const params = {
+ title: "Clone Delivery Service Assignments",
+ message: `Please select another ${server.type} cache to which to assign these ${deliveryServices.length} Delivery Services.` +
"<br>" +
"<br>" +
- "<strong>WARNING THIS CANNOT BE UNDONE</strong> - Any delivery services currently assigned to the selected cache will be lost and replaced with these " + deliveryServices.length + " delivery service assignments.",
- labelFunction: function(item) { return item['hostName'] + '.' + item['domainName'] }
+ `<strong class="uppercase">Warning this cannot be undone</strong> - Any Delivery Services currently assigned to the selected cache will be lost and replaced with these ${deliveryServices.length} Delivery Service assignments.`,
+ labelFunction: item => `${item.hostName}.${item.domainName}`
};
- var modalInstance = $uibModal.open({
- templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
- controller: 'DialogSelectController',
- size: 'md',
+
+ const modalInstance = $uibModal.open({
+ templateUrl: "common/modules/dialog/select/dialog.select.tpl.html",
+ controller: "DialogSelectController",
+ size: "md",
resolve: {
- params: function () {
- return params;
- },
- collection: function(serverService) {
- return serverService.getServers({ type: $scope.server.type, orderby: 'hostName', cdn: $scope.server.cdnId }).then(function(xs){return xs.filter(function(x){return x.id!=$scope.server.id})}, function(err){throw err});
+ params,
+ collection: async () => {
+ const opts = {
+ type: server.type,
+ orderby: "hostName",
+ cdn: server.cdnId
+ };
+ const ss = await serverService.getServers(opts);
+ return ss.filter(s => s.id !== server.id);
}
}
});
- modalInstance.result.then(function(selectedServer) {
- var dsIds = _.pluck(deliveryServices, 'id');
- serverService.assignDeliveryServices(selectedServer, dsIds, true, true)
- .then(
- function() {
- locationUtils.navigateToPath('/servers/' + selectedServer.id + '/delivery-services');
- }
- );
- }, function () {
- // do nothing
- });
+
+ let selectedServer;
+ try {
+ selectedServer = await modalInstance.result;
+ } catch {
+ return;
+ }
+ const dsIds = deliveryServices.map(ds=>ds.id);
+ await serverService.assignDeliveryServices(selectedServer, dsIds, true, true);
+ locationUtils.navigateToPath(`/servers/${selectedServer.id}/delivery-services`);
};
- $scope.selectDeliveryServices = function() {
- var modalInstance = $uibModal.open({
- templateUrl: 'common/modules/table/serverDeliveryServices/table.assignDeliveryServices.tpl.html',
- controller: 'TableAssignDeliveryServicesController',
- size: 'lg',
+ async function selectDeliveryServices() {
+ const modalInstance = $uibModal.open({
+ templateUrl: "common/modules/table/serverDeliveryServices/table.assignDeliveryServices.tpl.html",
+ controller: "TableAssignDeliveryServicesController",
+ size: "lg",
resolve: {
- server: function() {
- return $scope.server;
- },
- deliveryServices: function(deliveryServiceService) {
- return deliveryServiceService.getDeliveryServices({ cdn: $scope.server.cdnId });
- },
- assignedDeliveryServices: function() {
- return deliveryServices;
- }
+ server: () => server,
+ deliveryServices: deliveryServiceService => deliveryServiceService.getDeliveryServices({ cdn: server.cdnId }),
+ assignedDeliveryServices: () => deliveryServices
}
});
- modalInstance.result.then(function(selectedDsIds) {
- serverService.assignDeliveryServices($scope.server, selectedDsIds, true, false)
- .then(
- function() {
- $scope.refresh();
- }
- );
- }, function () {
- // do nothing
- });
+
+ let selectedDSIDs;
+ try {
+ selectedDSIDs = await modalInstance.result;
+ } catch {
+ return;
+ }
+ await serverService.assignDeliveryServices(server, selectedDSIDs, true, false);
+ $scope.refresh();
};
};
-TableServerDeliveryServicesController.$inject = ['server', 'deliveryServices', 'filter', '$controller', '$scope', '$state', '$uibModal', 'dateUtils', 'deliveryServiceUtils', 'locationUtils', 'serverUtils', 'deliveryServiceService', 'serverService'];
+TableServerDeliveryServicesController.$inject = ["server", "deliveryServices", "filter", "$controller", "$scope", "$uibModal", "locationUtils", "serverUtils", "deliveryServiceService", "serverService"];
module.exports = TableServerDeliveryServicesController;
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 c182756fff..1f85e4352f 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
@@ -18,110 +18,14 @@ under the License.
-->
<div class="x_panel">
- <div class="x_title">
- <ol class="breadcrumb pull-left">
- <li><a href="#!/servers">Servers</a></li>
- <li><a ng-href="#!/servers/{{server.id}}">{{::server.hostName}}</a></li>
- <li class="active">Delivery Services</li>
- </ol>
- <div class="pull-right">
- <div class="form-inline" role="search">
- <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
- <div class="input-group text-input">
- <span class="input-group-addon">
- <label for="pageSize">Page size</label>
- </span>
- <input id="pageSize" name="pageSize" type="number" min="1" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
- </div>
- <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
- <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- <i class="fa fa-columns"></i>
- <span class="caret"></span>
- </button>
- <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
- <div class="checkbox">
- <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
- </div>
- </li>
- </menu>
- </div>
- <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
- <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- More
- <span class="caret"></span>
- </button>
- <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem" ng-show="isEdge(server) || isOrigin(server)"><button class="menu-item-button clone-ds-assignments" type="button" ng-click="selectDeliveryServices()">Assign Delivery Services</button></li>
- <li role="menuitem"><button class="menu-item-button clone-ds-assignments" type="button" ng-click="cloneDsAssignments()">Clone Delivery Service Assignments</button></li>
- <li class="divider"></li>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearTableFilters()">Clear Table Filters</button></li>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
- </ul>
- </div>
- </div>
- </div>
- <div class="clearfix"></div>
- </div>
- <div class="x_content">
- <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
- </div>
+ <common-grid-controller
+ bread-crumbs="breadCrumbs"
+ table-name="{{tableName}}"
+ options="options"
+ data="deliveryServices"
+ columns="columns"
+ drop-down-options="dropDownOptions"
+ context-menu-options="contextMenuOptions"
+ >
+ </common-grid-controller>
</div>
-
-<menu id="context-menu" class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
- <ul>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}" target="_blank">Open {{ deliveryService.xmlId }} in New Tab</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <button type="button" ng-click="confirmRemoveDS(deliveryService, $event)">Remove {{deliveryService.xmlId}}</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}">Edit</a>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="clone(deliveryService, $event)">Clone</button>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="confirmDelete(deliveryService, $event)">Delete</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <button type="button" ng-click="viewCharts(deliveryService, $event)">View Charts</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/ssl-keys?dsType={{deliveryService.type}}">Manage SSL Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/url-sig-keys?dsType={{deliveryService.type}}">Manage URL Sig Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/uri-signing-keys?dsType={{deliveryService.type}}">Manage URI Signing Keys</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/jobs?dsType={{deliveryService.type}}">Manage Invalidation Requests</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') == -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/origins?dsType={{deliveryService.type}}">Manage Origins</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/regexes?dsType={{deliveryService.type}}">Manage Regexes</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('DNS') != -1 || deliveryService.type.indexOf('HTTP') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/required-server-capabilities?dsType={{deliveryService.type}}">Manage Required Server Capabilities</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/servers?dsType={{deliveryService.type}}">Manage Servers</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/targets?dsType={{deliveryService.type}}">Manage Targets</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/static-dns-entries?dsType={{deliveryService.type}}">Manage Static DNS Entries</a>
- </li>
- </ul>
-</menu>
diff --git a/traffic_portal/app/src/common/modules/table/serviceCategoryDeliveryServices/TableServiceCategoryDeliveryServicesController.js b/traffic_portal/app/src/common/modules/table/serviceCategoryDeliveryServices/TableServiceCategoryDeliveryServicesController.js
index cb70a7d3fa..36aff62dc5 100644
--- a/traffic_portal/app/src/common/modules/table/serviceCategoryDeliveryServices/TableServiceCategoryDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/serviceCategoryDeliveryServices/TableServiceCategoryDeliveryServicesController.js
@@ -23,6 +23,19 @@ var TableServiceCategoryDeliveryServicesController = function(serviceCategory, d
angular.extend(this, $controller('TableDeliveryServicesController', { tableName: 'scDS', deliveryServices: deliveryServices, filter: filter, $scope: $scope }));
$scope.serviceCategory = serviceCategory;
+ $scope.breadCrumbs = [
+ {
+ text: "Service Categories",
+ href: "#!/service-categories"
+ },
+ {
+ getText: () => serviceCategory.name,
+ getHref: () => `#!/service-categories/edit?name=${serviceCategory.name}`
+ },
+ {
+ text: "Delivery Services"
+ }
+ ]
};
TableServiceCategoryDeliveryServicesController.$inject = ['serviceCategory', 'deliveryServices', 'filter', '$controller', '$scope'];
diff --git a/traffic_portal/app/src/common/modules/table/serviceCategoryDeliveryServices/table.serviceCategoryDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/serviceCategoryDeliveryServices/table.serviceCategoryDeliveryServices.tpl.html
index f569543c4d..2d9dfa50be 100644
--- a/traffic_portal/app/src/common/modules/table/serviceCategoryDeliveryServices/table.serviceCategoryDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/serviceCategoryDeliveryServices/table.serviceCategoryDeliveryServices.tpl.html
@@ -18,105 +18,15 @@ under the License.
-->
<div class="x_panel">
- <div class="x_title">
- <ol class="breadcrumb pull-left">
- <li><a href="#!/service-categories">Service Categories</a></li>
- <li><a ng-href="#!/service-categories/edit?name={{serviceCategory.name}}">{{::serviceCategory.name}}</a></li>
- <li class="active">Delivery Services</li>
- </ol>
- <div class="pull-right">
- <div class="form-inline" role="search">
- <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
- <div class="input-group text-input">
- <span class="input-group-addon">
- <label for="pageSize">Page size</label>
- </span>
- <input id="pageSize" name="pageSize" type="number" min="1" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
- </div>
- <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
- <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- <i class="fa fa-columns"></i>
- <span class="caret"></span>
- </button>
- <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
- <div class="checkbox">
- <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
- </div>
- </li>
- </menu>
- </div>
- <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
- <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- More
- <span class="caret"></span>
- </button>
- <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearTableFilters()">Clear Table Filters</button></li>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
- </ul>
- </div>
- </div>
- </div>
- <div class="clearfix"></div>
- </div>
- <div class="x_content">
- <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
- </div>
+ <common-grid-controller
+ bread-crumbs="breadCrumbs"
+ table-name="{{tableName}}"
+ options="options"
+ data="deliveryServices"
+ columns="columns"
+ drop-down-options="dropDownOptions"
+ context-menu-options="contextMenuOptions"
+ sensitive-columns="sensitiveColumns"
+ >
+ </common-grid-controller>
</div>
-
-<menu id="context-menu" class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
- <ul>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}" target="_blank">Open {{ deliveryService.xmlId }} in New Tab</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}">Edit</a>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="clone(deliveryService, $event)">Clone</button>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="confirmDelete(deliveryService, $event)">Delete</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <button type="button" ng-click="viewCharts(deliveryService, $event)">View Charts</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/ssl-keys?dsType={{deliveryService.type}}">Manage SSL Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/url-sig-keys?dsType={{deliveryService.type}}">Manage URL Sig Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/uri-signing-keys?dsType={{deliveryService.type}}">Manage URI Signing Keys</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/jobs?dsType={{deliveryService.type}}">Manage Invalidation Requests</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') == -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/origins?dsType={{deliveryService.type}}">Manage Origins</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/regexes?dsType={{deliveryService.type}}">Manage Regexes</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('DNS') != -1 || deliveryService.type.indexOf('HTTP') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/required-server-capabilities?dsType={{deliveryService.type}}">Manage Required Server Capabilities</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/servers?dsType={{deliveryService.type}}">Manage Servers</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/targets?dsType={{deliveryService.type}}">Manage Targets</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/static-dns-entries?dsType={{deliveryService.type}}">Manage Static DNS Entries</a>
- </li>
- </ul>
-</menu>
-
-
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 c8c8357531..8277426a81 100644
--- a/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/TableTenantDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/TableTenantDeliveryServicesController.js
@@ -23,6 +23,19 @@ var TableTenantDeliveryServicesController = function(tenant, deliveryServices, f
angular.extend(this, $controller('TableDeliveryServicesController', { tableName: 'tenantDS', deliveryServices: deliveryServices, filter: filter, $scope: $scope }));
$scope.tenant = tenant;
+ $scope.breadCrumbs = [
+ {
+ href: "#!/tenants",
+ text: "Tenants"
+ },
+ {
+ getText: () => tenant.name,
+ getHref: () => `#!/tenants/${tenant.id}`
+ },
+ {
+ text: "Delivery Services"
+ }
+ ];
};
TableTenantDeliveryServicesController.$inject = ['tenant', 'deliveryServices', 'filter', '$controller', '$scope'];
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 5ed26baba7..2d9dfa50be 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
@@ -18,103 +18,15 @@ under the License.
-->
<div class="x_panel">
- <div class="x_title">
- <ol class="breadcrumb pull-left">
- <li><a href="#!/tenants">Tenants</a></li>
- <li><a ng-href="#!/tenants/{{tenant.id}}">{{::tenant.name}}</a></li>
- <li class="active">Delivery Services</li>
- </ol>
- <div class="pull-right">
- <div class="form-inline" role="search">
- <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
- <div class="input-group text-input">
- <span class="input-group-addon">
- <label for="pageSize">Page size</label>
- </span>
- <input id="pageSize" name="pageSize" type="number" min="1" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
- </div>
- <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
- <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- <i class="fa fa-columns"></i>
- <span class="caret"></span>
- </button>
- <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
- <div class="checkbox">
- <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
- </div>
- </li>
- </menu>
- </div>
- <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
- <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- More
- <span class="caret"></span>
- </button>
- <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearTableFilters()">Clear Table Filters</button></li>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
- </ul>
- </div>
- </div>
- </div>
- <div class="clearfix"></div>
- </div>
- <div class="x_content">
- <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
- </div>
+ <common-grid-controller
+ bread-crumbs="breadCrumbs"
+ table-name="{{tableName}}"
+ options="options"
+ data="deliveryServices"
+ columns="columns"
+ drop-down-options="dropDownOptions"
+ context-menu-options="contextMenuOptions"
+ sensitive-columns="sensitiveColumns"
+ >
+ </common-grid-controller>
</div>
-
-<menu id="context-menu" class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
- <ul>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}" target="_blank">Open {{ deliveryService.xmlId }} in New Tab</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}">Edit</a>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="clone(deliveryService, $event)">Clone</button>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="confirmDelete(deliveryService, $event)">Delete</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <button type="button" ng-click="viewCharts(deliveryService, $event)">View Charts</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/ssl-keys?dsType={{deliveryService.type}}">Manage SSL Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/url-sig-keys?dsType={{deliveryService.type}}">Manage URL Sig Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/uri-signing-keys?dsType={{deliveryService.type}}">Manage URI Signing Keys</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/jobs?dsType={{deliveryService.type}}">Manage Invalidation Requests</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') == -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/origins?dsType={{deliveryService.type}}">Manage Origins</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/regexes?dsType={{deliveryService.type}}">Manage Regexes</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('DNS') != -1 || deliveryService.type.indexOf('HTTP') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/required-server-capabilities?dsType={{deliveryService.type}}">Manage Required Server Capabilities</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/servers?dsType={{deliveryService.type}}">Manage Servers</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/targets?dsType={{deliveryService.type}}">Manage Targets</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/static-dns-entries?dsType={{deliveryService.type}}">Manage Static DNS Entries</a>
- </li>
- </ul>
-</menu>
diff --git a/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/TableTopologyDeliveryServicesController.js b/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/TableTopologyDeliveryServicesController.js
index c2719dd7ab..2168ab7ab9 100644
--- a/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/TableTopologyDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/TableTopologyDeliveryServicesController.js
@@ -17,13 +17,26 @@
* under the License.
*/
-var TableTopologyDeliveryServicesController = function(topologies, deliveryServices, filter, $controller, $scope) {
+function TableTopologyDeliveryServicesController(topologies, deliveryServices, filter, $controller, $scope) {
// extends the TableDeliveryServicesController to inherit common methods
- angular.extend(this, $controller('TableDeliveryServicesController', { tableName: 'topDS', deliveryServices: deliveryServices, filter: filter, $scope: $scope }));
+ angular.extend(this, $controller("TableDeliveryServicesController", { tableName: "topDS", deliveryServices, filter, $scope }));
- $scope.topology = topologies[0];
+ const topology = topologies[0];
+ $scope.breadCrumbs = [
+ {
+ href: "#!/topologies",
+ text: "Topologies"
+ },
+ {
+ href: `#!/topologies/edit?name=${topology.name}`,
+ text: topology.name
+ },
+ {
+ text: "Delivery Services"
+ }
+ ];
};
-TableTopologyDeliveryServicesController.$inject = ['topologies', 'deliveryServices', 'filter', '$controller', '$scope'];
+TableTopologyDeliveryServicesController.$inject = ["topologies", "deliveryServices", "filter", "$controller", "$scope"];
module.exports = TableTopologyDeliveryServicesController;
diff --git a/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/table.topologyDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/table.topologyDeliveryServices.tpl.html
index ed10084321..2d9dfa50be 100644
--- a/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/table.topologyDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/table.topologyDeliveryServices.tpl.html
@@ -18,103 +18,15 @@ under the License.
-->
<div class="x_panel">
- <div class="x_title">
- <ol class="breadcrumb pull-left">
- <li><a href="#!/topologies">Topologies</a></li>
- <li><a name="topLink" ng-href="#!/topologies/edit?name={{topology.name}}">{{::topology.name}}</a></li>
- <li class="active">Delivery Services</li>
- </ol>
- <div class="pull-right">
- <div class="form-inline" role="search">
- <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
- <div class="input-group text-input">
- <span class="input-group-addon">
- <label for="pageSize">Page size</label>
- </span>
- <input id="pageSize" name="pageSize" type="number" min="1" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
- </div>
- <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
- <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- <i class="fa fa-columns"></i>
- <span class="caret"></span>
- </button>
- <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
- <div class="checkbox">
- <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
- </div>
- </li>
- </menu>
- </div>
- <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
- <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- More
- <span class="caret"></span>
- </button>
- <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearTableFilters()">Clear Table Filters</button></li>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
- </ul>
- </div>
- </div>
- </div>
- <div class="clearfix"></div>
- </div>
- <div class="x_content">
- <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
- </div>
+ <common-grid-controller
+ bread-crumbs="breadCrumbs"
+ table-name="{{tableName}}"
+ options="options"
+ data="deliveryServices"
+ columns="columns"
+ drop-down-options="dropDownOptions"
+ context-menu-options="contextMenuOptions"
+ sensitive-columns="sensitiveColumns"
+ >
+ </common-grid-controller>
</div>
-
-<menu id="context-menu" class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
- <ul>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}" target="_blank">Open {{ deliveryService.xmlId }} in New Tab</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}">Edit</a>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="clone(deliveryService, $event)">Clone</button>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="confirmDelete(deliveryService, $event)">Delete</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <button type="button" ng-click="viewCharts(deliveryService, $event)">View Charts</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/ssl-keys?dsType={{deliveryService.type}}">Manage SSL Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/url-sig-keys?dsType={{deliveryService.type}}">Manage URL Sig Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/uri-signing-keys?dsType={{deliveryService.type}}">Manage URI Signing Keys</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/jobs?dsType={{deliveryService.type}}">Manage Invalidation Requests</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') == -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/origins?dsType={{deliveryService.type}}">Manage Origins</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/regexes?dsType={{deliveryService.type}}">Manage Regexes</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('DNS') != -1 || deliveryService.type.indexOf('HTTP') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/required-server-capabilities?dsType={{deliveryService.type}}">Manage Required Server Capabilities</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/servers?dsType={{deliveryService.type}}">Manage Servers</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/targets?dsType={{deliveryService.type}}">Manage Targets</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/static-dns-entries?dsType={{deliveryService.type}}">Manage Static DNS Entries</a>
- </li>
- </ul>
-</menu>
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 79e15e3e9d..383eff365f 100644
--- a/traffic_portal/app/src/common/modules/table/typeDeliveryServices/TableTypeDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/typeDeliveryServices/TableTypeDeliveryServicesController.js
@@ -1,18 +1,18 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
+ * or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
+ * regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
+ * with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
+ * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
@@ -20,10 +20,22 @@
var TableTypeDeliveryServicesController = function(type, deliveryServices, filter, $controller, $scope) {
// extends the TableDeliveryServicesController to inherit common methods
- angular.extend(this, $controller('TableDeliveryServicesController', { tableName: 'typeDS', deliveryServices: deliveryServices, filter: filter, $scope: $scope }));
+ angular.extend(this, $controller("TableDeliveryServicesController", { tableName: "typeDS", deliveryServices, filter, $scope }));
- $scope.type = type;
+ $scope.breadCrumbs = [
+ {
+ href: "#!/types",
+ text: "Types"
+ },
+ {
+ href: `#!/types/${type.id}`,
+ text: type.name,
+ },
+ {
+ text: "Delivery Services"
+ }
+ ]
};
-TableTypeDeliveryServicesController.$inject = ['type', 'deliveryServices', 'filter', '$controller', '$scope'];
+TableTypeDeliveryServicesController.$inject = ["type", "deliveryServices", "filter", "$controller", "$scope"];
module.exports = TableTypeDeliveryServicesController;
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 2ae3920318..2d9dfa50be 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
@@ -18,103 +18,15 @@ under the License.
-->
<div class="x_panel">
- <div class="x_title">
- <ol class="breadcrumb pull-left">
- <li><a href="#!/types">Types</a></li>
- <li><a ng-href="#!/types/{{type.id}}">{{::type.name}}</a></li>
- <li class="active">Delivery Services</li>
- </ol>
- <div class="pull-right">
- <div class="form-inline" role="search">
- <input id="quickSearch" name="quickSearch" type="search" class="form-control text-input" placeholder="Quick search..." ng-model="quickSearch" ng-change="onQuickSearchChanged()" aria-label="Search"/>
- <div class="input-group text-input">
- <span class="input-group-addon">
- <label for="pageSize">Page size</label>
- </span>
- <input id="pageSize" name="pageSize" type="number" min="1" class="form-control" placeholder="100" ng-model="pageSize" ng-change="onPageSizeChanged()" aria-label="Page Size"/>
- </div>
- <div id="toggleColumns" class="btn-group" role="group" title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
- <button type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- <i class="fa fa-columns"></i>
- <span class="caret"></span>
- </button>
- <menu ng-click="$event.stopPropagation()" class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem" ng-repeat="c in gridOptions.columnApi.getAllColumns() | orderBy:'colDef.headerName'">
- <div class="checkbox">
- <label><input type="checkbox" ng-checked="c.isVisible()" ng-click="toggleVisibility(c.colId)">{{::c.colDef.headerName}}</label>
- </div>
- </li>
- </menu>
- </div>
- <div class="btn-group" role="group" uib-dropdown is-open="more.isopen">
- <button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- More
- <span class="caret"></span>
- </button>
- <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="clearTableFilters()">Clear Table Filters</button></li>
- <li role="menuitem"><button class="menu-item-button" type="button" ng-click="exportCSV()">Export CSV</button></li>
- </ul>
- </div>
- </div>
- </div>
- <div class="clearfix"></div>
- </div>
- <div class="x_content">
- <div style="height: 740px;" ag-grid="gridOptions" class="ag-theme-alpine"></div>
- </div>
+ <common-grid-controller
+ bread-crumbs="breadCrumbs"
+ table-name="{{tableName}}"
+ options="options"
+ data="deliveryServices"
+ columns="columns"
+ drop-down-options="dropDownOptions"
+ context-menu-options="contextMenuOptions"
+ sensitive-columns="sensitiveColumns"
+ >
+ </common-grid-controller>
</div>
-
-<menu id="context-menu" class="dropdown-menu" ng-style="menuStyle" type="contextmenu" ng-show="showMenu">
- <ul>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}" target="_blank">Open {{ deliveryService.xmlId }} in New Tab</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}?dsType={{deliveryService.type}}">Edit</a>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="clone(deliveryService, $event)">Clone</button>
- </li>
- <li role="menuitem">
- <button type="button" ng-click="confirmDelete(deliveryService, $event)">Delete</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <button type="button" ng-click="viewCharts(deliveryService, $event)">View Charts</button>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/ssl-keys?dsType={{deliveryService.type}}">Manage SSL Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/url-sig-keys?dsType={{deliveryService.type}}">Manage URL Sig Keys</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/uri-signing-keys?dsType={{deliveryService.type}}">Manage URI Signing Keys</a>
- </li>
- <hr class="divider"/>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/jobs?dsType={{deliveryService.type}}">Manage Invalidation Requests</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') == -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/origins?dsType={{deliveryService.type}}">Manage Origins</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/regexes?dsType={{deliveryService.type}}">Manage Regexes</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('DNS') != -1 || deliveryService.type.indexOf('HTTP') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/required-server-capabilities?dsType={{deliveryService.type}}">Manage Required Server Capabilities</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/servers?dsType={{deliveryService.type}}">Manage Servers</a>
- </li>
- <li role="menuitem" ng-if="deliveryService.type.indexOf('STEERING') != -1">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/targets?dsType={{deliveryService.type}}">Manage Targets</a>
- </li>
- <li role="menuitem">
- <a ng-href="#!/delivery-services/{{deliveryService.id}}/static-dns-entries?dsType={{deliveryService.type}}">Manage Static DNS Entries</a>
- </li>
- </ul>
-</menu>
diff --git a/traffic_portal/app/src/styles/main.scss b/traffic_portal/app/src/styles/main.scss
index 12f6453111..c4f0e6aab4 100644
--- a/traffic_portal/app/src/styles/main.scss
+++ b/traffic_portal/app/src/styles/main.scss
@@ -269,3 +269,9 @@ input[type="checkbox"].dirty {
background-color: #d3d3d4;
border-color: #bcbebf;
}
+
+// This is, unfortunately, necessary because uibModal doesn't support scoped
+// stylesheets (afaik; it's a dead library so nobody knows).
+.uppercase {
+ text-transform: uppercase;
+}
diff --git a/traffic_portal/test/integration/Data/deliveryservices.ts b/traffic_portal/test/integration/Data/deliveryservices.ts
index cc90d8d177..7bd9c48644 100644
--- a/traffic_portal/test/integration/Data/deliveryservices.ts
+++ b/traffic_portal/test/integration/Data/deliveryservices.ts
@@ -299,196 +299,174 @@ export const deliveryservices = {
],
tests: [
{
- logins: [
- {
- description: "Admin Role",
- username: "TPAdmin",
- password: "pa$$word"
- }
- ],
+ description: "Admin Role Delivery Service actions",
+ login: {
+ username: "TPAdmin",
+ password: "pa$$word"
+ },
add: [
{
description: "create ANY_MAP delivery service",
- Name: "tpdservice1",
- Tenant: "tenantSame",
- Type: "ANY_MAP",
+ name: "tpdservice1",
+ tenant: "tenantSame",
+ type: "ANY_MAP",
validationMessage: "Delivery Service creation was successful"
},
{
description: "create DNS delivery service",
- Name: "tpdservice2",
- Tenant: "tenantSame",
- Type: "DNS",
+ name: "tpdservice2",
+ tenant: "tenantSame",
+ type: "DNS",
validationMessage: "Delivery Service creation was successful"
},
{
description: "create STEERING delivery service",
- Name: "tpdservice3",
- Tenant: "tenantSame",
- Type: "STEERING",
+ name: "tpdservice3",
+ tenant: "tenantSame",
+ type: "STEERING",
validationMessage: "Delivery Service creation was successful"
}
],
update: [
{
- description: "update delivery service display name",
- Name: "tpdservice1",
- NewName: "TPServiceNew1",
+ name: "tpdservice1",
+ newName: "TPServiceNew1",
validationMessage: "Delivery Service update was successful"
}
],
- assignserver: [
+ assignServer: [
{
- description: "assign server to delivery service",
- ServerName: "DSTest",
- DSName: "TPServiceNew1",
+ serverHostname: "DSTest",
+ xmlID: "TPServiceNew1",
validationMessage: "server assignments complete"
}
],
- assignrequiredcapabilities: [
+ assignRequiredCapabilities: [
{
- description: "assign required capabilities to delivery service",
- RCName: "DSTestCap",
- DSName: "tpdservice2",
+ rcName: "DSTestCap",
+ xmlID: "tpdservice2",
validationMessage: "deliveryservice.RequiredCapability was created."
}
],
remove: [
{
- description: "delete a delivery service",
- Name: "tpdservice1",
+ name: "tpdservice1",
validationMessage: "ds was deleted."
},
{
- description: "delete a delivery service",
- Name: "tpdservice2",
+ name: "tpdservice2",
validationMessage: "ds was deleted."
},
{
- description: "delete a delivery service",
- Name: "tpdservice3",
+ name: "tpdservice3",
validationMessage: "ds was deleted."
}
]
},
{
- logins: [
- {
- description: "Read Only Role",
- username: "TPReadOnly",
- password: "pa$$word"
- }
- ],
+ description: "Read Only Role Delivery Service actions",
+ login: {
+ username: "TPReadOnly",
+ password: "pa$$word"
+ },
add: [
{
description: "create ANY_MAP delivery service",
- Name: "tpdservice1",
- Type: "ANY_MAP",
- Tenant: "tenantSame",
+ name: "tpdservice1",
+ type: "ANY_MAP",
+ tenant: "tenantSame",
validationMessage: "missing required Permissions: DELIVERY-SERVICE:CREATE"
}
],
update: [
{
- description: "update delivery service display name",
- Name: "dstestro1",
- NewName: "TPServiceNew1",
+ name: "dstestro1",
+ newName: "TPServiceNew1",
validationMessage: "missing required Permissions: DELIVERY-SERVICE:UPDATE"
}
],
- assignserver: [
+ assignServer: [
{
- description: "assign server to delivery service",
- ServerName: "DSTest",
- DSName: "dstestro1",
+ serverHostname: "DSTest",
+ xmlID: "dstestro1",
validationMessage: "missing required Permissions: SERVER:UPDATE, DELIVERY-SERVICE:UPDATE"
}
],
- assignrequiredcapabilities: [
+ assignRequiredCapabilities: [
{
- description: "assign required capabilities to delivery service",
- RCName: "DSTestCap",
- DSName: "dstestro1",
+ rcName: "DSTestCap",
+ xmlID: "dstestro1",
validationMessage: "missing required Permissions: DELIVERY-SERVICE:UPDATE"
}
],
remove: [
{
- description: "delete a delivery service",
- Name: "dstestro1",
+ name: "dstestro1",
validationMessage: "missing required Permissions: DELIVERY-SERVICE:DELETE"
}
]
},
{
- logins: [
- {
- description: "Operation Role",
- username: "TPOperator",
- password: "pa$$word"
- }
- ],
+ description: "Operation Role Delivery Service actions",
+ login: {
+ username: "TPOperator",
+ password: "pa$$word"
+ },
add: [
{
description: "create ANY_MAP delivery service",
- Name: "optpdservice1",
- Tenant: "tenantSame",
- Type: "ANY_MAP",
+ name: "optpdservice1",
+ tenant: "tenantSame",
+ type: "ANY_MAP",
validationMessage: "Delivery Service creation was successful"
},
{
description: "create DNS delivery service",
- Name: "optpdservice2",
- Tenant: "tenantSame",
- Type: "DNS",
+ name: "optpdservice2",
+ tenant: "tenantSame",
+ type: "DNS",
validationMessage: "Delivery Service creation was successful"
},
{
description: "create STEERING delivery service",
- Name: "optpdservice3",
- Tenant: "tenantSame",
- Type: "STEERING",
+ name: "optpdservice3",
+ tenant: "tenantSame",
+ type: "STEERING",
validationMessage: "Delivery Service creation was successful"
}
],
update: [
{
- description: "update delivery service display name",
- Name: "optpdservice1",
- NewName: "opTPServiceNew1",
+ name: "optpdservice1",
+ newName: "opTPServiceNew1",
validationMessage: "Delivery Service update was successful"
}
],
- assignserver: [
+ assignServer: [
{
- description: "assign server to delivery service",
- ServerName: "DSTest",
- DSName: "opTPServiceNew1",
+ serverHostname: "DSTest",
+ xmlID: "opTPServiceNew1",
validationMessage: "server assignments complete"
}
],
- assignrequiredcapabilities: [
+ assignRequiredCapabilities: [
{
- description: "assign required capabilities to delivery service",
- RCName: "DSTestCap",
- DSName: "optpdservice2",
+ rcName: "DSTestCap",
+ xmlID: "optpdservice2",
validationMessage: "deliveryservice.RequiredCapability was created."
}
],
remove: [
{
- description: "delete a delivery service",
- Name: "optpdservice1",
+ name: "optpdservice1",
validationMessage: "ds was deleted."
},
{
- description: "delete a delivery service",
- Name: "optpdservice2",
+ name: "optpdservice2",
validationMessage: "ds was deleted."
},
{
- description: "delete a delivery service",
- Name: "optpdservice3",
+ name: "optpdservice3",
validationMessage: "ds was deleted."
}
]
diff --git a/traffic_portal/test/integration/PageObjects/BasePage.po.ts b/traffic_portal/test/integration/PageObjects/BasePage.po.ts
index 17a5c0d298..4deff86844 100644
--- a/traffic_portal/test/integration/PageObjects/BasePage.po.ts
+++ b/traffic_portal/test/integration/PageObjects/BasePage.po.ts
@@ -19,8 +19,8 @@
import { browser, element, by, ExpectedConditions } from 'protractor';
/**
* Class representing generic page.
- * Methods/properties for global elements should go here.
- *
+ * Methods/properties for global elements should go here.
+ *
* @export
* @class BasePage
*/
@@ -38,10 +38,10 @@ export class BasePage {
private btnDeletePermanently = element(by.buttonText('Delete Permanently'));
private btnCancel = element(by.className('close')).element(by.xpath("//span[text()='×']"));
private btnUpdate = element(by.buttonText('Update'));
- private btnSubmit = element(by.xpath("//button[text()='Submit']"));
+ private btnSubmit = element(by.buttonText("Submit"));
private btnRegister = element(by.buttonText('Send Registration'));
- private btnNo = element(by.xpath("//button[text()='No']"));
-
+ private btnNo = element(by.buttonText("No"));
+
async ClickNo(){
await this.btnNo.click();
}
@@ -52,7 +52,7 @@ export class BasePage {
}else{
return false;
}
-
+
}
public async ClickUpdate(): Promise<boolean>{
if(await this.btnUpdate.isEnabled()){
diff --git a/traffic_portal/test/integration/PageObjects/DeliveryServicePage.po.ts b/traffic_portal/test/integration/PageObjects/DeliveryServicePage.po.ts
index 2fedf54cac..5c815e3686 100644
--- a/traffic_portal/test/integration/PageObjects/DeliveryServicePage.po.ts
+++ b/traffic_portal/test/integration/PageObjects/DeliveryServicePage.po.ts
@@ -17,203 +17,174 @@
* under the License.
*/
-import { BasePage } from './BasePage.po';
+import { BasePage } from "./BasePage.po";
import { randomize } from "../config";
-import { SideNavigationPage } from './SideNavigationPage.po';
-import {browser, by, element} from 'protractor';
-
-interface DeliveryServices {
- Type: string;
- Name: string;
- Tenant: string;
- validationMessage: string;
-}
-interface UpdateDeliveryService {
- description: string;
- Name: string;
- NewName: string;
- validationMessage: string;
-}
-interface DeleteDeliveryService {
- Name: string;
- validationMessage: string;
-}
-interface AssignServer {
- DSName: string;
- ServerName: string;
- validationMessage: string;
-}
-interface AssignRC {
- RCName: string;
- DSName: string;
- validationMessage: string;
-}
+import { SideNavigationPage } from "./SideNavigationPage.po";
+import { browser, by, element, ExpectedConditions } from "protractor";
+
+/**
+ * The DeliveryServicePage is a page object modelling of the Delivery Service
+ * editing/creation view. For simplicity"s sake, it also provides functionality
+ * that relates to the Delivery Services table view.
+ */
export class DeliveryServicePage extends BasePage {
- private btnCreateNewDeliveryServices = element(by.buttonText("Create Delivery Service"));
- private mnuFormDropDown = element(by.name('selectFormDropdown'));
- private btnSubmitFormDropDown = element(by.buttonText('Submit'));
- private txtSearch = element(by.id("quickSearch"))
- private txtConfirmName = element(by.name('confirmWithNameInput'));
- private btnDelete = element(by.buttonText('Delete'));
- private btnMore = element(by.name('moreBtn'));
- private mnuManageRequiredServerCapabilities = element(by.linkText('Manage Required Server Capabilities'));
- private btnAddRequiredServerCapabilities = element(by.name('addCapabilityBtn'));
- private txtInputRC = element(by.name("selectFormDropdown"));
- private mnuManageServers = element(by.buttonText('Manage Servers'));
- private btnAssignServer = element(by.name("selectServersMenuItem"));
- private txtXmlId = element(by.name('xmlId'));
- private txtDisplayName = element(by.name('displayName'));
- private selectActive = element(by.name('active'));
- private selectType = element(by.id('type'));
- private selectTenant = element(by.name('tenantId'));
- private selectCDN = element(by.name('cdn'));
- private txtOrgServerURL = element(by.name('orgServerFqdn'));
- private txtProtocol = element(by.name('protocol'));
- private txtRemapText = element(by.name('remapText'));
- private btnCreateDeliveryServices = element(by.buttonText('Create'));
- private randomize = randomize;
-
- public async OpenDeliveryServicePage() {
- const snp = new SideNavigationPage();
- await snp.NavigateToDeliveryServicesPage();
- }
-
- public async OpenServicesMenu() {
- const snp = new SideNavigationPage();
- await snp.ClickServicesMenu();
- }
-
- public async CreateDeliveryService(deliveryservice: DeliveryServices): Promise<boolean> {
- let result = false;
- let type: string = deliveryservice.Type;
- const basePage = new BasePage();
- await this.btnMore.click();
- await this.btnCreateNewDeliveryServices.click();
- await this.mnuFormDropDown.sendKeys(type);
- await this.btnSubmitFormDropDown.click();
- switch (type) {
- case "ANY_MAP": {
- await this.txtXmlId.sendKeys(deliveryservice.Name + this.randomize);
- await this.txtDisplayName.sendKeys(deliveryservice.Name + this.randomize);
- await this.selectActive.sendKeys('Active')
- await this.selectType.sendKeys('ANY_MAP')
- await this.selectTenant.click();
- await element(by.name(deliveryservice.Tenant + this.randomize)).click();
- await this.selectCDN.sendKeys('dummycdn')
- await this.txtRemapText.sendKeys('test')
- break;
- }
- case "DNS": {
- await this.txtXmlId.sendKeys(deliveryservice.Name + this.randomize);
- await this.txtDisplayName.sendKeys(deliveryservice.Name + this.randomize);
- await this.selectActive.sendKeys('Active')
- await this.selectType.sendKeys('DNS')
- await this.selectTenant.click();
- await element(by.name(deliveryservice.Tenant + this.randomize)).click();
- await this.selectCDN.sendKeys('dummycdn')
- await this.txtOrgServerURL.sendKeys('http://origin.infra.ciab.test');
- await this.txtProtocol.sendKeys('HTTP')
- break;
- }
- case "HTTP": {
- await this.txtXmlId.sendKeys(deliveryservice.Name + this.randomize);
- await this.txtDisplayName.sendKeys(deliveryservice.Name + this.randomize);
- await this.selectActive.sendKeys('Active')
- await this.selectType.sendKeys('HTTP')
- await this.selectTenant.click();
- await element(by.name(deliveryservice.Tenant + this.randomize)).click();
- await this.selectCDN.sendKeys('dummycdn')
- await this.txtOrgServerURL.sendKeys('http://origin.infra.ciab.test');
- await this.txtProtocol.sendKeys('HTTP')
- break;
- }
- case "STEERING": {
- await this.txtXmlId.sendKeys(deliveryservice.Name + this.randomize);
- await this.txtDisplayName.sendKeys(deliveryservice.Name + this.randomize);
- await this.selectActive.sendKeys('Active')
- await this.selectType.sendKeys('STEERING')
- await this.selectTenant.click();
- await element(by.name(deliveryservice.Tenant + this.randomize)).click();
- await this.selectCDN.sendKeys('dummycdn')
- await this.txtProtocol.sendKeys('HTTP')
- break;
- }
- default:
- {
- console.log('Wrong Type name');
- break;
- }
- }
- await this.btnCreateDeliveryServices.click();
- result = await basePage.GetOutputMessage().then(value => value === deliveryservice.validationMessage);
- return result;
- }
-
- public async SearchDeliveryService(nameDS: string): Promise<boolean> {
- const name = nameDS + this.randomize;
- await this.txtSearch.clear();
- await this.txtSearch.sendKeys(name);
- const result = await element(by.cssContainingText("span", name)).isPresent();
- await element(by.cssContainingText("span", name)).click();
- return !result;
- }
-
- public async UpdateDeliveryService(deliveryservice: UpdateDeliveryService): Promise<boolean | undefined> {
- let result: boolean | undefined = false;
- const basePage = new BasePage();
- switch (deliveryservice.description) {
- case "update delivery service display name":
- await this.txtDisplayName.clear();
- await this.txtDisplayName.sendKeys(deliveryservice.NewName + this.randomize);
- await basePage.ClickUpdate();
- break;
- default:
- result = undefined;
- }
- if (result = !undefined) {
- result = await basePage.GetOutputMessage().then(value => value === deliveryservice.validationMessage);
- }
- return result;
- }
-
- public async DeleteDeliveryService(deliveryservice: DeleteDeliveryService): Promise<boolean> {
- let result = false;
- const basePage = new BasePage();
- if (deliveryservice.validationMessage.includes("deleted")) {
- deliveryservice.validationMessage = deliveryservice.validationMessage.replace(deliveryservice.Name, deliveryservice.Name + this.randomize);
- }
- await this.btnDelete.click();
- await this.txtConfirmName.sendKeys(deliveryservice.Name + this.randomize);
- await basePage.ClickDeletePermanently();
- result = await basePage.GetOutputMessage().then(value => value === deliveryservice.validationMessage);
- return result;
- }
-
- public async AssignServerToDeliveryService(deliveryservice: AssignServer): Promise<boolean>{
- let result = false;
- const basePage = new BasePage();
- await this.btnMore.click();
- await this.mnuManageServers.click();
- await this.btnMore.click();
- await this.btnAssignServer.click();
- await browser.sleep(3000);
- await element(by.cssContainingText(".ag-cell-value", deliveryservice.ServerName)).click();
- await this.ClickSubmit();
- result = await basePage.GetOutputMessage().then(value => value === deliveryservice.validationMessage);
- return result;
- }
-
- public async AssignRequiredCapabilitiesToDS(deliveryservice: AssignRC): Promise<boolean>{
- let result = false;
- const basePage = new BasePage();
- await this.btnMore.click();
- await this.mnuManageRequiredServerCapabilities.click();
- await this.btnAddRequiredServerCapabilities.click();
- await this.txtInputRC.sendKeys(deliveryservice.RCName);
- await this.ClickSubmit();
- result = await basePage.GetOutputMessage().then(value => value === deliveryservice.validationMessage);
- return result;
- }
+ /** The search box in the DS table view. */
+ private readonly txtSearch = element(by.id("quickSearch"));
+
+ /** The "Display Name" text input in the editing/creation view(s). */
+ private readonly txtDisplayName = element(by.name("displayName"));
+ /** The "More" dropdown menu button in the editing/creation view(s). */
+ private readonly btnMore = element(by.name("moreBtn"));
+
+ /**
+ * Navigates to the Delivery Services table view.
+ */
+ public async OpenDeliveryServicePage(): Promise<void> {
+ const snp = new SideNavigationPage();
+ return snp.NavigateToDeliveryServicesPage();
+ }
+
+ /**
+ * Toggles the open/close state of the "Services" sub-menu in the left-side
+ * navigation pane.
+ */
+ public async OpenServicesMenu(): Promise<void> {
+ const snp = new SideNavigationPage();
+ return snp.ClickServicesMenu();
+ }
+
+ /**
+ * Creates a new Delivery Service.
+ *
+ * @param deliveryservice Details for the Delivery Service to be created.
+ * @returns The text shown in the first Alert pane found after creation.
+ */
+ public async CreateDeliveryService(name: string, type: string, tenant: string): Promise<string> {
+ await this.btnMore.click();
+ await element(by.buttonText("Create Delivery Service")).click();
+ await element(by.name("selectFormDropdown")).sendKeys(type);
+ await element(by.buttonText("Submit")).click();
+
+ name += randomize;
+ tenant += randomize;
+
+ const ps = [];
+ switch (type) {
+ case "ANY_MAP":
+ ps.push(element(by.name("remapText")).sendKeys("test"));
+ break;
+
+ case "DNS":
+ case "HTTP":
+ ps.push(element(by.name("orgServerFqdn")).sendKeys("http://origin.infra.ciab.test"));
+ case "STEERING":
+ ps.push(element(by.name("protocol")).sendKeys("HTTP"));
+ break;
+
+ default:
+ throw new Error(`invalid Delivery Service routing type: ${type}`);
+ }
+ ps.push(
+ element(by.name("xmlId")).sendKeys(name),
+ this.txtDisplayName.sendKeys(name),
+ element(by.name("active")).sendKeys("Active"),
+ element(by.id("type")).sendKeys(type),
+ element(by.name("tenantId")).click().then(() => element(by.name(tenant)).click()),
+ element(by.name("cdn")).sendKeys("dummycdn")
+ );
+
+ await Promise.all(ps);
+ await element(by.buttonText("Create")).click();
+
+ return this.GetOutputMessage();
+ }
+
+ /**
+ * Searches the table for a Delivery Service in the table.
+ *
+ * (Note this neither checks nor enforces that the sought-after DS is
+ * actually found.)
+ *
+ * @param name The name for which to search.
+ */
+ public async SearchDeliveryService(name: string): Promise<void> {
+ name += randomize;
+
+ await this.txtSearch.clear();
+ await this.txtSearch.sendKeys(name);
+ const nameSpan = element(by.cssContainingText("span", name));
+ await nameSpan.click();
+ }
+
+ /**
+ * Changes a Delivery Service's Display Name to the provided value (after
+ * randomization).
+ *
+ * @param newName The new Display Name to be given to the Delivery Service.
+ * @returns The text shown in the first Alert pane found after attempting to
+ * submit the update.
+ */
+ public async UpdateDeliveryServiceDisplayName(newName: string): Promise<string> {
+ await this.txtDisplayName.clear();
+ await this.txtDisplayName.sendKeys(newName + randomize);
+ await this.ClickUpdate();
+ return this.GetOutputMessage();
+ }
+
+ /**
+ * Attempts to delete a Delivery Service.
+ *
+ * @param name The XMLID of the Delivery Service to be deleted.
+ * @returns The text shown in the first Alert pane found after attempting
+ * the deletion.
+ */
+ public async DeleteDeliveryService(name: string): Promise<string> {
+ name += randomize;
+ await element(by.buttonText("Delete")).click();
+ await element(by.name("confirmWithNameInput")).sendKeys(name);
+ await this.ClickDeletePermanently();
+ return this.GetOutputMessage();
+ }
+
+ /**
+ * Assigns the server with the given hostname to the Delivery Service. Note
+ * that the browser must already be on a Delivery Service edit view for this
+ * to work, as this method neither navigates to it nor back to the table
+ * view afterward!
+ *
+ * @param serverName The name of the server being assigned.
+ * @returns The text shown in the first Alert pane found after attempting
+ * the assignment.
+ */
+ public async AssignServerToDeliveryService(serverName: string): Promise<string>{
+ await this.btnMore.click();
+ await element(by.buttonText("Manage Servers")).click();
+ await this.btnMore.click();
+ await element(by.partialButtonText("Assign")).click();
+ const serverCell = element(by.cssContainingText(".ag-cell-value", serverName));
+ await browser.wait(ExpectedConditions.elementToBeClickable(serverCell), 3000);
+ await serverCell.click();
+ await this.ClickSubmit();
+ return this.GetOutputMessage();
+ }
+ /**
+ * Assigns the Capability with the given name as a requirement of the
+ * Delivery Service. Note that the browser must already be on a Delivery
+ * Service edit view for this to work, as this method neither navigates to
+ * it nor back to the table view afterward!
+ *
+ * @param name The name of the Capability to be required.
+ * @returns The text shown in the first Alert pane found after attempting
+ * the assignment.
+ */
+ public async AssignRequiredCapabilitiesToDS(name: string): Promise<string>{
+ await this.btnMore.click();
+ await element(by.linkText("Manage Required Server Capabilities")).click();
+ await element(by.name("addCapabilityBtn")).click();
+ await element(by.name("selectFormDropdown")).sendKeys(name);
+ await this.ClickSubmit();
+ return this.GetOutputMessage();
+ }
}
diff --git a/traffic_portal/test/integration/specs/DeliveryServices.spec.ts b/traffic_portal/test/integration/specs/DeliveryServices.spec.ts
index 7c92742072..a7c8efb39b 100644
--- a/traffic_portal/test/integration/specs/DeliveryServices.spec.ts
+++ b/traffic_portal/test/integration/specs/DeliveryServices.spec.ts
@@ -28,72 +28,65 @@ const topNavigation = new TopNavigationPage();
const loginPage = new LoginPage();
const deliveryservicesPage = new DeliveryServicePage();
-describe('Setup API for delivery service test', function () {
- it('Setup', async () => {
- await api.UseAPI(deliveryservices.setup);
- });
-});
+describe("Delivery Services", () => {
+ beforeAll(async () => {
+ await api.UseAPI(deliveryservices.setup);
+ });
+
+ afterAll(async () => {
+ await api.UseAPI(deliveryservices.cleanup);
+ });
+
+ for (const data of deliveryservices.tests) {
+ describe(`Traffic Portal - Delivery Service - ${data.description}`, () =>{
+ beforeAll(async () => {
+ browser.get(browser.params.baseUrl);
+ await loginPage.Login(data.login);
+ expect(await loginPage.CheckUserName(data.login)).toBe(true);
+ await deliveryservicesPage.OpenServicesMenu();
+ await deliveryservicesPage.OpenDeliveryServicePage();
+ });
+ afterEach(async () => {
+ await deliveryservicesPage.OpenDeliveryServicePage();
+ expect((await browser.getCurrentUrl()).split("#").slice(-1).join().replace(/\/$/, "")).toBe("!/delivery-services");
+ });
+ afterAll(async () => {
+ await deliveryservicesPage.OpenServicesMenu();
+ expect(await topNavigation.Logout()).toBe(true);
+ });
+
+ for (const {description, name, type, tenant, validationMessage} of data.add) {
+ it(description, async () => {
+ expect(await deliveryservicesPage.CreateDeliveryService(name, type, tenant)).toBe(validationMessage);
+ });
+ }
+ for (const {name, newName, validationMessage} of data.update) {
+ it("updates Delivery Service Display Name", async () => {
+ await deliveryservicesPage.SearchDeliveryService(name);
+ expect(await deliveryservicesPage.UpdateDeliveryServiceDisplayName(newName)).toBe(validationMessage);
+ });
+ }
-deliveryservices.tests.forEach(async deliveryservicesData => {
- deliveryservicesData.logins.forEach(login =>{
- describe(`Traffic Portal - Delivery Service - ${login.description}`, () =>{
- it('can login', async () => {
- browser.get(browser.params.baseUrl);
- await loginPage.Login(login);
- expect(await loginPage.CheckUserName(login)).toBe(true);
- });
- it('can open delivery service page', async () => {
- await deliveryservicesPage.OpenServicesMenu();
- await deliveryservicesPage.OpenDeliveryServicePage();
- });
- deliveryservicesData.add.forEach(add => {
- it(add.description, async function () {
- expect(await deliveryservicesPage.CreateDeliveryService(add)).toBe(true);
- await deliveryservicesPage.OpenDeliveryServicePage();
- });
- });
- deliveryservicesData.update.forEach(update => {
- it(update.description, async function () {
- await deliveryservicesPage.SearchDeliveryService(update.Name);
- expect(await deliveryservicesPage.UpdateDeliveryService(update)).toBe(true);
- await deliveryservicesPage.OpenDeliveryServicePage();
- });
- })
- deliveryservicesData.assignserver.forEach(assignserver => {
- it(assignserver.description, async function(){
- await deliveryservicesPage.SearchDeliveryService(assignserver.DSName);
- expect(await deliveryservicesPage.AssignServerToDeliveryService(assignserver)).toBe(true);
- await deliveryservicesPage.OpenDeliveryServicePage();
- }
+ for (const {serverHostname, xmlID, validationMessage} of data.assignServer){
+ it("assigns servers to a Delivery Service", async () => {
+ await deliveryservicesPage.SearchDeliveryService(xmlID);
+ expect(await deliveryservicesPage.AssignServerToDeliveryService(serverHostname)).toBe(validationMessage);
+ });
+ }
- )
- })
- deliveryservicesData.assignrequiredcapabilities.forEach(assignrc => {
- it(assignrc.description, async function(){
- await deliveryservicesPage.SearchDeliveryService(assignrc.DSName);
- expect(await deliveryservicesPage.AssignRequiredCapabilitiesToDS(assignrc)).toBe(true);
- await deliveryservicesPage.OpenDeliveryServicePage();
- })
- })
- deliveryservicesData.remove.forEach(remove => {
- it(remove.description, async () => {
- await deliveryservicesPage.SearchDeliveryService(remove.Name);
- expect(await deliveryservicesPage.DeleteDeliveryService(remove)).toBe(true);
- await deliveryservicesPage.OpenDeliveryServicePage();
- });
- });
- it('can close service menu tab', async () => {
- await deliveryservicesPage.OpenServicesMenu();
- });
- it('can logout', async () => {
- expect(await topNavigation.Logout()).toBe(true);
- });
- })
- })
+ for (const {rcName, validationMessage, xmlID} of data.assignRequiredCapabilities) {
+ it("assign required capabilities to delivery service", async () => {
+ await deliveryservicesPage.SearchDeliveryService(xmlID);
+ expect(await deliveryservicesPage.AssignRequiredCapabilitiesToDS(rcName)).toBe(validationMessage);
+ });
+ }
-})
-describe('Clean up API for delivery service test', () => {
- it('Cleanup', async () => {
- await api.UseAPI(deliveryservices.cleanup);
- });
+ for (const {name, validationMessage} of data.remove) {
+ it("deletes a Delivery Service", async () => {
+ await deliveryservicesPage.SearchDeliveryService(name);
+ expect(await deliveryservicesPage.DeleteDeliveryService(name)).toBe(validationMessage);
+ });
+ }
+ });
+ }
});