From a026345abc4030bcb0353b197b0c2de71c4d1ef8 Mon Sep 17 00:00:00 2001 From: Akash Manna Date: Tue, 18 Feb 2025 08:24:50 +0530 Subject: [PATCH 1/3] Add chart click and context menu handling functions --- src/main/webapp/js/echarts-api.js | 142 ++++++++++++++++++++++++++---- 1 file changed, 126 insertions(+), 16 deletions(-) diff --git a/src/main/webapp/js/echarts-api.js b/src/main/webapp/js/echarts-api.js index f9fb54e..3a1a4ef 100644 --- a/src/main/webapp/js/echarts-api.js +++ b/src/main/webapp/js/echarts-api.js @@ -336,7 +336,7 @@ const echartsJenkinsApi = { const pointInPixel = [params.offsetX, params.offsetY]; const pointInGrid = chart.convertFromPixel('grid', pointInPixel); const buildDisplayName = chart.getModel().get('xAxis')[0].data[pointInGrid[0]] - chartClickedEventHandler(buildDisplayName); + handleChartClick(params.event, buildDisplayName, chartDivId); } }) } @@ -454,22 +454,24 @@ const echartsJenkinsApi = { const pointInPixel = [params.offsetX, params.offsetY]; const pointInGrid = chart.convertFromPixel('grid', pointInPixel); const buildDisplayName = chart.getModel().get('xAxis')[0].data[pointInGrid[0]] - const builds = chartPlaceHolder.model.buildNumbers; - const labels = chartPlaceHolder.model.domainAxisLabels; - - let selectedBuild = 0; - for (let i = 0; i < builds.length; i++) { - if (buildDisplayName === labels[i]) { - selectedBuild = builds[i]; - break; - } - } - - if (selectedBuild > 0) { - window.location.assign(selectedBuild + '/' + urlName); - } + handleChartClick(params.event, buildDisplayName, chartDivId); } - }) + }); + + + + + + chart.getZr().on('contextmenu', params => { + if (params.offsetY > 30) { // skip the legend + const pointInPixel = [params.offsetX, params.offsetY]; + const pointInGrid = chart.convertFromPixel('grid', pointInPixel); + const buildDisplayName = chart.getModel().get('xAxis')[0].data[pointInGrid[0]]; + handleContextMenu(params.event, buildDisplayName, chartDivId); + } + }); + + } } } @@ -671,3 +673,111 @@ const echartsJenkinsApi = { } } } + +//Add global function +function handleChartClick(event, buildDisplayName, chartDivId) { + let chartPlaceHolder = document.getElementById(chartDivId); + if (!chartPlaceHolder || !chartPlaceHolder.model) { + console.warn('Chart placeholder or model not found for:', chartDivId); + return; + } + + let builds = chartPlaceHolder.model.buildNumbers; + let labels = chartPlaceHolder.model.domainAxisLabels; + let urlName = chartPlaceHolder.getAttribute("tool"); + + + let selectedBuild = 0; + for (let i = 0; i < builds.length; i++) { + if (buildDisplayName === labels[i]) { + selectedBuild = builds[i]; + break; + } + } + + if (selectedBuild > 0) { + let url = selectedBuild + '/' + urlName; + + if (event.ctrlKey || event.which === 2) { // Ctrl+Click or Middle-click + window.open(url, '_blank'); // Open in new tab/window + } else if (event.shiftKey) { // Shift+Click + window.open(url, '_blank', 'noopener,noreferrer'); // Open in a new window (more isolated) + } else { + window.location.href = url; // Original behavior (same tab) + } + + event.preventDefault(); // Prevent default action if needed. + } +} + +// Add global function +function handleContextMenu(event, buildDisplayName, chartDivId) { + event.preventDefault(); // Prevent the browser's default context menu + + let chartPlaceHolder = document.getElementById(chartDivId); + if (!chartPlaceHolder || !chartPlaceHolder.model) { + console.warn('Chart placeholder or model not found for:', chartDivId); + return; + } + + let builds = chartPlaceHolder.model.buildNumbers; + let labels = chartPlaceHolder.model.domainAxisLabels; + let urlName = chartPlaceHolder.getAttribute("tool"); + + let selectedBuild = 0; + for (let i = 0; i < builds.length; i++) { + if (buildDisplayName === labels[i]) { + selectedBuild = builds[i]; + break; + } + } + + if (selectedBuild > 0) { + let url = selectedBuild + '/' + urlName; + + // Create a custom context menu + const contextMenu = document.createElement('div'); + contextMenu.style.position = 'absolute'; + contextMenu.style.left = event.clientX + 'px'; + contextMenu.style.top = event.clientY + 'px'; + contextMenu.style.border = '1px solid #ccc'; + contextMenu.style.backgroundColor = '#fff'; + contextMenu.style.padding = '5px'; + contextMenu.style.zIndex = '1000'; // Ensure it's above other elements + // Option to open in new tab + const openNewTabOption = document.createElement('div'); + openNewTabOption.textContent = 'Open in New Tab'; + openNewTabOption.style.cursor = 'pointer'; + openNewTabOption.addEventListener('click', () => { + window.open(url, '_blank'); + contextMenu.remove(); // Remove the context menu after selection + }); + contextMenu.appendChild(openNewTabOption); + + // Option to copy link address + const copyLinkOption = document.createElement('div'); + copyLinkOption.textContent = 'Copy Link Address'; + copyLinkOption.style.cursor = 'pointer'; + copyLinkOption.addEventListener('click', () => { + navigator.clipboard.writeText(url).then(() => { + // Optional: Provide feedback to the user that the link was copied + console.log('Link copied to clipboard'); + }).catch(err => { + console.error('Failed to copy link: ', err); + }); + contextMenu.remove(); // Remove the context menu after selection + }); + contextMenu.appendChild(copyLinkOption); + + // Add the context menu to the document + document.body.appendChild(contextMenu); + + // Remove the context menu when clicking outside of it + document.addEventListener('click', function removeContextMenu(e) { + if (!contextMenu.contains(e.target)) { + contextMenu.remove(); + document.removeEventListener('click', removeContextMenu); + } + }); + } +} From 5af66c3a036982bfe30ffc9966fda190ebd76227 Mon Sep 17 00:00:00 2001 From: Akash Manna Date: Tue, 18 Feb 2025 22:16:08 +0530 Subject: [PATCH 2/3] Refactor chart event handling by removing unnecessary whitespace and comments --- src/main/webapp/js/echarts-api.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/webapp/js/echarts-api.js b/src/main/webapp/js/echarts-api.js index 3a1a4ef..8000775 100644 --- a/src/main/webapp/js/echarts-api.js +++ b/src/main/webapp/js/echarts-api.js @@ -457,11 +457,6 @@ const echartsJenkinsApi = { handleChartClick(params.event, buildDisplayName, chartDivId); } }); - - - - - chart.getZr().on('contextmenu', params => { if (params.offsetY > 30) { // skip the legend const pointInPixel = [params.offsetX, params.offsetY]; @@ -469,9 +464,7 @@ const echartsJenkinsApi = { const buildDisplayName = chart.getModel().get('xAxis')[0].data[pointInGrid[0]]; handleContextMenu(params.event, buildDisplayName, chartDivId); } - }); - - + }); } } } From 5f1e14f1cc41cb1f72b16d6430fe8e059069f8f7 Mon Sep 17 00:00:00 2001 From: Akash Manna Date: Fri, 21 Feb 2025 19:10:41 +0530 Subject: [PATCH 3/3] Simplify chart click handling by removing 'noopener,noreferrer' from Shift+Click behavior --- src/main/webapp/js/echarts-api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/js/echarts-api.js b/src/main/webapp/js/echarts-api.js index 8000775..6a63b83 100644 --- a/src/main/webapp/js/echarts-api.js +++ b/src/main/webapp/js/echarts-api.js @@ -694,7 +694,7 @@ function handleChartClick(event, buildDisplayName, chartDivId) { if (event.ctrlKey || event.which === 2) { // Ctrl+Click or Middle-click window.open(url, '_blank'); // Open in new tab/window } else if (event.shiftKey) { // Shift+Click - window.open(url, '_blank', 'noopener,noreferrer'); // Open in a new window (more isolated) + window.open(url, '_blank'); // just open in new window } else { window.location.href = url; // Original behavior (same tab) }