diff --git a/scripts/js/charts.js b/scripts/js/charts.js index ecb99b61..707c6f79 100644 --- a/scripts/js/charts.js +++ b/scripts/js/charts.js @@ -5,7 +5,7 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -/* global upstreams:false */ +/* global upstreamIPs:false */ "use strict"; @@ -63,6 +63,23 @@ globalThis.htmlLegendPlugin = { for (const item of items) { const li = document.createElement("li"); + // Select the corresponding "slice" of the chart when the mouse is over a legend item + li.addEventListener("mouseover", () => { + chart.setActiveElements([ + { + datasetIndex: 0, + index: item.index, + }, + ]); + chart.update(); + }); + + // Deselect all "slices" + li.addEventListener("mouseout", () => { + chart.setActiveElements([]); + chart.update(); + }); + // Color checkbox (toggle visibility) const boxSpan = document.createElement("span"); boxSpan.title = "Toggle visibility"; @@ -96,9 +113,19 @@ globalThis.htmlLegendPlugin = { if (isQueryTypeChart) { link.href = `queries?type=${item.text}`; - } else if (isForwardDestinationChart) { + } else { // Encode the forward destination as it may contain an "#" character - link.href = `queries?upstream=${encodeURIComponent(upstreams[item.text])}`; + link.href = `queries?upstream=${encodeURIComponent(upstreamIPs[item.index])}`; + + // If server name and IP are different: + if (item.text !== upstreamIPs[item.index]) { + // replace the title tooltip to include the upstream IP to the text ... + link.title = `List ${item.text} (${upstreamIPs[item.index]}) queries`; + + // ... and include the server name (without port) to the querystring, to match + // the text used on the SELECT element (sent by suggestions API endpoint) + link.href += ` (${item.text.split("#")[0]})`; + } } } else { // no clickable links in other charts diff --git a/scripts/js/index.js b/scripts/js/index.js index 9bf49555..3eb1e6ce 100644 --- a/scripts/js/index.js +++ b/scripts/js/index.js @@ -226,7 +226,7 @@ function updateClientsOverTime() { }); } -const upstreams = {}; +const upstreamIPs = []; function updateForwardDestinationsPie() { $.getJSON(document.body.dataset.apiurl + "/stats/upstreams", data => { const v = []; @@ -248,11 +248,8 @@ function updateForwardDestinationsPie() { label += "#" + item.port; } - // Store upstreams for generating links to the Query Log - upstreams[label] = item.ip; - if (item.port > 0) { - upstreams[label] += "#" + item.port; - } + // Store upstreams IPs for generating links to the Query Log + upstreamIPs.push(item.port > 0 ? item.ip + "#" + item.port : item.ip); const percent = (100 * item.count) / sum; values.push([label, percent, THEME_COLORS[i++ % THEME_COLORS.length]]); @@ -893,6 +890,8 @@ $(() => { elements: { arc: { borderColor: $(".box").css("background-color"), + hoverBorderColor: $(".box").css("background-color"), + hoverOffset: 10, }, }, plugins: { @@ -917,6 +916,9 @@ $(() => { animation: { duration: 750, }, + layout: { + padding: 10, + }, }, }); @@ -939,6 +941,8 @@ $(() => { elements: { arc: { borderColor: $(".box").css("background-color"), + hoverBorderColor: $(".box").css("background-color"), + hoverOffset: 10, }, }, plugins: { @@ -963,6 +967,9 @@ $(() => { animation: { duration: 750, }, + layout: { + padding: 10, + }, }, });