### Get Source List Entry by ID Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Finds and returns a specific entry from a source list based on its ID. Used to retrieve CRC information for binary file diffs. ```javascript function getSourceListEntry(name, srcList) { var retval $.each(srcList, function(i, v) { if (v.id == name) { retval = v return false } }) return retval } ``` -------------------------------- ### Render Package and iFlow Selection Options Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Populates dropdowns for tenant, package, and iFlow selection based on provided package content. It sorts options alphabetically and caches them for performance. Handles initial rendering and subsequent updates based on user selections. ```javascript function renderPackageContent(pkgContent) { var htmlSelTenants = "" var htmlSelPackages = "" var htmlSelIFlows = "" $.each(pkgContent.result, function(i, v) { htmlSelTenants += `` v.content.sort(function(a, b) { var x = a.name.toLowerCase(), y = b.name.toLowerCase(); return x < y ? -1 : x > y ? 1 : 0; }); $.each(v.content, function(ii, vv) { var optPkg = `` if (htmlSelPackages.indexOf(optPkg) == -1) htmlSelPackages += optPkg vv.iFlows.sort(function(a, b) { var x = a.name.toLowerCase(), y = b.name.toLowerCase(); return x < y ? -1 : x > y ? 1 : 0; }); $.each(vv.iFlows, function(iii, vvv) { var optIfl = `` if (htmlSelIFlows.indexOf(optIfl) == -1) htmlSelIFlows += optIfl }) }) }) $('#select-tenant-1').html(htmlSelTenants) $('#select-tenant-2').html(htmlSelTenants) $('#select-package-1').html(htmlSelPackages) $('#select-package-2').html(htmlSelPackages) $('#select-iflow-1').html(htmlSelIFlows) $('#select-iflow-2').html(htmlSelIFlows) $optionsCachePackages1 = $('#select-package-1').find('option') $optionsCachePackages2 = $('#select-package-2').find('option') $optionsCacheIFlows1 = $('#select-iflow-1').find('option') $optionsCacheIFlows2 = $('#select-iflow-2').find('option') } ``` -------------------------------- ### Handle Tenant Selection Change Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Updates the package dropdown based on the selected tenant. Filters cached package options to show only those belonging to the chosen tenant and triggers a change event for further updates. ```javascript $('#select-tenant-1').on('change', function() { $('#select-package-1').html($optionsCachePackages1.filter(`[value="${this.options[this.selectedIndex].text}"]`)); $('#select-package-1').val($("#select-package-1 option:first").val()) $('#select-package-1').trigger('change') }).trigger('change'); $('#select-tenant-2').on('change', function() { $('#select-package-2').html($optionsCachePackages2.filter(`[value="${this.options[this.selectedIndex].text}"]`)); $('#select-package-2').val($("#select-package-2 option:first").val()) $('#select-package-2').trigger('change') }).trigger('change') ``` -------------------------------- ### Load and Display Endpoints Table Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Initializes and loads data into a Bootstrap table for displaying endpoints. Handles different environments (local vs. remote) and uses AJAX for fetching data from a specified endpoint. ```javascript function loadEndpointList(){ var endpointsTable = $('table#endpoints') endpointsTable.bootstrapTable() endpointsTable.bootstrapTable('showLoading') try { if (window.location.protocol == "file:" || location.hostname === "localhost" || location.hostname === "127.0.0.1") { endpointsTable.bootstrapTable('destroy') var loadedMaterials = loadEndpointsTableData(endpoints) endpointsTable.bootstrapTable() endpointsTable.bootstrapTable('showLoading') endpointsTable.bootstrapTable('load', loadedMaterials) $('p[data-toggle="popover"]').popover() endpointsTable.bootstrapTable('hideLoading') } else { $.ajax({ xhrFields: { withCredentials: true }, url: "<>" }).done(function(endpoints) { console.log("Got response from CPI for endpoints content"); endpointsTable.bootstrapTable('destroy') var loadedMaterials = ``` -------------------------------- ### Load CPI Package Content Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Fetches package content from the CPI diffutils endpoint using AJAX. Handles local/localhost access by using a provided object, and displays errors using a modal. ```javascript function loadPackageContent() { try { if (window.location.protocol == "file:" || location.hostname === "localhost" || location.hostname === "127.0.0.1") { renderPackageContent(iFlowPackageContent); } else { $.ajax({ xhrFields: { withCredentials: true }, url: "<>?mode=packages" }).done(function(iFlowPackageContent) { console.log("Got response from CPI for diffutils/package content"); renderPackageContent(iFlowPackageContent); }).fail(function(jqxhr, textStatus, error) { console.log(textStatus) console.log(error) var err = jqxhr.responseJSON[0].error; var htmlError = `

Error ${err.code}

${err.message}

Error text: ${err.exception.text}

` $('#modal-error-body').html(htmlError); $('#modal-error').modal('show'); }); } } catch (ex) { alert(ex) console.log(ex) } } ``` -------------------------------- ### Initiate iFlow Comparison Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Handles the click event for the 'Compare iFlows' button. It checks for draft status on selected iFlow versions and either displays an error modal or proceeds to load the iFlow difference. ```javascript $('#btn-compare-iflows').prop('disabled', '') $('#btn-compare-iflows').click(function() { if (!$('#select-version-1').prop('disabled') && ($("#select-version-1 option[value='Draft']").length !== 0 || $("#select-version-2 option[value='Draft']").length !== 0)){ var htmlError = `

Draft Error

Error text: The "compare IFlow on version level" feature can only be used, if both artifacts are saved as version. At least one of the two objects to be compared are in state "Draft". Please save both IFlows "as version" first.
` $('#modal-error-body').html(htmlError) $('#modal-error').modal('show') } else { loadIFlowDiff() } }) ``` -------------------------------- ### Display Hardware Information Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Displays total CPU count, core count, and detailed CPU information including model name, vendor ID, frequency, cache size, and cores per CPU. Also renders disk usage percentages and capacities. ```javascript var cpuTotal = `${' '.repeat(data[1].hardwareInfo.cpuInfo.totalCpus)} (${data[1].hardwareInfo.cpuInfo.totalCpus}) ` $('#cpu-total').html(cpuTotal) var coreTotal = `${' '.repeat(data[1].hardwareInfo.cpuInfo.totalCores)} (${data[1].hardwareInfo.cpuInfo.totalCores}) ` $('#core-total').html(coreTotal) var cpuDetailsHtml = '
' $.each(data[1].hardwareInfo.cpuInfo.cpuDetails, function(i, v) { cpuDetailsHtml += `
CPU Model name:${v.modelName}
Vendor-, Family-, Model-ID:${v.vendorId} / ${v.cpuFamilyId} / ${v.cpuModelId}
Frequency (Mhz):${v.frequencyMhz}
Cache size:${v.cacheSizeKb}
CPU Cores:${v.cores}
` if (i % 2 != 0 && i < (data[1].hardwareInfo.cpuInfo.cpuDetails.length - 1)) { //new row after seconds element, if not last element in collection cpuDetailsHtml += '
' } }) cpuDetailsHtml += '
' //close row $('#cpu-detail-container').html(cpuDetailsHtml) //Render disk usage var diskHtml = "" $.each(data[1].hardwareInfo.systemDisk, function(i, v) { var usePerc = number_format(v.usedSpaceBytes / v.totalSpaceBytes * 100, 0, ',', '') var color = usePerc < 50 ? "success" : (usePerc < 75 ? "warning" : "danger") diskHtml += `

${v.path} ${usePerc}% (${v.usedSpaceHu} of ${v.totalSpaceHu} in use)

` }) $('#cardbody-diskusage').html(diskHtml) ``` -------------------------------- ### Display Software Versions Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Lists software versions for the operating system, SAP CPI, Groovy, JVM, and XSLT Engine. It also dynamically generates a table for SAP CPI module versions. ```javascript var htmlTblMain = createTableRow("Operating system", data[0].osInfo.release) htmlTblMain += createTableRow("SAP CPI release", data[3].cpiInfo.versionInfo.cpiVersion) htmlTblMain += createTableRow("Groovy release", data[3].cpiInfo.versionInfo.groovyVersion) htmlTblMain += createTableRow("JVM version", data[2].jvmInfo.jvmSystemInfo.jvmVersion) htmlTblMain += createTableRow(`XSLT Engine (${data[3].cpiInfo.xsltEngineInfo.productName})`, data[3].cpiInfo.xsltEngineInfo.version) $('#tbl-main-modules').html(htmlTblMain) var htmlTblCpi = "" $.each(data[3].cpiInfo.versionInfo.moduleVersions, function(i, v) { htmlTblCpi += createTableRow(v.name, v.version) }) $('#tbl-cpi-modules').html(htmlTblCpi) ``` -------------------------------- ### Render iFlow Version History Options Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Renders the fetched iFlow version history into HTML options for a select element. It also manages a counter to determine when all version history loads are complete. ```javascript function renderIFlowVersionHistory(data, optionsId){ var optionsHtml $.each(data.result.versionList, function(i, v) { optionsHtml += `` }) $('#select-version-'+optionsId).html(optionsHtml) //Mark as done loadIFlowVersionLoadCounter-- //If last job, setup GUI if (loadIFlowVersionLoadCounter == 0){ $('#select-version-1,#select-version-2').prop("disabled", false) $('#alert-diff-versioning').fadeIn(250) $('.loading').fadeOut(250) } } ``` -------------------------------- ### Load iFlow Version History Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Initiates the loading of version history for two selected iFlows. It increments a counter and calls a function to fetch and render the version history data for each iFlow. ```javascript var loadIFlowVersionLoadCounter = 0 function loadIFlowVersionHistory(){ $('.loading').fadeIn(250) //Load first row loadIFlowVersionLoadCounter++ loadIFlowVersionHistoryData($('#select-tenant-1').val(), $('#select-package-1 option:selected').attr('data-regid'), $('#select-iflow-1 option:selected').attr('data-regid'), '1') //Load second row loadIFlowVersionLoadCounter++ loadIFlowVersionHistoryData($('#select-tenant-2').val(), $('#select-package-2 option:selected').attr('data-regid'), $('#select-iflow-2 option:selected').attr('data-regid'), '2') } ``` -------------------------------- ### Render File Name with Bolded Base Name Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Formats a file name by making the base name bold. Handles file names with or without directory paths. ```javascript function renderFileName(fName) { if (fName.indexOf('/') > -1) { return `${fName.substr(0,fName.lastIndexOf('/')+1)}${fName.substr(fName.lastIndexOf('/')+1)}` } else { return `${fName}` } } ``` -------------------------------- ### Configure Artifacts Table Popover Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Enables popovers for artifact rows with non-OK severity, displaying remarks on hover. Initializes popovers after table content is loaded. ```javascript function renderArtifactsTableRowAttributes(row, index) { if (row.Severity != 'OK') { return { 'data-toggle': 'popover', 'data-placement': 'bottom', 'data-trigger': 'hover', 'title': row.Severity + ": Remarks for '" + row.Id + "'", 'data-content': row.Remarks, 'data-html': true }; } return {}; } // Enables popover of renderArtifactsTableRowAttributes $(function() { $('#artifacts').on('post-body.bs.table', function(e) { $(' [data-toggle="popover"]').popover(); }); }); ``` -------------------------------- ### Load Log Viewer in Modal Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Opens a modal dialog to display the content of a log file by setting the iframe source to the provided URL. ```javascript function loadLogviewer(filename, extUrl) { $('#logviewer-title').html(filename) $('#logviewer-iframe').prop("src", extUrl) $('#modal-logviewer').modal('show') } ``` -------------------------------- ### Initialize Dashboard Variables Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Initializes key variables used for dashboard functionality, including timers, loading states, and shell command history. This code is typically run on page load. ```javascript var autoRefreshTimer var initialLoad = true var cacheAlertRules var shellExecuting = false var shellWindowContent = "" var shellHistory = [] var shellHistoryIndex = -1 ``` -------------------------------- ### Render iFlow Scheduler Information Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Renders scheduler information for iFlows, displaying runs by date and by interface. This includes cron details, next fire times, and externalization status. ```javascript function renderIFlowScheduler(scheduler) { var htmlTblScheduler24hRows = "" $.each(scheduler.byRunDate.runs, function(i, v) { htmlTblScheduler24hRows += createTableRow(`${v.datetime}`, ``) }) $('#tbl-scheduler-24h-rows').html(htmlTblScheduler24hRows) var htmlTblSchedulerByIFlowRows = "" $.each(scheduler.byInterface.list, function(i, v) { $.each(v.crons, function(ii, vv) { htmlTblSchedulerByIFlowRows += ` ${v.name}
Timer element: ${vv.cronInfo.id} ${vv.cronInfo.cron}
(${vv.cronInfo.cronHumanReadable}) ${!vv.cronInfo.isExternalized?'No':`Externalized via parameter ${vv.cronInfo.patternName}`} ` }) }) $('#tbl-tbl-scheduler-iflow-rows').html(htmlTblSchedulerByIFlowRows) $('.load-scheduler-info').hide() } ``` -------------------------------- ### Render Security Material Table Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Populates a table with security material details, including ID, type, username, and password. Includes functionality to toggle password visibility. ```javascript function renderSecurityMaterial(data) { try { var htmlTblSecmatRows = "" $.each(data, function(i, v) { htmlTblSecmatRows += ` ${v.id}
(${v.type}) ${v.user}
` }) $('#tbl-secmat-rows').html(htmlTblSecmatRows) $("#ipg-password button").on('click', function(event) { event.preventDefault(); var cont = $(this).parent().parent() if (cont.find('input').attr("type") == "text") { cont.find('input').attr('type', 'password') cont.find('i').addClass("fa-eye-slash") cont.find('i').removeClass("fa-eye") } else if (cont.find('input').attr("type") == "password") { cont.find('input').attr('type', 'text') cont.find('i').removeClass("fa-eye-slash") cont.find('i').addClass("fa-eye") } }) $('#pw-infobox').hide() $('#tbl-secmat').show() } catch (ex) { alert(ex) console.log(ex) } $('.loading').fadeOut(500) } ``` -------------------------------- ### Render Doughnut Chart Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Initializes and renders a doughnut chart using the Chart.js library. Configures chart appearance, tooltips, and legend. ```javascript function renderPieChart(elementId, labels, data) { Chart.defaults.global.defaultFontFamily = 'Nunito', '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'; Chart.defaults.global.defaultFontColor = '#858796'; var ctx = document.getElementById(elementId); var myPieChart = new Chart(ctx, { type: 'doughnut', data: { labels: labels, datasets: [{ data: data, backgroundColor: ['#6a6c77', '#80c801', '#36b9cc'], hoverBackgroundColor: ['#a0a3af', '#c5e887', '#2c9faf'], hoverBorderColor: "rgba(234, 236, 244, 1)", }], }, options: { maintainAspectRatio: false, tooltips: { backgroundColor: "rgb(255,255,255)", bodyFontColor: "#858796", borderColor: '#dddfeb', borderWidth: 1, xPadding: 15, yPadding: 15, displayColors: false, caretPadding: 10, }, legend: { display: false }, cutoutPercentage: 80, }, }); } ``` -------------------------------- ### Load iFlow Difference Comparison Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Initiates the comparison of two selected iFlow versions. It collects selection details and sends an AJAX POST request to the diff utility endpoint. ```javascript function loadIFlowDiff() { $('#modal-diff-body-info').show() $('#modal-diff-body-loading').show() $('#modal-diff-resultcontent').hide() $('#modal-diffutils').modal('show') var iFlowCompSelection = { "iFlow1": { "hostname": $('#select-tenant-1 option:selected').val(), "iFlowId": $('#select-iflow-1 option:selected').attr('data'), "versionSemanticSelected": $('#select-version-1 option:selected').val(), "versionTechnicalSelected": $('#select-version-1 option:selected').attr('data'), "versionSemanticCurrent": $('#select-version-1 option:first').val(), "versionTechnicalCurrent": $('#select-version-1 option:first').attr('data'), "iFlowRegId": $('#select-iflow-1 option:selected').attr('data-regid'), "packageRegId": $('#select-package-1 option:selected').attr('data-regid') }, "iFlow2": { "hostname": $('#select-tenant-2 option:selected').val(), "iFlowId": $('#select-iflow-2 option:selected').attr('data'), "versionSemanticSelected": $('#select-version-2 option:selected').val(), "versionTechnicalSelected": $('#select-version-2 option:selected').attr('data'), "versionSemanticCurrent": $('#select-version-2 option:first').val(), "versionTechnicalCurrent": $('#select-version-2 option:first').attr('data'), "iFlowRegId": $('#select-iflow-2 option:selected').attr('data-regid'), "packageRegId": $('#select-package-2 option:selected').attr('data-regid') } } try { $.ajax({ xhrFields: { withCredentials: true }, dataType: "json", type: "POST", contentType: "application/json", data: JSON.stringify(iFlowCompSelection), url: "<>" }).done(function(result) { console.log("Got response from CPI for requesting iflow diff"); renderDiffResult(result) }).fail(function(jqxhr, textStatus, error) { $('.loading').fadeOut(250) console.log(textStatus) console.log(error) var err = jqxhr.responseJSON !== undefined ? jqxhr.responseJSON[0].error : { "code": textStatus, "message": textStatus, "exception": { "text": error }, "dogception": "https://httpstatusdogs.com/img/503.jpg" } var htmlError = `

Error ${err.code}

${err.message}

Error text: ${err.exception.text}

` $('#modal-error-body').html(htmlError) $('#modal-error').modal('show') }); } catch (ex) { $('.loading').fadeOut(250) alert(ex) console.log(ex) } } ``` -------------------------------- ### Load iFlow Version History Data Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Fetches version history data for a specific iFlow using an AJAX request. It handles local development environments differently from deployed environments. Renders the history upon successful data retrieval. ```javascript function loadIFlowVersionHistoryData(hostname, packageRegId, iflowRegId, optionsId){ try { if (window.location.protocol == "file:" || location.hostname === "localhost" || location.hostname === "127.0.0.1") { renderIFlowVersionHistory(iFlowVersions, optionsId) } else { $.ajax({ xhrFields: { withCredentials: true }, url: ``` -------------------------------- ### Handle Package Selection Change Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Updates the iFlow dropdown based on the selected package. Filters cached iFlow options to show only those belonging to the chosen package and triggers a change event. ```javascript $('#select-package-1').on('change', function() { $('#select-iflow-1').html($optionsCacheIFlows1.filter(`[value="${this.options[this.selectedIndex].text}"]`)); $('#select-iflow-1').val($("#select-iflow-1 option:first").val()) $('#select-iflow-1,select-iflow-2').trigger('change') }).trigger('change'); $('#select-package-2').on('change', function() { $('#select-iflow-2').html($optionsCacheIFlows2.filter(`[value="${this.options[this.selectedIndex].text}"]`)); $('#select-iflow-2').val($("#select-iflow-2 option:first").val()) $('#select-iflow-1,select-iflow-2').trigger('change') }).trigger('change') ``` -------------------------------- ### Configure Alerting Rule UI Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Handles the UI changes for alert configuration based on the selected alert type (Message or Certificate). ```javascript $('#alert-conf-active').prop("checked", false) $('#alert-conf-certdays').val(14) $('.alert-message-only').show() $('.alert-cert-only').hide() } $(document).ready(function() { //DEBUG //$('#modal-diffutils').modal('show') //setTimeout(function(){renderDiffResult(diffResult)},1500) //Change alert config GUI in dependency to alert type $('#alert-conf-type').on('change', function() { if ($(this).val() == "Message") { $('.alert-message-only').show() $('.alert-cert-only').hide() } else { $('.alert-message-only').hide() $('.alert-cert-only').show() } }) $('#modal-alerting-save').click(function() { saveAlertRule() }) $('#modal-alerting-cancel').click(function() { cancelAlertRule() }) $('#modal-alerting-close').click(function() { cancelAlertRule() }) $('#btn-print').click(function() { window.print() }) $('#btn-alerting-add').click(function() { alertCreate() }) $('#btn-diff-specific-1,#btn-diff-specific-2').click(function(){ loadIFlowVersionHistory() }) //Add shell handlers $('#inp-shell-command').on('keyup', function (e) { if (e.keyCode === 13) { //Enter-Key executeShellCommand() } else if (e.keyCode === 38) { //Arrow up-key if (shellHistory.length > 0){ if (shellHistoryIndex > 0){ shellHistoryIndex-- } $("#inp-shell-command").val(shellHistory[shellHistoryIndex]) } } else if (e.keyCode === 40) { //Arrow down-key if (shellHistory.length > 0){ if (shellHistoryIndex < (shellHistory.length-1)){ shellHistoryIndex++ } $("#inp-shell-command").val(shellHistory[shellHistoryIndex]) } } }) $('#btn-shell-exec').click(function() { executeShellCommand() }) $('#dropdown-shell-clear').click(function(e) { e.preventDefault() shellWindowContent = "" $('#txtarea-shell').html('') }) $('#btn-auto-refresh').click(function() { var mode = $(this).attr('data') if (mode == "inactive") { $(this).attr('data', 'active') $(this).find('i').removeClass('fa-square') $(this).find('i').addClass('fa-check-square') $('#inp-auto-refresh').attr('readonly', true) var intVal = parseInt($('#inp-auto-refresh').val()) * 1000 autoRefreshTimer = setInterval(loadDashboardData, intVal) } else { $(this).attr('data', 'inactive') $(this).find('i').removeClass('fa-check-square') $(this).find('i').addClass('fa-square') $('#inp-auto-refresh').attr('readonly', false) clearInterval(autoRefreshTimer) } }) $('#accordionSidebar .nav-link').click(function() { $(".nav-item").removeClass("active") $(this).parent().addClass("active") }) loadDashboardData() //Load them in parallel, since they have their own loading animation and shouldn't be reloaded with auto load loadArtifactsContent() loadEndpointList() loadIFlowScheduler() loadPackageContent() }) ``` -------------------------------- ### Load and Display Endpoints Table Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Loads endpoint data into a Bootstrap Table. Handles both local file/localhost and remote API calls. Displays loading states and errors. ```javascript function loadEndpointsTableData(endpoints) { endpointsTable.bootstrapTable() endpointsTable.bootstrapTable('showLoading') endpointsTable.bootstrapTable('load', loadedMaterials) $(' [data-toggle="popover"] ').popover() endpointsTable.bootstrapTable('hideLoading') }).fail(function(jqxhr, textStatus, error) { console.log(textStatus) console.log(error) var err = jqxhr.responseJSON[0].error var htmlError = `

Error ${err.code}

${err.message}

Error text: ${err.exception.text}

` $('#modal-error-body').html(htmlError) $('#modal-error').modal('show') }); } } catch (ex) { alert(ex) console.log(ex) } } function loadArtifactsContent() { var artifactsTable = $('table#artifacts') artifactsTable.bootstrapTable() artifactsTable.bootstrapTable('showLoading') try { if (window.location.protocol == "file:" || location.hostname === "localhost" || location.hostname === "127.0.0.1") { artifactsTable.bootstrapTable('destroy') var loadedMaterials = loadArtifactsTableData(artifactsContent) artifactsTable.bootstrapTable() artifactsTable.bootstrapTable('showLoading') artifactsTable.bootstrapTable('load', loadedMaterials) $(' [data-toggle="popover"] ').popover() artifactsTable.bootstrapTable('hideLoading') } else { $.ajax({ xhrFields: { withCredentials: true }, url: "<>" }).done(function(artifactsContent) { console.log("Got response from CPI for artifacts content"); artifactsTable.bootstrapTable('destroy') var loadedMaterials = loadArtifactsTableData(artifactsContent) artifactsTable.bootstrapTable() artifactsTable.bootstrapTable('showLoading') artifactsTable.bootstrapTable('load', loadedMaterials) $(' [data-toggle="popover"] ').popover() artifactsTable.bootstrapTable('hideLoading') }).fail(function(jqxhr, textStatus, error) { console.log(textStatus) console.log(error) var err = jqxhr.responseJSON[0].error var htmlError = `

Error ${err.code}

${err.message}

Error text: ${err.exception.text}

` $('#modal-error-body').html(htmlError) $('#modal-error').modal('show') }); } } catch (ex) { alert(ex) console.log(ex) } } function loadEndpointsTableData(data){ // Handle endpoints var endpoints = data.result[0].endpoints var rows = [] var countIFlows = 0 var countEndpoints = 0 Object.keys(endpoints).forEach(function(key) { if (endpoints[key].endpointsFlat != null && endpoints[key].endpointsFlat.length > 0){ countIFlows++ } $.each(endpoints[key].endpointsFlat, function(k, v){ countEndpoints++ //clean endpoint var protocol = "other" var plainEndpoint = v if (plainEndpoint.indexOf("hana.ondemand.com") != -1){ plainEndpoint = plainEndpoint.substring(plainEndpoint.indexOf("hana.ondemand.com")+"hana.ondemand.com".length) } if (plainEndpoint.startsWith("/http")){ protocol = "http" plainEndpoint = plainEndpoint.substring(5) } else if (plainEndpoint.startsWith("/cxf")){ protocol = "cxf" plainEndpoint = plainEndpoint.substring(4) } // Prepare table row var row = [] row['Id'] = key row['Endpoint'] = `${plainEndpoint}` row['Type'] = protocol.toUpperCase() row['Link'] = `Url ` var wsdlUrl = findWsdlUrl(endpoints[key], plainEndpoint) if (protocol == "cxf" && wsdlUrl != ""){ row['WSDL'] = `Download ` } else { row['WSDL'] = "" } // Add table row to table data rows.push(row) }) }) // Add the number of rows per serverity to the legend $('#countEndpointsIFlows').html(countIFlows + "x") $('#countEndpointsEndpoints').html(countEndpoints + "x") return rows } function findWsdlUrl(endpointInfo, plainEndpoint){ var wsdlUrl = "" $.each(endpointInfo.endpointsDetailed, function(i,v){ $.each(v, function(ii,vv){ if (vv.type == "DEFINITION_WSDL" && vv.url.indexOf(`&servicePath=${plainEndpoint}&`) != -1){ wsdlUrl = vv.url } }) }) return wsdlUrl } function loadArtifactsTableData(data) { var systems = data["systems"] var artifacts = data["artifacts"] // Handle systems Object.keys(systems).forEach(function(key) { $('#artifactsTableColumnCategories').append('' + systems[key] + ' [' + key + ']') $('#artifactsTableColumns').append('Design Version [' + key + ']Runtime Version [' + key + ']>" }).done(function(scheduler) { console.log("Got response from CPI for scheduler"); renderIFlowScheduler(scheduler); }).fail(function(jqxhr, textStatus, error) { console.log(textStatus) console.log(error) var err = jqxhr.responseJSON[0].error; var htmlError = `

Error ${err.code}

${err.message}

Error text: ${err.exception.text}

` $('#modal-error-body').html(htmlError); $('#modal-error').modal('show'); }); } } catch (ex) { alert(ex) console.log(ex) } } ``` -------------------------------- ### Load iFlow Version History Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Fetches the version history for a given iFlow from the CPI system. Used to populate dropdowns for version selection in the diff utility. ```javascript function loadIFlowVersion(hostname, iflowRegId, packageRegId, optionsId) { try { $.ajax({ xhrFields: { withCredentials: true }, dataType: "json", type: "GET", url: "<>?mode=versions&hostname=${hostname}&iflowId=${iflowRegId}&pkgId=${packageRegId}" }).done(function(data) { console.log("Got response from CPI for IFlow version history"); renderIFlowVersionHistory(data, optionsId) }).fail(function(jqxhr, textStatus, error) { console.log(textStatus) console.log(error) var err = jqxhr.responseJSON[0].error var htmlError = `

Error ${err.code}

${err.message}

Error text: ${err.exception.text}

` $('#modal-error-body').html(htmlError) $('#modal-error').modal('show') }); } catch (ex) { alert(ex) console.log(ex) } } ``` -------------------------------- ### Render Diff HTML Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Renders the pretty HTML for a unified diff. Use this to display differences between two versions of a file. ```javascript Diff2Html.getPrettyHtml(data.totalUnifiedDiff, { inputFormat: 'diff', showFiles: true, matching: 'lines', outputFormat: 'side-by-side' }) ``` -------------------------------- ### Render Message Volume Charts Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Renders area charts for message volume over different time periods (last 30 days and today/yesterday). It processes raw data to prepare it for charting. ```javascript dataNow.labels.push(el.startDate.substring(0, 10)) } ix++ } }) //console.log(dataNow) $('#card-header-msg-volume-30').html(\` Message volume / last ${(batchSize*2)} days ecation) renderAreaChart("chart-message14days", dataNow, dataPast, "days") //Render message list - today var countHourlys = 0 $.each(data[3].cpiInfo.messageCountInfo, function(i, el) { countHourlys += (el.type == "HOURLY" ? 1 : 0) }) var batchSizeDaily = countHourlys / 2 var dataToday = { data: [], labels: [] } var dataYesterday = { data: [], labels: [] } ix = 0 $.each(data[3].cpiInfo.messageCountInfo, function(i, el) { if (el.type == "HOURLY") { if ((ix + 1) <= batchSizeDaily) { dataYesterday.data.push(el.count) dataYesterday.labels.push(el.startDate) } else { dataToday.data.push(el.count) dataToday.labels.push(el.startDate) } ix++ } }) renderAreaChart("chart-message-today", dataToday, dataYesterday, "hours") ``` -------------------------------- ### Render Diff Comparison Results Source: https://github.com/codebude/cpi-dashboard/blob/master/Webfrontend/index.html Processes the results of an iFlow difference comparison and updates the UI to display counts of different file types (text, binary, whitespace only, single files, similar files). ```javascript function renderDiffResult(data) { console.log(data) console.log("got diff result") //Get file/tab counts var countDiffText = 0, countDiffBin = 0, countSingleFiles = 0, countSimilar = 0, countLinebreakDifferent = 0 var iFlows = [] $.each(data.result, function(i, v) { if (iFlows.length != 2) { if (!iFlows.includes(v.sourceList[0].id)) { iFlows.push(v.sourceList[0].id) } if (!v.sourceList.length == 2 && iFlows.includes(v.sourceList[1].id)) { iFlows.push(v.sourceList[1].id) } } if (v.identical) { countSimilar++ } else { if (v.sourceList.length == 1) { countSingleFiles++ } else if (v.isTextBased) { if (v.unifiedDiff == "") { countLinebreakDifferent++ } else { countDiffText++ } } else { countDiffBin++ } } }) iFlows.sort() $('#diffmodal-difftext-tab').html(`Different text files (${countDiffText})`) $('#diffmodal-diffbin-tab').html(`Different binary files (${countDiffBin})`) $('#diffmodal-diffwhitespace-tab').html(`Different in linebreaks [\\r,\\n] only (${countLinebreakDifferent})`) $('#diffmodal-singlefiles-tab').html(`Files existing in one of both (${countSingleFiles})`) $('#diffmodal-similar-tab').html(`Similar files (${countSimilar})`) //Render text file diff var diffHtml = ```