From a39010582cf76b7b946472932fdba95d0eed2c75 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 27 Dec 2020 20:49:00 +0100 Subject: [PATCH 1/8] Add additional information children to adlist table Signed-off-by: DL6ER --- groups-adlists.php | 2 + scripts/pi-hole/js/groups-adlists.js | 107 +++++++++++++++++++++------ style/pi-hole.css | 24 ++++++ 3 files changed, 112 insertions(+), 21 deletions(-) diff --git a/groups-adlists.php b/groups-adlists.php index 94c26a7ea..bf2a3b419 100644 --- a/groups-adlists.php +++ b/groups-adlists.php @@ -41,6 +41,7 @@
  1. Please run pihole -g or update your gravity list online after modifying your adlists.
  2. Multiple adlists can be added by separating each unique URL with a space
  3. +
  4. Click on to get additional information about your lists. The color of the icon corresponds to the health of the list.
@@ -61,6 +62,7 @@ ID + Address Status Comment diff --git a/scripts/pi-hole/js/groups-adlists.js b/scripts/pi-hole/js/groups-adlists.js index 1f2068747..3d958833b 100644 --- a/scripts/pi-hole/js/groups-adlists.js +++ b/scripts/pi-hole/js/groups-adlists.js @@ -30,6 +30,52 @@ $(function () { getGroups(); }); +function format(data) { + // Generate human-friendly status string + var statusText = "Unknown"; + if (data.status !== null) { + switch (parseInt(data.status, 10)) { + case 1: + statusText = "List download was successful (OK)"; + break; + case 2: + statusText = "List unchanged upstream, Pi-hole used a local copy (OK)"; + break; + case 3: + statusText = "List unavailable, Pi-hole used a local copy"; + break; + case 4: + statusText = + "List unavailable, there is no local copy of this list available on your Pi-hole"; + break; + + default: + statusText = "Unknown (" + parseInt(data.status, 10) + ")"; + break; + } + } + + // Compile extra info for displaying + return ( + '' + + "
Health status of this list:" + + statusText + + "
This list was added to Pi-hole on  " + + utils.datetime(data.date_added, false) + + "
Database entry was last modified on  " + + utils.datetime(data.date_modified, false) + + "
The list contents were last updated on  " + + (data.date_updated !== null ? utils.datetime(data.date_updated, false) : "N/A") + + "
Number of valid domains on this list:  " + + (data.number !== null ? data.number : "N/A") + + "
Number of invalid domains on this list:  " + + (data.invalid_domains !== null ? data.invalid_domains : "N/A") + + "
Database ID of this list:" + + data.id + + "
" + ); +} + function initTable() { table = $("#adlistsTable").DataTable({ ajax: { @@ -40,6 +86,7 @@ function initTable() { order: [[0, "asc"]], columns: [ { data: "id", visible: false }, + { data: null, orderable: false, searchable: false, class: "details-control" }, { data: "address" }, { data: "enabled", searchable: false }, { data: "comment" }, @@ -53,27 +100,29 @@ function initTable() { }, rowCallback: function (row, data) { $(row).attr("data-id", data.id); - var tooltip = - "Added: " + - utils.datetime(data.date_added, false) + - "\nLast modified (database entry): " + - utils.datetime(data.date_modified, false) + - "\nLast updated (list content): " + - (data.date_updated !== null ? utils.datetime(data.date_updated, false) : "N/A") + - "\nDatabase ID: " + - data.id; - $("td:eq(0)", row).html( - '"); + + $("td:eq(1)", row).html( + '' + + '" class="breakall" href="' + + data.address + + '">' + data.address + - "" + "" ); - var disabled = data.enabled === 0; - $("td:eq(1)", row).html( + $("td:eq(2)", row).html( '" ); var statusEl = $("#status_" + data.id, row); @@ -86,13 +135,13 @@ function initTable() { }); statusEl.on("change", editAdlist); - $("td:eq(2)", row).html(''); + $("td:eq(3)", row).html(''); var commentEl = $("#comment_" + data.id, row); commentEl.val(utils.unescapeHtml(data.comment)); commentEl.on("change", editAdlist); - $("td:eq(3)", row).empty(); - $("td:eq(3)", row).append( + $("td:eq(4)", row).empty(); + $("td:eq(4)", row).append( '' ); var selectEl = $("#multiselect_" + data.id, row); @@ -162,7 +211,7 @@ function initTable() { '">' + '' + ""; - $("td:eq(4)", row).html(button); + $("td:eq(5)", row).html(button); }, dom: "<'row'<'col-sm-4'l><'col-sm-8'f>>" + @@ -204,6 +253,22 @@ function initTable() { $("#resetButton").addClass("hidden"); }); + // Add event listener for opening and closing details + $("#adlistsTable tbody").on("click", "td.details-control", function () { + var tr = $(this).closest("tr"); + var row = table.row(tr); + + if (row.child.isShown()) { + // This row is already open - close it + row.child.hide(); + tr.removeClass("shown"); + } else { + // Open this row + row.child(format(row.data())).show(); + tr.addClass("shown"); + } + }); + // Disable autocorrect in the search box var input = document.querySelector("input[type=search]"); if (input !== null) { diff --git a/style/pi-hole.css b/style/pi-hole.css index 635006311..d60da7fb1 100644 --- a/style/pi-hole.css +++ b/style/pi-hole.css @@ -330,3 +330,27 @@ .small-box { border-radius: 10px; } + +.list-status-0 { + color: #7D7D7D; +} + +.list-status-1 { + color: #74c700; +} + +.list-status-2 { + color: #98ca52; +} + +.list-status-3 { + color: #ff8c00; +} + +.list-status-4 { + color: #cc0000; +} + +td.details-control { + cursor: pointer; +} From 5533b4fc9e4346ad7e8d2f52afa67f405b3acb12 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 28 Dec 2020 10:23:31 +0100 Subject: [PATCH 2/8] Improve formatting and make status texts more human-friendly Signed-off-by: DL6ER --- scripts/pi-hole/js/groups-adlists.js | 51 +++++++++++++++++++--------- scripts/pi-hole/js/utils.js | 7 +++- style/pi-hole.css | 4 +++ 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/scripts/pi-hole/js/groups-adlists.js b/scripts/pi-hole/js/groups-adlists.js index 3d958833b..d73eb4fcf 100644 --- a/scripts/pi-hole/js/groups-adlists.js +++ b/scripts/pi-hole/js/groups-adlists.js @@ -33,44 +33,63 @@ $(function () { function format(data) { // Generate human-friendly status string var statusText = "Unknown"; + var PrintNumbers = true; if (data.status !== null) { switch (parseInt(data.status, 10)) { + case 0: + if(data.enabled === 0) { + statusText = 'List is disabled and not checked'; + } else { + statusText = 'List was not downloaded so far'; + } + PrintNumbers = false; + break; case 1: - statusText = "List download was successful (OK)"; + statusText = 'List download was successful (OK)'; break; case 2: - statusText = "List unchanged upstream, Pi-hole used a local copy (OK)"; + statusText = 'List unchanged upstream, Pi-hole used a local copy (OK)'; break; case 3: - statusText = "List unavailable, Pi-hole used a local copy"; + statusText = 'List unavailable, Pi-hole used a local copy (check list)'; break; case 4: statusText = - "List unavailable, there is no local copy of this list available on your Pi-hole"; + 'List unavailable, there is no local copy of this list available on your Pi-hole (replace list)'; + PrintNumbers = false; break; default: - statusText = "Unknown (" + parseInt(data.status, 10) + ")"; + statusText = 'Unknown (' + parseInt(data.status, 10) + ')'; break; } } // Compile extra info for displaying return ( - '' + - "" + + "" + "
Health status of this list:" + + '' + + '
Health status of this list:' + statusText + - "
This list was added to Pi-hole on  " + + '
This list was added to Pi-hole  ' + + utils.datetimeRelative(data.date_added) + + " (" + utils.datetime(data.date_added, false) + - "
Database entry was last modified on  " + + ')
Database entry was last modified  ' + + utils.datetimeRelative(data.date_modified) + + " (" + utils.datetime(data.date_modified, false) + - "
The list contents were last updated on  " + - (data.date_updated !== null ? utils.datetime(data.date_updated, false) : "N/A") + - "
Number of valid domains on this list:  " + - (data.number !== null ? data.number : "N/A") + - "
Number of invalid domains on this list:  " + - (data.invalid_domains !== null ? data.invalid_domains : "N/A") + - "
Database ID of this list:" + + ')
The list contents were last updated  ' + + (data.date_updated !== null + ? utils.datetimeRelative(data.date_updated) + + " (" + + utils.datetime(data.date_updated) + + ")" + : "N/A") + + '
Number of valid domains on this list:  ' + + (data.number !== null && PrintNumbers === true ? data.number : "N/A") + + '
Number of invalid domains on this list:  ' + + (data.invalid_domains !== null && PrintNumbers === true ? data.invalid_domains : "N/A") + + '
Database ID of this list:' + data.id + "
" ); diff --git a/scripts/pi-hole/js/utils.js b/scripts/pi-hole/js/utils.js index cdc4beade..73e382585 100644 --- a/scripts/pi-hole/js/utils.js +++ b/scripts/pi-hole/js/utils.js @@ -124,7 +124,11 @@ function showAlert(type, icon, title, message) { function datetime(date, html) { var format = html === false ? "Y-MM-DD HH:mm:ss z" : "Y-MM-DD []HH:mm:ss z"; - return moment.unix(Math.floor(date)).format(format); + return moment.unix(Math.floor(date)).format(format).trim(); +} + +function datetimeRelative(date) { + return moment.unix(Math.floor(date)).fromNow(); } function disableAll() { @@ -331,6 +335,7 @@ window.utils = (function () { padNumber: padNumber, showAlert: showAlert, datetime: datetime, + datetimeRelative: datetimeRelative, disableAll: disableAll, enableAll: enableAll, validateIPv4CIDR: validateIPv4CIDR, diff --git a/style/pi-hole.css b/style/pi-hole.css index d60da7fb1..df4b95d7e 100644 --- a/style/pi-hole.css +++ b/style/pi-hole.css @@ -354,3 +354,7 @@ td.details-control { cursor: pointer; } + +.dataTables-child td { + padding: 2px 5px; +} From 9b821dd481e5a1b6e481dac23149e8ae3eb915c0 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 28 Dec 2020 10:36:08 +0100 Subject: [PATCH 3/8] Use distinct icons for getting more information on the first look Signed-off-by: DL6ER --- groups-adlists.php | 2 +- scripts/pi-hole/js/groups-adlists.js | 54 +++++++++++++++++++--------- style/pi-hole.css | 2 +- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/groups-adlists.php b/groups-adlists.php index bf2a3b419..1fb041792 100644 --- a/groups-adlists.php +++ b/groups-adlists.php @@ -41,7 +41,7 @@
  1. Please run pihole -g or update your gravity list online after modifying your adlists.
  2. Multiple adlists can be added by separating each unique URL with a space
  3. -
  4. Click on to get additional information about your lists. The color of the icon corresponds to the health of the list.
  5. +
  6. Click on the icon in the first column to get additional information about your lists. The icons correspond to the health of the list.
diff --git a/scripts/pi-hole/js/groups-adlists.js b/scripts/pi-hole/js/groups-adlists.js index d73eb4fcf..39000dcdb 100644 --- a/scripts/pi-hole/js/groups-adlists.js +++ b/scripts/pi-hole/js/groups-adlists.js @@ -33,41 +33,43 @@ $(function () { function format(data) { // Generate human-friendly status string var statusText = "Unknown"; - var PrintNumbers = true; + var numbers = true; if (data.status !== null) { switch (parseInt(data.status, 10)) { case 0: - if(data.enabled === 0) { - statusText = 'List is disabled and not checked'; - } else { - statusText = 'List was not downloaded so far'; - } - PrintNumbers = false; + statusText = + data.enabled === 0 + ? "List is disabled and not checked" + : "List was not downloaded so far"; + numbers = false; break; case 1: statusText = 'List download was successful (OK)'; break; case 2: - statusText = 'List unchanged upstream, Pi-hole used a local copy (OK)'; + statusText = + 'List unchanged upstream, Pi-hole used a local copy (OK)'; break; case 3: - statusText = 'List unavailable, Pi-hole used a local copy (check list)'; + statusText = + 'List unavailable, Pi-hole used a local copy (check list)'; break; case 4: statusText = 'List unavailable, there is no local copy of this list available on your Pi-hole (replace list)'; - PrintNumbers = false; + numbers = false; break; default: - statusText = 'Unknown (' + parseInt(data.status, 10) + ')'; + statusText = + 'Unknown (' + parseInt(data.status, 10) + ")"; break; } } // Compile extra info for displaying return ( - '' + + "
" + '
Health status of this list:' + statusText + '
This list was added to Pi-hole  ' + @@ -86,9 +88,9 @@ function format(data) { ")" : "N/A") + '
Number of valid domains on this list:  ' + - (data.number !== null && PrintNumbers === true ? data.number : "N/A") + + (data.number !== null && numbers === true ? data.number : "N/A") + '
Number of invalid domains on this list:  ' + - (data.invalid_domains !== null && PrintNumbers === true ? data.invalid_domains : "N/A") + + (data.invalid_domains !== null && numbers === true ? data.invalid_domains : "N/A") + '
Database ID of this list:' + data.id + "
" @@ -121,7 +123,8 @@ function initTable() { $(row).attr("data-id", data.id); var disabled = data.enabled === 0; - var statusCode = 0; + var statusCode = 0, + statusIcon; // If there is no status or the list is disabled, we keep // status 0 (== unknown) if (data.status !== null && disabled !== true) { @@ -129,7 +132,26 @@ function initTable() { } $("td:eq(0)", row).addClass("list-status-" + statusCode); - $("td:eq(0)", row).html(""); + switch (statusCode) { + default: + case 0: + statusIcon = "fa-question-circle"; + break; + case 1: + statusIcon = "fa-check"; + break; + case 2: + statusIcon = "fa-history"; + break; + case 3: + statusIcon = "fa-exclamation-circle"; + break; + case 4: + statusIcon = "fa-times"; + break; + } + + $("td:eq(0)", row).html(""); $("td:eq(1)", row).html( '" + @@ -89,7 +94,10 @@ function format(data) { : "N/A") + '
Number of valid domains on this list:  ' + (data.number !== null && numbers === true ? data.number : "N/A") + - '
Number of invalid domains on this list:  ' + + '
Number of invalid domains on this list:  " + (data.invalid_domains !== null && numbers === true ? data.invalid_domains : "N/A") + '
Database ID of this list:' + data.id + @@ -131,7 +139,6 @@ function initTable() { statusCode = parseInt(data.status, 10); } - $("td:eq(0)", row).addClass("list-status-" + statusCode); switch (statusCode) { default: case 0: @@ -151,7 +158,14 @@ function initTable() { break; } - $("td:eq(0)", row).html(""); + // Always overwrite icon with red exclamation-triangle when there are invalid lines in a list + var extra = ""; + if (data.invalid_domains !== null && data.invalid_domains > 0) { + extra = ""; + } + + $("td:eq(0)", row).addClass("list-status-" + statusCode); + $("td:eq(0)", row).html("" + extra); $("td:eq(1)", row).html( '
Number of valid domains on this list:  ' + - (data.number !== null && numbers === true ? data.number : "N/A") + + (data.number !== null && numbers === true ? parseInt(data.number, 10) : "N/A") + '
Number of invalid domains on this list:  " + - (data.invalid_domains !== null && numbers === true ? data.invalid_domains : "N/A") + + (data.invalid_domains !== null && numbers === true + ? parseInt(data.invalid_domains, 10) + : "N/A") + '
Database ID of this list:' + data.id + "
" @@ -115,7 +117,7 @@ function initTable() { order: [[0, "asc"]], columns: [ { data: "id", visible: false }, - { data: null, orderable: false, searchable: false, class: "details-control" }, + { data: "status", searchable: false, class: "details-control" }, { data: "address" }, { data: "enabled", searchable: false }, { data: "comment" }, @@ -172,7 +174,7 @@ function initTable() { data.id + '" class="breakall" href="' + data.address + - '">' + + '" target="_blank" rel="noopener noreferrer">' + data.address + "" ); From ba3acbbade57bc633564a29d25a86b23d8344685 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 3 Jan 2021 22:20:22 +0100 Subject: [PATCH 6/8] Do not create links for file:// adlists Signed-off-by: DL6ER --- scripts/pi-hole/js/groups-adlists.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/scripts/pi-hole/js/groups-adlists.js b/scripts/pi-hole/js/groups-adlists.js index 3b036e68f..98b0eadcb 100644 --- a/scripts/pi-hole/js/groups-adlists.js +++ b/scripts/pi-hole/js/groups-adlists.js @@ -169,15 +169,23 @@ function initTable() { $("td:eq(0)", row).addClass("list-status-" + statusCode); $("td:eq(0)", row).html("" + extra); - $("td:eq(1)", row).html( - '' + - data.address + - "" - ); + if (data.address.startsWith("file://")) { + // Local files cannot be downloaded from a distant client so don't show + // a link to such a list here + $("td:eq(1)", row).html( + '' + data.address + "" + ); + } else { + $("td:eq(1)", row).html( + '' + + data.address + + "" + ); + } $("td:eq(2)", row).html( '" From bc108ea834be1f61203c261b395b894386c8af16 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Thu, 7 Jan 2021 21:35:05 +0100 Subject: [PATCH 7/8] Add status icon tooltip Signed-off-by: DL6ER --- scripts/pi-hole/js/groups-adlists.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/pi-hole/js/groups-adlists.js b/scripts/pi-hole/js/groups-adlists.js index 98b0eadcb..4b298167e 100644 --- a/scripts/pi-hole/js/groups-adlists.js +++ b/scripts/pi-hole/js/groups-adlists.js @@ -142,10 +142,6 @@ function initTable() { } switch (statusCode) { - default: - case 0: - statusIcon = "fa-question-circle"; - break; case 1: statusIcon = "fa-check"; break; @@ -158,16 +154,22 @@ function initTable() { case 4: statusIcon = "fa-times"; break; + case 0: + default: + statusIcon = "fa-question-circle"; + break; } - // Always overwrite icon with red exclamation-triangle when there are invalid lines in a list + // Append red exclamation-triangle when there are invalid lines on the list var extra = ""; if (data.invalid_domains !== null && data.invalid_domains > 0) { extra = ""; } $("td:eq(0)", row).addClass("list-status-" + statusCode); - $("td:eq(0)", row).html("" + extra); + $("td:eq(0)", row).html( + "" + extra + ); if (data.address.startsWith("file://")) { // Local files cannot be downloaded from a distant client so don't show From 78672fdbecb095df39e6064485c8cea9ddbe8502 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 17 Mar 2021 16:55:27 +0100 Subject: [PATCH 8/8] Avoid 1970 date if list was never updated. --- scripts/pi-hole/js/groups-adlists.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pi-hole/js/groups-adlists.js b/scripts/pi-hole/js/groups-adlists.js index 4b298167e..6a5baf8af 100644 --- a/scripts/pi-hole/js/groups-adlists.js +++ b/scripts/pi-hole/js/groups-adlists.js @@ -86,7 +86,7 @@ function format(data) { " (" + utils.datetime(data.date_modified, false) + ')The list contents were last updated  ' + - (data.date_updated !== null + (data.date_updated > 0 ? utils.datetimeRelative(data.date_updated) + " (" + utils.datetime(data.date_updated) +