Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use automatic percent formatting #2971

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions scripts/pi-hole/js/formatter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* Pi-hole: A black hole for Internet advertisements
* (c) 2024 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */

/* global moment:false */

Number.prototype.toPercent = function (fractionDigits = 0) {
const userLocale = navigator.language || 'en-US';
return new Intl.NumberFormat(userLocale, {
style: 'percent',
minimumFractionDigits: fractionDigits,
maximumFractionDigits: fractionDigits
}).format(this / 100);
};
45 changes: 20 additions & 25 deletions scripts/pi-hole/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

/* global utils:false, Chart:false */

import 'formatter.js'

// Define global variables
var timeLineChart, clientsChart;
var queryTypePieChart, forwardDestinationPieChart;
Expand Down Expand Up @@ -206,8 +208,8 @@ var customTooltips = function (context) {
} else {
// Calculate percentage X value depending on the tooltip's
// width to avoid hanging arrow out on tooltip width changes
var arrowXpercent = ((100 / tooltipWidth) * arrowX).toFixed(1);
tooltipEl.querySelector(".arrow").style.left = arrowXpercent + "%";
var arrowXpercent = ((100 / tooltipWidth) * arrowX);
tooltipEl.querySelector(".arrow").style.left = `${arrowXpercent.toPercent(1)}`;
}

tooltipEl.style.opacity = 1;
Expand Down Expand Up @@ -694,14 +696,11 @@ function updateSummaryData(runOnce) {
var textData = data[apiName];
if (!FTLoffline) {
// Only format as number if FTL is online
var formatter = new Intl.NumberFormat();

// Round to one decimal place and format locale-aware
var text = formatter.format(Math.round(data[apiName] * 10) / 10);
textData = idx === 2 && data[apiName] !== "to" ? text + "%" : text;
const roundedValue = Math.round(data[apiName] * 10) / 10;
const textData = idx === 2 && data[apiName] !== "to" ? roundedValue.toPercent(1) : roundedValue;
}

if ($todayElement.text() !== textData && $todayElement.text() !== textData + "%") {
if ($todayElement.text() !== textData && $todayElement.text() !== `${textData}`) {
$todayElement.addClass("glow");
$todayElement.text(textData);
}
Expand Down Expand Up @@ -738,32 +737,28 @@ function doughnutTooltip(tooltipLabel) {
var label = " " + tooltipLabel.label;
var itemPercentage;

// if we only show < 1% percent of all, show each item with two decimals
// If we only show < 1% percent of all, show each item with two decimals
if (percentageTotalShown < 1) {
itemPercentage = tooltipLabel.parsed.toFixed(2);
itemPercentage = tooltipLabel.parsed.toPercent(2);
} else {
// show with one decimal, but in case the item share is really small it could be rounded to 0.0
// we compensate for this
// Show with one decimal, but in case the item share is really small, it could be rounded to 0.0
// We compensate for this
itemPercentage =
tooltipLabel.parsed.toFixed(1) === "0.0" ? "< 0.1" : tooltipLabel.parsed.toFixed(1);
tooltipLabel.parsed.toPercent(1) === "0.0" ? "< 0.1" : tooltipLabel.parsed.toPercent(1);
}

// even if no doughnut slice is hidden, sometimes percentageTotalShown is slightly less then 100
// we therefore use 99.9 to decide if slices are hidden (we only show with 0.1 precision)
// Even if no doughnut slice is hidden, sometimes percentageTotalShown is slightly less than 100
// We therefore use 99.9 to decide if slices are hidden (we only show with 0.1 precision)
if (percentageTotalShown > 99.9) {
// All items shown
return label + ": " + itemPercentage + "%";
return `${label}: ${itemPercentage}`;
} else {
// set percentageTotalShown again without rounding to account
// for cases where the total shown percentage would be <0.1% of all
// Set percentageTotalShown again without rounding to account
// for cases where the total shown percentage would be < 0.1% of all
percentageTotalShown = tooltipLabel.chart._metasets[0].total;
return (
label +
":<br>&bull; " +
itemPercentage +
"% of all queries<br>&bull; " +
((tooltipLabel.parsed * 100) / percentageTotalShown).toFixed(1) +
"% of shown items"
`${label}:<br>&bull; ${itemPercentage} of all queries` +
`<br>&bull; ${(tooltipLabel.parsed * 100 / percentageTotalShown).toPercent(1)} of shown items`
);
}
}
Expand Down Expand Up @@ -917,7 +912,7 @@ $(function () {
percentage = (100 * blocked) / (permitted + blocked);
}

label += ": " + tooltipLabel.parsed.y + " (" + percentage.toFixed(1) + "%)";
label += `: ${tooltipLabel.parsed.y} (${percentage.toPercent(1)})`;
} else {
label += ": " + tooltipLabel.parsed.y;
}
Expand Down
10 changes: 7 additions & 3 deletions scripts/pi-hole/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

/* global moment:false */

import 'formatter.js'

// Credit: https://stackoverflow.com/a/4835406
function escapeHtml(text) {
var map = {
Expand Down Expand Up @@ -354,10 +356,12 @@ function addTD(content) {
return "<td>" + content + "</td> ";
}

}
function colorBar(percentage, total, cssClass) {
var title = percentage.toFixed(1) + "% of " + total;
var bar = '<div class="progress-bar ' + cssClass + '" style="width: ' + percentage + '%"></div>';
return '<div class="progress progress-sm" title="' + title + '"> ' + bar + " </div>";
const percentFormatted = percentage.toPercent(1);
const title = `${percentFormatted} of ${total}`;
const bar = `<div class="progress-bar ${cssClass}" style="width: ${percentage}%"></div>`;
return `<div class="progress progress-sm" title="${title}"> ${bar} </div>`;
}

function checkMessages() {
Expand Down
7 changes: 6 additions & 1 deletion scripts/pi-hole/php/sidebar.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@
echo 'text-green-light';
}
if ($memory_usage > 0.0) {
echo '"></i> Memory usage:&nbsp;&nbsp;'.sprintf('%.1f', 100.0 * $memory_usage).'&thinsp;%</span>';
$locale = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : 'en_US';
$formatter = new NumberFormatter($locale, NumberFormatter::PERCENT);
$formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, 1);
$formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, 1);
$formattedPercent = $formatter->format($memory_usage);
echo '"></i> Memory usage:&nbsp;&nbsp;' . $formattedPercent . '</span>';
} else {
echo '"></i> Memory usage:&nbsp;&nbsp; N/A</span>';
}
Expand Down
Loading