summaryrefslogtreecommitdiffstats
path: root/gui-pdp-monitoring/src/webapp/js
diff options
context:
space:
mode:
Diffstat (limited to 'gui-pdp-monitoring/src/webapp/js')
-rw-r--r--gui-pdp-monitoring/src/webapp/js/MonitoringChart.js260
-rw-r--r--gui-pdp-monitoring/src/webapp/js/MonitoringConfig.js127
-rw-r--r--gui-pdp-monitoring/src/webapp/js/MonitoringMain.js109
-rw-r--r--gui-pdp-monitoring/src/webapp/js/MonitoringTable.js61
-rw-r--r--gui-pdp-monitoring/src/webapp/js/MonitoringUtils.js416
-rw-r--r--gui-pdp-monitoring/src/webapp/js/PdpEngineWorkerStatus.js147
-rw-r--r--gui-pdp-monitoring/src/webapp/js/PdpInformation.js65
-rw-r--r--gui-pdp-monitoring/src/webapp/js/PdpListView.js75
-rw-r--r--gui-pdp-monitoring/src/webapp/js/PdpStatisticsSummary.js142
-rw-r--r--gui-pdp-monitoring/src/webapp/js/__test__/MonitoringUtils.test.js19
10 files changed, 1421 insertions, 0 deletions
diff --git a/gui-pdp-monitoring/src/webapp/js/MonitoringChart.js b/gui-pdp-monitoring/src/webapp/js/MonitoringChart.js
new file mode 100644
index 0000000..514446b
--- /dev/null
+++ b/gui-pdp-monitoring/src/webapp/js/MonitoringChart.js
@@ -0,0 +1,260 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+import * as d3 from "d3";
+
+/*
+ * Create a chart and append it to a container
+ */
+function createChart(data, container, title, unit, lineStroke, nodeColour) {
+ // Set the dimensions of the canvas
+ var margin = {
+ top : 30,
+ right : 20,
+ bottom : 30,
+ left : 50
+ }, width = 600 - margin.left - margin.right, height = 270 - margin.top
+ - margin.bottom;
+
+ // Set the ranges
+ var x = d3.time.scale().range([ 0, width ]);
+ var y = d3.scale.linear().range([ height, 0 ]);
+
+ // Define the axes
+ var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5).innerTickSize(
+ -height).outerTickSize(0).tickPadding(10);
+
+ var yAxis = d3.svg.axis().scale(y).orient("left").ticks(10).innerTickSize(
+ -width).outerTickSize(0).tickPadding(10);
+
+ // Define the line
+ var valueline = d3.svg.line().x(function(d) {
+ return x(d.timestamp);
+ }).y(function(d) {
+ return y(d.value);
+ });
+
+ // Add the svg canvas to the container
+ var svg = d3.select(container).append("svg").attr("preserveAspectRatio",
+ "xMinYMin meet").attr("viewBox", "0 0 600 400").classed(
+ "svg-content-responsive", true).append("g").attr("transform",
+ "translate(" + margin.left + "," + margin.top + ")");
+
+ // Set the unit for the value
+ svg.attr("unit", unit);
+
+ // Format the data for the chart
+ data.forEach(function(d) {
+ d.timestamp = d.timestamp;
+ d.value = +d.value;
+ });
+
+ // Scale the range of the data
+ x.domain(d3.extent(data, function(d) {
+ return d.timestamp;
+ }));
+ y.domain([ 0, d3.max(data, function(d) {
+ return Math.ceil((d.value + 1) / 10) * 10;
+ }) ]);
+
+ // Set the colour of the line
+ if (!lineStroke) {
+ lineStroke = "#5fbadd"
+ }
+
+ // Set the colour of the circles
+ if (!nodeColour) {
+ nodeColour = "#00A9D4"
+ }
+
+ // Add the valueline path
+ svg.append("path").attr("class", "line").data(data).attr("unit", unit)
+ .attr("stroke", lineStroke).attr("d", valueline(data));
+
+ // Add the scatterplot
+ svg.selectAll("circle").data(data).enter().append("circle").attr("r", 3.5)
+ .attr("class", "circle").attr("fill", nodeColour).attr("cx",
+ function(d) {
+ return x(d.timestamp);
+ }).attr("cy", function(d) {
+ return y(d.value);
+ })
+
+ // Apply the tooltip to each node
+ .on(
+ "mouseover",
+ function(d) {
+ d3.select("body").select(".tooltip").transition()
+ .duration(50).style("opacity", 1);
+ d3.select("body").select(".tooltip").html(
+ formatDate(new Date(d.timestamp)) + "<br/>"
+ + d.value + (unit ? " " + unit : ""))
+ .style("left", (d3.event.pageX) + "px").style(
+ "top", (d3.event.pageY - 28) + "px");
+ }).on(
+ "mouseout",
+ function(d) {
+ d3.select("body").select(".tooltip").transition()
+ .duration(500).style("opacity", 0);
+ });
+
+ // Add the X Axis
+ svg.append("g").attr("class", "x axis").attr("transform",
+ "translate(0," + height + ")").call(xAxis);
+
+ // Add the Y Axis
+ svg.append("g").attr("class", "y axis").call(yAxis);
+
+ // Add the title
+ svg.append("text").attr("x", (width / 2)).attr("y", 0 - (margin.top / 2))
+ .attr("text-anchor", "middle").style("font-size", "16px").style(
+ "text-decoration", "underline").text(title);
+
+ // Add the background
+ svg.selectAll(".tick:not(:first-of-type) line").attr("stroke", "#777")
+ .attr("stroke-dasharray", "2,2");
+}
+
+/*
+ * Generates random chart data. Used when initializing the charts so that they
+ * are not empty on load
+ */
+function generateRandomData() {
+ var data = [];
+ for (var i = 0; i < 30; i++) {
+ data.push({
+ timestamp : new Date().getTime() - (i * 5000),
+ value : Math.floor(Math.random() * 100) + 1
+ });
+ }
+ return data;
+}
+
+/*
+ * Update a chart belonging to a specific container
+ */
+function updateChart(container, data, nodeColour) {
+ var margin = {
+ top : 30,
+ right : 20,
+ bottom : 30,
+ left : 50
+ }, width = 600 - margin.left - margin.right, height = 270 - margin.top
+ - margin.bottom;
+ var parseDate = d3.time.format("%d-%b-%y").parse;
+
+ // Format the data for the chart
+ data.forEach(function(d) {
+ d.timestamp = d.timestamp;
+ d.value = +d.value;
+ });
+
+ // Select the chart
+ var svg = d3.select(container);
+
+ // Set the ranges
+ var x = d3.time.scale().range([ 0, width ]);
+ var y = d3.scale.linear().range([ height, 0 ]);
+
+ // Define the axes
+ var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5).innerTickSize(
+ -height).outerTickSize(0).tickPadding(10);
+
+ var yAxis = d3.svg.axis().scale(y).orient("left").ticks(10).innerTickSize(
+ -width).outerTickSize(0).tickPadding(10);
+
+ // Scale the range of the data
+ x.domain(d3.extent(data, function(d) {
+ return d.timestamp;
+ }));
+ y.domain([ 0, d3.max(data, function(d) {
+ return Math.ceil((d.value + 1) / 10) * 10;
+ }) ]);
+
+ // Update the valueline path
+ var valueline = d3.svg.line().x(function(d) {
+ return x(d.timestamp);
+ }).y(function(d) {
+ return y(d.value);
+ });
+
+ var unit = svg.select(".line").attr("unit");
+
+ // Remove all nodes
+ svg.selectAll("circle").remove();
+
+ // Set the node colour if one is passed in
+ if (!nodeColour) {
+ nodeColour = "#00A9D4"
+ }
+
+ // Make the changes
+ svg.select(".line").data(data) // change the line
+ .transition().duration(750).attr("d", valueline(data));
+ svg.select(".x.axis") // change the x axis
+ .transition().duration(750).call(xAxis.ticks(5));
+ svg.select(".y.axis") // change the y axis
+ .transition().duration(750).call(yAxis);
+
+ // Redraw the nodes based on the new data
+ svg.select("svg").select("g").selectAll("circle").data(data).enter()
+ .append("circle").attr("r", 3.5).attr("class", "circle").attr(
+ "fill", nodeColour).attr("cx", function(d) {
+ return x(d.timestamp);
+ }).attr("cy", function(d) {
+ return y(d.value);
+ })
+
+ // Apply the tooltip to each node
+ .on(
+ "mouseover",
+ function(d) {
+ d3.select("body").select(".tooltip").transition()
+ .duration(50).style("opacity", 1);
+ d3.select("body").select(".tooltip").html(
+ formatDate(new Date(d.timestamp)) + "<br/>"
+ + d.value + (unit ? " " + unit : ""))
+ .style("left", (d3.event.pageX) + "px").style(
+ "top", (d3.event.pageY - 28) + "px");
+ }).on(
+ "mouseout",
+ function(d) {
+ d3.select("body").select(".tooltip").transition()
+ .duration(500).style("opacity", 0);
+ });
+
+}
+
+/*
+ * Initialize a singleton div used as a floating tooltip for all charts
+ */
+function initTooltip() {
+ d3.select("body").append("div").attr("class", "tooltip").attr("id",
+ "tooltip").style("opacity", 0);
+}
+
+/*
+ * Format a date object to string
+ */
+function formatDate(date) {
+ return date.toLocaleString().replace(',', '');
+}
+
+export { initTooltip, createChart, updateChart }; \ No newline at end of file
diff --git a/gui-pdp-monitoring/src/webapp/js/MonitoringConfig.js b/gui-pdp-monitoring/src/webapp/js/MonitoringConfig.js
new file mode 100644
index 0000000..f929282
--- /dev/null
+++ b/gui-pdp-monitoring/src/webapp/js/MonitoringConfig.js
@@ -0,0 +1,127 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+// Configuration used for page layout and charts
+const config = {
+ refresh: 5000,
+ restPort: 17999,
+ engineService: {
+ parent: "engineService",
+ tableId: "engineServicesTable",
+ headers: [{
+ title: "Engine Service ID",
+ id: "engine_id"
+ }, {
+ title: "GroupName",
+ id: "group_name"
+ }, {
+ title: "SubGroupName",
+ id: "subgroup_name"
+ }, {
+ title: "HealthStatus",
+ id: "health_status"
+ }, {
+ title: "PdpState",
+ id: "pdp_state"
+ }, {
+ title: "Pap server:port",
+ id: "server_port"
+ }]
+ },
+ engineSummary: {
+ parent: "engineSummary",
+ tableId: "engineSummaryTable",
+ headers: [{
+ title: "Timestamp",
+ id: "timestamp"
+ }, {
+ title: "Sum of policy deploy",
+ id: "policy_deploy"
+ }, {
+ title: "Sum of policy deploy success",
+ id: "policy_deploy_success"
+ }, {
+ title: "Sum of policy deploy fail",
+ id: "policy_deploy_fail"
+ }, {
+ title: "Sum of policy executions",
+ id: "policy_executions"
+ }, {
+ title: "Sum of policy executions success",
+ id: "policy_executions_success"
+ }, {
+ title: "Sum of policy executions fail",
+ id: "policy_executions_fail"
+ }, {
+ title: "Up Time(ms)",
+ id: "up_time"
+ }],
+ chart: {
+ avgPolicyDurationChart: {
+ parent: "avgPolicyDuration",
+ title: "Average Policy Duration (ms)",
+ unit: "ms",
+ lineStroke: "#5FBADD",
+ nodeColour: "#00A9D4"
+ },
+ }
+ },
+ engineStatus: {
+ parent: "engineStatus",
+ tableId: "engineStatusTable",
+ headers: [{
+ title: "Timestamp",
+ id: "timestamp"
+ }, {
+ title: "Engine ID",
+ id: "engine_id"
+ }, {
+ title: "Engine Status",
+ id: "engine_status"
+ }, {
+ title: "Last Message",
+ id: "last_message"
+ }, {
+ title: "Up Time (ms)",
+ id: "up_time"
+ }, {
+ title: "Policy Executions",
+ id: "policy_executions"
+ }]
+ },
+ engineChart: {
+ lastPolicyDurationChart: {
+ parent: "lastPolicyDurationChart",
+ title: "Last Policy Duration (ms)",
+ unit: "ms",
+ lineStroke: "#F5A241",
+ nodeColour: "#F08A00"
+ },
+ averagePolicyDurationChart: {
+ parent: "averagePolicyDurationChart",
+ title: "Average Policy Duration (ms)",
+ unit: "ms",
+ lineStroke: "#00625F",
+ nodeColour: "#007B78"
+ }
+ }
+};
+
+export { config, }; \ No newline at end of file
diff --git a/gui-pdp-monitoring/src/webapp/js/MonitoringMain.js b/gui-pdp-monitoring/src/webapp/js/MonitoringMain.js
new file mode 100644
index 0000000..456f3a9
--- /dev/null
+++ b/gui-pdp-monitoring/src/webapp/js/MonitoringMain.js
@@ -0,0 +1,109 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+import $ from "jquery";
+import { initTooltip } from "./MonitoringChart";
+import { getEngineURL, clearEngineURL, setUpPage,
+ removeChildrenElementsByClass, ajax_get_statistics
+} from "./MonitoringUtils";
+import { setEngineServiceData } from "./PdpInformation";
+import { config } from "./MonitoringConfig";
+import { setEngineSummaryData } from "./PdpStatisticsSummary";
+import { highlightSelected } from "./PdpListView";
+import { setEngineStatusData } from "./PdpEngineWorkerStatus";
+
+function servicesCallback(data){
+ var engineURL = localStorage.getItem("pap-monitor-services");
+ if (engineURL) {
+ engineURL = JSON.parse(engineURL);
+ if (engineURL.hostname === data.server && engineURL.port === data.port) {
+ setEngineServiceData(data.engineId, window.groupName, window.subGroupName, data.healthStatus, data.pdpState, data.server, data.port);
+ setEngineSummaryData(data.status, data.timeStamp, data.policyDeployCount, data.policyDeploySuccessCount, data.policyDeployFailCount, data.policyExecutedCount, data.policyExecutedSuccessCount, data.policyExecutedFailCount);
+
+ if (window.engine_id === data.engineId){
+ setEngineStatusData(data.status, false);
+ }else{
+ removeChildrenElementsByClass(config.engineStatus.parent);
+ setEngineStatusData(data.status, true);
+ }
+
+ window.engine_id = data.engineId;
+
+ // Make content visible after data has been returned for the first time
+ if (!$(".content").is(':visible')) {
+ $(".content").fadeIn();
+ }
+
+ // Repeat the same request
+ setTimeout(function() {
+ window.servicesCall = ajax_get_statistics(window.restRootURL + "statistics/", servicesCallback,
+ window.services.useHttps, window.services.hostname, window.services.port,
+ window.services.username, window.services.password, window.id);
+ }, config.refresh);
+ }
+ }
+}
+
+/*
+ * Called after the DOM is ready
+ */
+$(document).ready(
+ function() {
+ window.restRootURL = location.protocol
+ + "//"
+ + window.location.hostname
+ + ':' + config.restPort
+ + (location.pathname.endsWith("/monitoring/") ? location.pathname.substring(0, location.pathname.indexOf("monitoring/")) : location.pathname)
+ + "papservices/monitoring/";
+ // Initialize tooltip for the charts
+ initTooltip();
+
+ // Set up the structure of the page
+ setUpPage(true);
+
+ // Check cookies for engine URL
+ getEngineURL();
+
+ // Add click event to config icon for clearing engine URL
+ $(".ebSystemBar-config").click(
+ function() {
+ // Clear the engine URL
+ clearEngineURL(true);
+
+ // Request the engine URL
+ getEngineURL();
+ }
+ );
+
+ ['hashchange', 'load'].forEach(event => window.addEventListener(event, function() {
+ // Get ID from url
+ window.id = window.location.hash.replace('#', '');
+ if (window.id !== ''){
+ var arr = window.id.split("/");
+ window.groupName = arr[0];
+ window.subGroupName = arr[1];
+ highlightSelected(window.id);
+ ajax_get_statistics(restRootURL + "statistics/", servicesCallback,
+ window.services.useHttps, window.services.hostname, window.services.port,
+ window.services.username, window.services.password, window.id);
+ }
+ }));
+ }
+); \ No newline at end of file
diff --git a/gui-pdp-monitoring/src/webapp/js/MonitoringTable.js b/gui-pdp-monitoring/src/webapp/js/MonitoringTable.js
new file mode 100644
index 0000000..229ef6a
--- /dev/null
+++ b/gui-pdp-monitoring/src/webapp/js/MonitoringTable.js
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/*
+ * Create a table with given headers
+ */
+function createEngineTable(parent, id, tableHeaders) {
+ var table = createTable(id);
+
+ var tableHead = document.createElement("thead");
+ table.appendChild(tableHead);
+ tableHead.setAttribute("id", "engineTableHeader");
+
+ var tableHeaderRow = document.createElement("tr");
+ tableHead.appendChild(tableHeaderRow);
+ tableHeaderRow.setAttribute("id", "engineTableHeaderRow");
+
+ for ( var t in tableHeaders) {
+ var tableHeader = document.createElement("th");
+ tableHeaderRow.appendChild(tableHeader);
+ tableHeader.setAttribute("id", "engineTableHeader");
+ tableHeader.appendChild(document.createTextNode(tableHeaders[t]));
+ }
+
+ var tableBody = document.createElement("tbody");
+ tableBody.setAttribute("id", "engineTableBody");
+ table.appendChild(tableBody);
+
+ parent.append(table);
+
+ return table;
+}
+
+/*
+ * Create a table and apply UISDK styles to it
+ */
+function createTable(id) {
+ var table = document.createElement("table");
+ table.setAttribute("id", id);
+ table.setAttribute("class", "papTable ebTable elTablelib-Table-table ebTable_striped");
+ return table;
+}
+
+export { createEngineTable }; \ No newline at end of file
diff --git a/gui-pdp-monitoring/src/webapp/js/MonitoringUtils.js b/gui-pdp-monitoring/src/webapp/js/MonitoringUtils.js
new file mode 100644
index 0000000..9c6e076
--- /dev/null
+++ b/gui-pdp-monitoring/src/webapp/js/MonitoringUtils.js
@@ -0,0 +1,416 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+import $ from "jquery";
+import { createEngineServiceTable } from "./PdpInformation";
+import { createEngineSummaryTable } from "./PdpStatisticsSummary";
+import { RenderPdpList } from "./PdpListView";
+
+/*
+ * Crate a dialog with input, attach it to a given parent and show an optional message
+ */
+function papDialogFormActivate(formParent, message) {
+ papUtilsRemoveElement("papDialogDiv");
+
+ var contentelement = document.createElement("papDialogDiv");
+ var formDiv = document.createElement("div");
+ var backgroundDiv = document.createElement("div");
+ backgroundDiv.setAttribute("id", "papDialogDivBackground");
+ backgroundDiv.setAttribute("class", "papDialogDivBackground");
+
+ backgroundDiv.appendChild(formDiv);
+ contentelement.appendChild(backgroundDiv);
+ formParent.appendChild(contentelement);
+
+ formDiv.setAttribute("id", "papDialogDiv");
+ formDiv.setAttribute("class", "papDialogDiv");
+
+ var headingSpan = document.createElement("span");
+ formDiv.appendChild(headingSpan);
+
+ headingSpan.setAttribute("class", "headingSpan");
+ headingSpan.innerHTML = "PAP Configuration";
+
+ var form = document.createElement("papDialog");
+ formDiv.appendChild(form);
+
+ form.setAttribute("id", "papDialog");
+ form.setAttribute("class", "form-style-1");
+ form.setAttribute("method", "post");
+
+ if (message) {
+ var messageLI = document.createElement("li");
+ messageLI.setAttribute("class", "dialogMessage");
+ messageLI.innerHTML = message;
+ form.appendChild(messageLI);
+ }
+
+ var services = localStorage.getItem("pap-monitor-services_old");
+ //url
+ var input = createDialogList(form, "papDialogUrlInput","Pap rest baseURL:", "services_url_input", "http://localhost:12345", (services && services !== "null") ? JSON.parse(services).useHttps + "://" + JSON.parse(services).hostname + ":"
+ + JSON.parse(services).port : "");
+
+ //UserName
+ createDialogList(form, "papDialogUsernameInput","Pap UserName:", "services_username_input", "username", (services && services !== "null") ? JSON.parse(services).username : "");
+
+ //Password
+ createDialogList(form, "papDialogPasswordInput","Pap Password:", "services_password_input", "password", (services && services !== "null") ? JSON.parse(services).password : "");
+
+ //submit
+ var inputLI = document.createElement("li");
+ form.appendChild(inputLI);
+ var submitInput = document.createElement("input");
+ submitInput.setAttribute("id", "submit");
+ submitInput.setAttribute("class", "button ebBtn");
+ submitInput.setAttribute("type", "submit");
+ submitInput.setAttribute("value", "Submit");
+ submitInput.onclick = papDialogFormSubmitPressed;
+ inputLI.appendChild(submitInput);
+
+ // Enter key press triggers submit
+ $(input).keyup(function(event) {
+ if (event.keyCode == 13) {
+ $(submitInput).click();
+ }
+ });
+
+ input.focus();
+}
+
+function createDialogList(form, forA, reminder, id, placeholder, value_old){
+ var diaLI = document.createElement("li");
+ form.appendChild(diaLI);
+
+ var diaLabel = document.createElement("label");
+ diaLI.appendChild(diaLabel);
+
+ diaLabel.setAttribute("for", forA);
+ diaLabel.innerHTML = reminder;
+
+ var diaLabelSpan = document.createElement("span");
+ diaLabel.appendChild(diaLabelSpan);
+
+ diaLabelSpan.setAttribute("class", "required");
+ diaLabelSpan.innerHTML = "*";
+
+ var input = document.createElement("input");
+ input.setAttribute("id", id);
+ input.setAttribute("placeholder", placeholder);
+ input.value = value_old;
+ diaLI.appendChild(input);
+ return input;
+}
+
+/*
+ * Create a dialog for displaying text
+ */
+function papTextDialogActivate(formParent, message, title) {
+ papUtilsRemoveElement("papDialogDiv");
+
+ var contentelement = document.createElement("div");
+ contentelement.setAttribute("id", "papDialogDiv")
+ var formDiv = document.createElement("div");
+ var backgroundDiv = document.createElement("div");
+ backgroundDiv.setAttribute("id", "papDialogDivBackground");
+ backgroundDiv.setAttribute("class", "papDialogDivBackground");
+
+ backgroundDiv.appendChild(formDiv);
+ contentelement.appendChild(backgroundDiv);
+ formParent.appendChild(contentelement);
+
+ formDiv.setAttribute("id", "papErrorDialogDiv");
+ formDiv.setAttribute("class", "papDialogDiv papErrorDialogDiv");
+
+ var headingSpan = document.createElement("span");
+ formDiv.appendChild(headingSpan);
+
+ headingSpan.setAttribute("class", "headingSpan");
+ headingSpan.innerHTML = title;
+
+ var form = document.createElement("div");
+ formDiv.appendChild(form);
+
+ form.setAttribute("id", "papDialog");
+ form.setAttribute("class", "form-style-1");
+ form.setAttribute("method", "post");
+
+ if (message) {
+ var messageLI = document.createElement("li");
+ messageLI.setAttribute("class", "dialogMessage");
+ messageLI.innerHTML = message;
+ form.appendChild(messageLI);
+ }
+
+ var inputLI = document.createElement("li");
+ form.appendChild(inputLI);
+
+ var cancelInput = document.createElement("input");
+ cancelInput.setAttribute("class", "button ebBtn");
+ cancelInput.setAttribute("type", "submit");
+ cancelInput.setAttribute("value", "Close");
+ cancelInput.onclick = newModelFormCancelPressed;
+ form.appendChild(cancelInput);
+}
+
+/*
+ * Create a Success dialog
+ */
+function papSuccessDialogActivate(formParent, message) {
+ papTextDialogActivate(formParent, message, "Success");
+}
+
+/*
+ * Create an Error dialog
+ */
+function papErrorDialogActivate(formParent, message) {
+ papTextDialogActivate(formParent, message, "Error");
+}
+
+/*
+ * Dialog cancel callback
+ */
+function newModelFormCancelPressed() {
+ papUtilsRemoveElement("papDialogDivBackground");
+}
+
+/*
+ * Dialog submit callback
+ */
+function papDialogFormSubmitPressed() {
+ var url = $('#services_url_input').val();
+ var userName = $('#services_username_input').val();
+ var passWord = $('#services_password_input').val();
+ if (url.length > 0 && userName.length > 0 && passWord.length > 0) {
+ var engineConfig = {
+ useHttps : url.split(":")[0] == "https"? "https": "http",
+ hostname : url.split(":")[1].split("//")[1],
+ port : url.split(":")[2],
+ username : userName,
+ password : passWord
+ };
+ localStorage.setItem("pap-monitor-services_old", JSON.stringify(engineConfig));
+ localStorage.setItem("pap-monitor-services", JSON.stringify(engineConfig));
+ papUtilsRemoveElement("papDialogDivBackground");
+ getEngineURL();
+ }
+}
+
+/*
+ * Remove an element from the page
+ */
+function papUtilsRemoveElement(elementname) {
+ var element = document.getElementById(elementname);
+ if (element != null) {
+ element.parentNode.removeChild(element);
+ }
+}
+
+function getHomepageURL() {
+ var homepageURL = location.protocol
+ + "//"
+ + window.location.hostname
+ + (location.port ? ':' + location.port : '')
+ + (location.pathname.endsWith("/monitoring/") ? location.pathname.substring(0, location.pathname
+ .indexOf("monitoring/")) : location.pathname);
+ location.href = homepageURL;
+}
+
+function removeChildrenElementsByClass(className){
+ var elements = document.getElementsByClassName(className);
+ elements[0].innerHTML = '';
+}
+
+/*
+ * Clears and resets all content on the page
+ */
+function setUpPage(clearPdps) {
+ // Hide all content
+ $('#content').hide();
+
+ // Clear each div
+ $('#content > div').each(function () {
+ $(this).empty();
+ });
+
+ // clear hashchange
+ history.replaceState(null, null, ' ');
+
+ //remove last search result of pdps.
+ if (clearPdps) {
+ removeChildrenElementsByClass('pdps__list');
+ } else {
+ localStorage.setItem("pap-monitor-services", localStorage.getItem("pap-monitor-services_old"));
+ }
+
+ // Reset trackers for tables
+ window.engineStatusTables = [];
+
+ // Set up content div's
+ createEngineServiceTable();
+ createEngineSummaryTable();
+}
+
+/*
+ * Retrieves the engine URL from the cookie. If it has not been set yet, then a
+ * dialog is shown asking for it
+ */
+function getEngineURL(message) {
+ // The engine URL is stored in a cookie using the key
+ // "pap-monitor-services"
+ var services = localStorage.getItem("pap-monitor-services");
+
+ // If an engine URL is stored in the cookie
+ if (services) {
+ // Parse the engine URL
+ window.services = JSON.parse(services);
+
+ // Send a request with that engine URL
+ ajax_get(window.restRootURL, getPdpList,
+ window.services.useHttps, window.services.hostname, window.services.port,
+ window.services.username, window.services.password);
+ } else {
+ // Prompt for engine URL
+ papDialogFormActivate(document.body, message);
+ }
+}
+
+/*
+ * Clears the cookie and reset the page
+ */
+function clearEngineURL(clearPdps) {
+
+ if (typeof window.servicesCall !== "undefined") {
+ window.servicesCall.abort();
+ }
+
+ // Remove engine URL from cookie
+ localStorage.removeItem("pap-monitor-services");
+
+ // Reset the page
+ setUpPage(clearPdps);
+}
+
+function getPdpList(data) {
+ const pdpArray = [];
+ for (let i = 0; i < data.groups.length; i++) {
+ var map = {};
+ map.title = data.groups[i].name;
+ map.children = [];
+ (data.groups[i].pdpSubgroups).forEach((pdpSubgroup, index) => {
+ map.children[index] = {};
+ map.children[index].title = pdpSubgroup.pdpType;
+ const instanceId = [];
+ pdpSubgroup.pdpInstances.forEach(pdpInstance => {
+ var instanceIdMap = {};
+ instanceIdMap.title = pdpInstance.instanceId;
+ instanceId.push(instanceIdMap)
+ });
+ map.children[index].children = instanceId;
+ });
+ pdpArray.push(map);
+ }
+ RenderPdpList(pdpArray, 'pdps__list');
+}
+
+/*
+ * Send a GET request
+ */
+function ajax_get(requestURL, callback, useHttps, hostname, port, username, password, params, errorCallback) {
+ var data = {
+ useHttps: useHttps,
+ hostname: hostname,
+ port: port,
+ username: username,
+ password: password
+ };
+ for (var p in params) {
+ data[p] = params[p];
+ }
+ return $.ajax({
+ type: 'GET',
+ url: requestURL,
+ dataType: "json",
+ data: data,
+ success: function (data, textStatus, jqXHR) {
+ if (callback) {
+ callback(data);
+ }
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ if (jqXHR.status == 500 || jqXHR.status == 404) {
+ if (jqXHR.status == 404 || jqXHR.responseText.indexOf("Request failed.") !== -1) {
+ clearEngineURL(true);
+ getEngineURL("Cannot connect to PAP");
+ } else {
+ papErrorDialogActivate(document.body, jqXHR.responseText);
+ }
+ }
+ if (errorCallback) {
+ errorCallback(jqXHR, textStatus, errorThrown);
+ }
+ }
+ });
+}
+
+function ajax_get_statistics(requestURL, callback, useHttps, hostname, port, username, password, id, params, errorCallback) {
+ var data = {
+ useHttps: useHttps,
+ hostname: hostname,
+ port: port,
+ username: username,
+ password: password,
+ id: id
+ };
+ for (var p in params) {
+ data[p] = params[p];
+ }
+ return $.ajax({
+ type: 'GET',
+ url: requestURL,
+ dataType: "json",
+ data: data,
+ success: function (data, textStatus, jqXHR) {
+ if (callback) {
+ callback(data);
+ }
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ if (jqXHR.status == 500 || jqXHR.status == 404) {
+ clearEngineURL(false);
+ papErrorDialogActivate(document.body, "Failed to get Statistics in DB.");
+ }
+ if (errorCallback) {
+ errorCallback(jqXHR, textStatus, errorThrown);
+ }
+ }
+ });
+}
+
+export {
+ removeChildrenElementsByClass,
+ papDialogFormActivate,
+ papErrorDialogActivate,
+ clearEngineURL,
+ getEngineURL,
+ setUpPage,
+ ajax_get,
+ ajax_get_statistics,
+ papUtilsRemoveElement,
+}; \ No newline at end of file
diff --git a/gui-pdp-monitoring/src/webapp/js/PdpEngineWorkerStatus.js b/gui-pdp-monitoring/src/webapp/js/PdpEngineWorkerStatus.js
new file mode 100644
index 0000000..4ba8703
--- /dev/null
+++ b/gui-pdp-monitoring/src/webapp/js/PdpEngineWorkerStatus.js
@@ -0,0 +1,147 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+import $ from "jquery";
+import { createEngineTable } from "./MonitoringTable";
+import { config } from "./MonitoringConfig";
+import { createChart, updateChart } from "./MonitoringChart";
+/*
+ * Create an Engine Status Table and its charts
+ */
+function createEngineStatusTable(id, startStopStatus) {
+ var tableId = config.engineStatus.tableId;
+ var headers = config.engineStatus.headers;
+
+ // Create a wrapper div for both the table and the charts
+ var wrapper = document.createElement("div");
+ wrapper.setAttribute("id", id + "_wrapper");
+ wrapper.setAttribute("class", "wrapper");
+ $("." + config.engineStatus.parent).append(wrapper);
+
+ // Create the table
+ var table = createEngineTable($(wrapper), id, headers.map(function(a) {
+ return a.title;
+ }));
+ var tableRow = document.createElement("tr");
+ var tableData = "";
+ for ( var h in headers) {
+ tableData += "<td id=" + tableId + "_" + headers[h].id + "></td>";
+ }
+ tableRow.innerHTML = tableData;
+ // var actionTD = $(tableRow).find("#" + tableId + "_action");
+ // var checked = (startStopStatus === "STOPPED") ? "checked" : "";
+ var chartWrapper = document.createElement("div");
+ chartWrapper.setAttribute("id", "chartWrapper");
+
+ $(table).children("#engineTableBody").append(tableRow);
+
+ var expand = document.createElement("i");
+ expand.setAttribute("class", "ebIcon ebIcon_rowExpanded ebIcon_large ebIcon_interactive expandIcon");
+ $(expand).click(function() {
+ if ($(chartWrapper).is(":visible")) {
+ expand.setAttribute("class", "ebIcon ebIcon_rowCollapsed ebIcon_large ebIcon_interactive expandIcon");
+ } else {
+ expand.setAttribute("class", "ebIcon ebIcon_rowExpanded ebIcon_large ebIcon_interactive expandIcon");
+ }
+ $(chartWrapper).slideToggle();
+ }.bind(window));
+ $(wrapper).append(expand);
+ $(wrapper).append(chartWrapper);
+ return table;
+}
+
+/*
+ * Check for any changes in the Engine Status Table data and its charts and
+ * update only where necessary
+ */
+function setEngineStatusData(engineStatusData, changed) {
+ var tableId = config.engineStatus.tableId;
+ var headers = config.engineStatus.headers.map(function(a) {
+ return a.id;
+ });
+ for ( var esd in engineStatusData) {
+ var id = tableId + "_" + engineStatusData[esd].id;
+ var existingTable = undefined;
+ for ( var est in window.engineStatusTables) {
+ if (id === window.engineStatusTables[est].getAttribute("id")) {
+ existingTable = window.engineStatusTables[est];
+ }
+ }
+
+ var data = [ engineStatusData[esd].timestamp, id.split("_")[1], engineStatusData[esd].status,
+ engineStatusData[esd].lastMessage, engineStatusData[esd].upTime,
+ engineStatusData[esd].policyExecutions ];
+
+ var table = existingTable;
+ // If no table already exists for the engine, add one
+ if (!table || changed) {
+ table = createEngineStatusTable(id, engineStatusData[esd].status);
+ table.setAttribute("id", id);
+ table.style["margin-bottom"] = "10px";
+ table.style.display = "inline-block";
+ window.engineStatusTables.push(table);
+ }
+
+ // Update data in table
+ for ( var h in headers) {
+ var td = $(table).find("#" + tableId + "_" + headers[h]);
+ if (td.html() !== data[h]) {
+ $(table).find("#" + tableId + "_" + headers[h]).html(data[h]);
+ }
+ }
+
+ // Update charts
+ var wrapper = $(table).parent();
+ var chartWrapper = $(wrapper).find("#chartWrapper")
+
+ var chartConfig = config.engineChart.lastPolicyDurationChart;
+ var lastPolicyDurationChart = wrapper.find("#" + chartConfig.parent)[0];
+ if (lastPolicyDurationChart) {
+ updateChart(lastPolicyDurationChart, JSON.parse(engineStatusData[esd].lastPolicyDuration),
+ chartConfig.nodeColour);
+ } else {
+ chartConfig = config.engineChart.lastPolicyDurationChart;
+ var lastPolicyDurationDiv = document.createElement("div");
+ lastPolicyDurationDiv.setAttribute("id", chartConfig.parent);
+ lastPolicyDurationDiv.setAttribute("class", "papChart");
+ createChart(JSON.parse(engineStatusData[esd].lastPolicyDuration), lastPolicyDurationDiv,
+ chartConfig.title, chartConfig.unit, chartConfig.lineStroke, chartConfig.nodeColour);
+ $(chartWrapper).append(lastPolicyDurationDiv);
+ }
+
+ chartConfig = config.engineChart.averagePolicyDurationChart;
+ var averagePolicyDurationChart = wrapper.find("#" + chartConfig.parent)[0];
+ if (averagePolicyDurationChart) {
+ updateChart(averagePolicyDurationChart, JSON.parse(engineStatusData[esd].averagePolicyDuration),
+ chartConfig.nodeColour);
+ } else {
+ chartConfig = config.engineChart.averagePolicyDurationChart;
+ var averagePolicyDurationDiv = document.createElement("div");
+ averagePolicyDurationDiv.setAttribute("id", chartConfig.parent);
+ averagePolicyDurationDiv.setAttribute("class", "papChart");
+ createChart(JSON.parse(engineStatusData[esd].averagePolicyDuration), averagePolicyDurationDiv,
+ chartConfig.title, chartConfig.unit, chartConfig.lineStroke, chartConfig.nodeColour);
+ $(chartWrapper).append(averagePolicyDurationDiv);
+ }
+
+ }
+}
+
+export { setEngineStatusData, }; \ No newline at end of file
diff --git a/gui-pdp-monitoring/src/webapp/js/PdpInformation.js b/gui-pdp-monitoring/src/webapp/js/PdpInformation.js
new file mode 100644
index 0000000..cbb71a7
--- /dev/null
+++ b/gui-pdp-monitoring/src/webapp/js/PdpInformation.js
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+import $ from "jquery";
+import { config } from "./MonitoringConfig";
+import { createEngineTable } from "./MonitoringTable";
+
+/*
+ * Create the Engine Service Table
+ */
+function createEngineServiceTable() {
+ var tableId = config.engineService.tableId;
+ var headers = config.engineService.headers;
+ var table = createEngineTable($("." + config.engineService.parent), tableId, headers.map(function(a) {
+ return a.title;
+ }));
+ var tableRow = document.createElement("tr");
+ var tableData = "";
+ for ( var h in headers) {
+ tableData += "<td id=" + tableId + "_" + headers[h].id + "></td>";
+ }
+ tableRow.innerHTML = tableData;
+ $(table).children("#engineTableBody").append(tableRow);
+}
+
+/*
+ * Check for any changes in the Engine Service Table data and update only where
+ * necessary
+ */
+function setEngineServiceData(engineId, groupName, subGroupName, healthStatus, pdpState, server, port) {
+ window.engineId = engineId;
+ var tableId = config.engineService.tableId;
+ var headers = config.engineService.headers.map(function(a) {
+ return a.id;
+ });
+ var data = [ engineId, groupName, subGroupName, healthStatus, pdpState, server + ":" + port ];
+
+ var engineServiceTable = $("#engineServicesTable");
+
+ for ( var h in headers) {
+ var td = engineServiceTable.find("#" + tableId + "_" + headers[h]);
+ if (td.html() !== data[h]) {
+ engineServiceTable.find("#" + tableId + "_" + headers[h]).html(data[h]);
+ }
+ }
+};
+
+export { createEngineServiceTable, setEngineServiceData }; \ No newline at end of file
diff --git a/gui-pdp-monitoring/src/webapp/js/PdpListView.js b/gui-pdp-monitoring/src/webapp/js/PdpListView.js
new file mode 100644
index 0000000..1457a9e
--- /dev/null
+++ b/gui-pdp-monitoring/src/webapp/js/PdpListView.js
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+function RenderPdpList(treeArr, className) {
+ var $ = treeArr,
+ root = document.createDocumentFragment(),
+ childLevel = 0
+ var index=''
+ var isNode=false
+ function insertChildren(parentNode, traverseArr, subGroup) {
+
+ for(let i = 0; i < traverseArr.length; i++) {
+ if(parentNode === root) {
+ childLevel = 0
+ }
+ var currentLi = document.createElement('li')
+ currentLi.setAttribute('level', childLevel)
+ if(traverseArr[i].children && traverseArr[i].children.length > 0) {
+ var title = document.createElement('div')
+ var triangle = document.createElement('i')
+ var text = document.createElement('p')
+ currentLi.classList.add('parentNode')
+ title.classList.add('title')
+ triangle.classList.add('triangle')
+ text.innerText = traverseArr[i].title
+ title.appendChild(triangle)
+ title.appendChild(text)
+ currentLi.appendChild(title)
+ childLevel++
+ if(isNode) index=""
+ if(subGroup !== null){
+ index+= subGroup+"/"
+ }
+ insertChildren(currentLi, traverseArr[i].children, traverseArr[i].title)
+ }else {
+ var a = document.createElement('a')
+ a.setAttribute('href',"#"+index+subGroup+"/"+traverseArr[i].title)
+ a.classList.add('pdps__link')
+ a.textContent= traverseArr[i].title
+ currentLi.appendChild(a)
+ isNode=true
+ }
+ parentNode.appendChild(currentLi)
+ }
+ }
+ insertChildren(root, $, null)
+ document.querySelector('ul.' + className + '').appendChild(root)
+}
+
+function highlightSelected (id){
+ const resultsArr = Array.from(document.querySelectorAll('.pdps__link'));
+ resultsArr.forEach(el => {
+ el.classList.remove('pdps__link--active');
+ });
+ document.querySelector(`.pdps__link[href*="${id}"]`).classList.add('pdps__link--active');
+};
+
+export { RenderPdpList, highlightSelected, }; \ No newline at end of file
diff --git a/gui-pdp-monitoring/src/webapp/js/PdpStatisticsSummary.js b/gui-pdp-monitoring/src/webapp/js/PdpStatisticsSummary.js
new file mode 100644
index 0000000..4060c05
--- /dev/null
+++ b/gui-pdp-monitoring/src/webapp/js/PdpStatisticsSummary.js
@@ -0,0 +1,142 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+import $ from "jquery";
+import { config } from "./MonitoringConfig";
+import { createEngineTable } from "./MonitoringTable";
+import { createChart, updateChart } from "./MonitoringChart";
+import { papUtilsRemoveElement } from "./MonitoringUtils";
+
+/*
+ * Create the Engine Service Table
+ */
+function createEngineSummaryTable() {
+ var tableId = config.engineSummary.tableId;
+ var headers = config.engineSummary.headers;
+
+ // Create a wrapper div for both the table and the charts
+ var wrapper = document.createElement("div");
+ wrapper.setAttribute("id", "engineSummary_wrapper");
+ wrapper.setAttribute("class", "wrapper_borderless");
+ $("." + config.engineSummary.parent).append(wrapper);
+
+ var table = createEngineTable($(wrapper), tableId, headers.map(function(a) {
+ return a.title;
+ }));
+ var tableRow = document.createElement("tr");
+ var tableData = "";
+ for ( var h in headers) {
+ tableData += "<td id=" + tableId + "_" + headers[h].id + "></td>";
+ }
+ tableRow.innerHTML = tableData;
+
+ $(table).children("#engineTableBody").append(tableRow);
+
+}
+
+function setEngineSummaryData(data, timeStamp, policyDeployCount, policyDeploySuccessCount, policyDeployFailCount, policyExecutedCount, policyExecutedSuccessCount, policyExecutedFailCount) {
+ _setEngineSummaryData(timeStamp, getAvgPolicyDuration(data), policyDeployCount, policyDeploySuccessCount, policyDeployFailCount, policyExecutedCount, policyExecutedSuccessCount, policyExecutedFailCount, getUptimeOfOldestEngine(data));
+}
+
+/*
+ * Check for any changes in the Engine Summary Table data and update only where
+ * necessary
+ */
+function _setEngineSummaryData(timestamp, avgPolicyDuration, policyDeployCount, policyDeploySuccessCount, policyDeployFailCount, policyExecutedCount, policyExecutedSuccessCount, policyExecutedFailCount, upTime) {
+
+ var tableId = config.engineSummary.tableId;
+ var headers = config.engineSummary.headers.map(function(a) {
+ return a.id;
+ });
+ var data = [ timestamp, policyDeployCount, policyDeploySuccessCount, policyDeployFailCount, policyExecutedCount, policyExecutedSuccessCount, policyExecutedFailCount ,upTime == -1? "N/A":upTime];
+
+ var engineSummaryTable = $("#engineSummaryTable");
+
+ for ( var h in headers) {
+ var td = engineSummaryTable.find("#" + tableId + "_" + headers[h]);
+ if (td.html() !== data[h]) {
+ engineSummaryTable.find("#" + tableId + "_" + headers[h]).html(data[h]);
+ }
+ }
+
+ // Update charts
+ var wrapper = engineSummaryTable.parent();
+ var chartConfig = config.engineSummary.chart.avgPolicyDurationChart;
+ var avgPolicyDurationChart = wrapper.find("#" + chartConfig.parent)[0];
+ if (avgPolicyDuration.length) {
+ if (avgPolicyDurationChart) {
+ updateChart(avgPolicyDurationChart, avgPolicyDuration, chartConfig.nodeColour);
+ } else {
+ var avgPolicyDurationDiv = document.createElement("div");
+ avgPolicyDurationDiv.setAttribute("id", chartConfig.parent);
+ avgPolicyDurationDiv.setAttribute("class", "papChart_inline");
+ createChart(avgPolicyDuration, avgPolicyDurationDiv, chartConfig.title, chartConfig.unit,
+ chartConfig.lineStroke, chartConfig.nodeColour);
+ $(wrapper).append(avgPolicyDurationDiv);
+ }
+ } else if (avgPolicyDurationChart){
+ papUtilsRemoveElement(chartConfig.parent);
+ }
+}
+
+function getUptimeOfOldestEngine(data) {
+ var oldestUpTime = -1;
+ for ( var d in data) {
+ if (data[d].upTime > oldestUpTime) {
+ oldestUpTime = data[d].upTime;
+ }
+ }
+ return oldestUpTime;
+}
+
+function getSumOfPolicyExecutions(data) {
+ var totalPolicyExecutions = 0;
+ for ( var d in data) {
+ totalPolicyExecutions += data[d].policyExecutions;
+ }
+ return totalPolicyExecutions;
+}
+
+function getAvgPolicyDuration(data) {
+ var chartData = [];
+ var avgPolicyDurations = [];
+ for ( var d in data) {
+ var avgPolicyDuration = JSON.parse(data[d].averagePolicyDuration);
+ avgPolicyDurations.push(avgPolicyDuration);
+ }
+
+ if (avgPolicyDurations.length > 0) {
+ chartData = avgPolicyDurations[0];
+ for (var i = 1; i < avgPolicyDurations.length; i++) {
+ var engineData = avgPolicyDurations[i];
+ for ( var c in chartData) {
+ chartData[c].value += engineData[c].value;
+ }
+ }
+ }
+
+ for ( var c2 in chartData) {
+ chartData[c2].value = Math.round(chartData[c2].value / data.length);
+ }
+
+ return chartData;
+}
+
+export { createEngineSummaryTable, setEngineSummaryData, }; \ No newline at end of file
diff --git a/gui-pdp-monitoring/src/webapp/js/__test__/MonitoringUtils.test.js b/gui-pdp-monitoring/src/webapp/js/__test__/MonitoringUtils.test.js
new file mode 100644
index 0000000..45fae79
--- /dev/null
+++ b/gui-pdp-monitoring/src/webapp/js/__test__/MonitoringUtils.test.js
@@ -0,0 +1,19 @@
+import $ from 'jquery';
+import { ajax_get, ajax_get_statistics } from "../MonitoringUtils";
+
+$.ajax = jest.fn().mockImplementation(() => {
+ const fakeResponse = {
+ data: {
+ id: 1,
+ name: "All",
+ value: "Dummy Data"
+ }
+ };
+ return Promise.resolve(fakeResponse);
+});
+
+test('ajax_get return ok', () => {
+ ajax_get().then(response => {
+ expect(response.data.id).toBe(1);
+ });
+}); \ No newline at end of file