From 1db322b96367ab5f5d6cc3dccbf591e5e08879f1 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 10 Feb 2018 14:10:55 +0100 Subject: [PATCH 01/13] Show most recent 100 queries instead of queries within most recent 10 minutes Signed-off-by: DL6ER --- api_FTL.php | 4 ++++ queries.php | 2 +- scripts/pi-hole/js/queries.js | 13 +++++++------ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/api_FTL.php b/api_FTL.php index d4e1c085..61efa5b9 100644 --- a/api_FTL.php +++ b/api_FTL.php @@ -230,6 +230,10 @@ if (isset($_GET['getAllQueries']) && $auth) // Get specific client only sendRequestFTL("getallqueries-client ".$_GET['client']); } + else if(is_numeric($_GET['getAllQueries'])) + { + sendRequestFTL("getallqueries (".$_GET['getAllQueries'].")"); + } else { // Get all queries diff --git a/queries.php b/queries.php index 89ed91d7..792ee2a3 100644 --- a/queries.php +++ b/queries.php @@ -59,7 +59,7 @@ else if(isset($_GET["from"]) && isset($_GET["until"])) } else { - $showing .= " within recent 10 minutes, show all"; + $showing .= ", most recent 100, show all"; } if(isset($setupVars["API_PRIVACY_MODE"])) diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js index 722f8543..623ce881 100644 --- a/scripts/pi-hole/js/queries.js +++ b/scripts/pi-hole/js/queries.js @@ -122,26 +122,27 @@ $(document).ready(function() { location.search.substr(1).split("&").forEach(function(item) {GETDict[item.split("=")[0]] = item.split("=")[1];}); var APIstring = "api.php?getAllQueries"; + var options = ""; if("from" in GETDict && "until" in GETDict) { - APIstring += "&from="+GETDict["from"]; + options += "&from="+GETDict["from"]; APIstring += "&until="+GETDict["until"]; } else if("client" in GETDict) { - APIstring += "&client="+GETDict["client"]; + options += "&client="+GETDict["client"]; } else if("domain" in GETDict) { - APIstring += "&domain="+GETDict["domain"]; + options += "&domain="+GETDict["domain"]; } + // If we don't ask filtering and also not for all queries, just request the most recent 100 queries else if(!("all" in GETDict)) { - var timestamp = Math.floor(Date.now() / 1000); - APIstring += "&from="+(timestamp - 600); - APIstring += "&until="+(timestamp + 100); + APIstring += "=100"; } + APIstring += options; tableApi = $("#all-queries").DataTable( { "rowCallback": function( row, data, index ){ From c62daea621eb9b7dd174f671ce951316736d53bb Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 10 Feb 2018 16:32:29 +0100 Subject: [PATCH 02/13] Remove unnecessary options variable Signed-off-by: DL6ER --- scripts/pi-hole/js/queries.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js index 623ce881..58ec73b9 100644 --- a/scripts/pi-hole/js/queries.js +++ b/scripts/pi-hole/js/queries.js @@ -82,7 +82,7 @@ function add(domain,list) { } }); }); - + // Reset Modal after it has faded out alertModal.one("hidden.bs.modal", function() { alProcessing.show(); @@ -122,27 +122,25 @@ $(document).ready(function() { location.search.substr(1).split("&").forEach(function(item) {GETDict[item.split("=")[0]] = item.split("=")[1];}); var APIstring = "api.php?getAllQueries"; - var options = ""; if("from" in GETDict && "until" in GETDict) { - options += "&from="+GETDict["from"]; + APIstring += "&from="+GETDict["from"]; APIstring += "&until="+GETDict["until"]; } else if("client" in GETDict) { - options += "&client="+GETDict["client"]; + APIstring += "&client="+GETDict["client"]; } else if("domain" in GETDict) { - options += "&domain="+GETDict["domain"]; + APIstring += "&domain="+GETDict["domain"]; } // If we don't ask filtering and also not for all queries, just request the most recent 100 queries else if(!("all" in GETDict)) { APIstring += "=100"; } - APIstring += options; tableApi = $("#all-queries").DataTable( { "rowCallback": function( row, data, index ){ From f132122e5753e476e90e3c3122a2477d8b34cf8c Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 5 Mar 2018 09:18:37 +0100 Subject: [PATCH 03/13] Use better client host name caching for DB queries Signed-off-by: DL6ER --- api_db.php | 59 ++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/api_db.php b/api_db.php index 3e3fdf03..b4bd8cb3 100644 --- a/api_db.php +++ b/api_db.php @@ -16,6 +16,30 @@ check_cors(); ini_set("max_execution_time","600"); $data = array(); +$clients = []; +function resolveOnlyHostname($clientip) +{ + if(array_key_exists($clientip, $clients)) + { + // Entry already exists + $clientname = $clients[$clientip]; + return $clientname; + } + + if(filter_var($clientip, FILTER_VALIDATE_IP)) + { + // Get host name of client and convert to lower case + $clientname = strtolower(gethostbyaddr($clientip)); + } + else + { + // This is already a host name + $clientname = strtolower($clientip); + } + // Buffer result + $clients[$clientname] = $clientip; + return $clientname; +} // Get posible non-standard location of FTL's database $FTLsettings = parse_ini_file("/etc/pihole/pihole-FTL.conf"); @@ -78,27 +102,7 @@ if (isset($_GET['getAllQueries']) && $auth) if(!is_bool($results)) while ($row = $results->fetchArray()) { - $c = $row[3]; - if(array_key_exists($row[3], $clients)) - { - // Entry already exists - $c = $clients[$row[3]]; - } - else - { - if(filter_var($row[3], FILTER_VALIDATE_IP)) - { - // Get host name of client and convert to lower case - $c = strtolower(gethostbyaddr($row[3])); - } - else - { - // This is already a host name - $c = strtolower($row[3]); - } - // Buffer result - $clients[$row[3]] = $c; - } + $c = resolveOnlyHostname($row[3]); $allQueries[] = [$row[0],$row[1] == 1 ? "IPv4" : "IPv6",$row[2],$c,$row[4]]; } } @@ -132,16 +136,9 @@ if (isset($_GET['topClients']) && $auth) if(!is_bool($results)) while ($row = $results->fetchArray()) { - if(filter_var($row[0], FILTER_VALIDATE_IP)) - { - // Get host name of client and convert to lower case - $c = strtolower(gethostbyaddr($row[0])); - } - else - { - // This is already a host name - $c = strtolower($row[0]); - } + + $c = resolveOnlyHostname($row[0]); + if(array_key_exists($c, $clients)) { // Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database) From 746ac1ea3f0fbf470da3f1728f6852915a41a44e Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 5 Mar 2018 15:45:22 +0100 Subject: [PATCH 04/13] Prevent confusion between arrays Signed-off-by: DL6ER --- api_db.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api_db.php b/api_db.php index b4bd8cb3..7c126297 100644 --- a/api_db.php +++ b/api_db.php @@ -131,7 +131,7 @@ if (isset($_GET['topClients']) && $auth) $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER); $results = $stmt->execute(); - $clients = array(); + $clientnums = array(); if(!is_bool($results)) while ($row = $results->fetchArray()) @@ -139,25 +139,25 @@ if (isset($_GET['topClients']) && $auth) $c = resolveOnlyHostname($row[0]); - if(array_key_exists($c, $clients)) + if(array_key_exists($c, $clientnums)) { // Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database) - $clients[$c] += intval($row[1]); + $clientnums[$c] += intval($row[1]); } else { // Entry does not yet exist - $clients[$c] = intval($row[1]); + $clientnums[$c] = intval($row[1]); } } // Sort by number of hits - arsort($clients); + arsort($clientnums); // Extract only the first ten entries - $clients = array_slice($clients, 0, 10); + $clientnums = array_slice($clientnums, 0, 10); - $result = array('top_sources' => $clients); + $result = array('top_sources' => $clientnums); $data = array_merge($data, $result); } From 57f0642c0f8afb4a6d450eb4e597b94b5f12e788 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 5 Mar 2018 15:46:23 +0100 Subject: [PATCH 05/13] Remove unused array Signed-off-by: DL6ER --- api_db.php | 1 - 1 file changed, 1 deletion(-) diff --git a/api_db.php b/api_db.php index 7c126297..0c3686f2 100644 --- a/api_db.php +++ b/api_db.php @@ -98,7 +98,6 @@ if (isset($_GET['getAllQueries']) && $auth) $stmt->bindValue(":from", intval($from), SQLITE3_INTEGER); $stmt->bindValue(":until", intval($until), SQLITE3_INTEGER); $results = $stmt->execute(); - $clients = array(); if(!is_bool($results)) while ($row = $results->fetchArray()) { From 322b87befe78e9f8b5ee8515dadea811ebd147c9 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 5 Mar 2018 16:48:05 +0100 Subject: [PATCH 06/13] Imporve resolveHostname() subroutine Signed-off-by: DL6ER --- api_db.php | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/api_db.php b/api_db.php index 0c3686f2..aee13616 100644 --- a/api_db.php +++ b/api_db.php @@ -16,28 +16,35 @@ check_cors(); ini_set("max_execution_time","600"); $data = array(); -$clients = []; -function resolveOnlyHostname($clientip) +$clients = array(); +function resolveHostname($clientip, $printIP) { + global $clients; + $ipaddr = strtolower($clientip); if(array_key_exists($clientip, $clients)) { // Entry already exists - $clientname = $clients[$clientip]; + $clientname = $clients[$ipaddr]; + if($printIP) + return $clientname."|".$clientip; return $clientname; } - if(filter_var($clientip, FILTER_VALIDATE_IP)) + else if(filter_var($clientip, FILTER_VALIDATE_IP)) { // Get host name of client and convert to lower case - $clientname = strtolower(gethostbyaddr($clientip)); + $clientname = strtolower(gethostbyaddr($ipaddr)); } else { // This is already a host name - $clientname = strtolower($clientip); + $clientname = $ipaddr; } // Buffer result - $clients[$clientname] = $clientip; + $clients[$ipaddr] = $clientname; + + if($printIP) + return $clientname."|".$clientip; return $clientname; } @@ -101,7 +108,7 @@ if (isset($_GET['getAllQueries']) && $auth) if(!is_bool($results)) while ($row = $results->fetchArray()) { - $c = resolveOnlyHostname($row[3]); + $c = resolveHostname($row[3],false); $allQueries[] = [$row[0],$row[1] == 1 ? "IPv4" : "IPv6",$row[2],$c,$row[4]]; } } @@ -136,7 +143,7 @@ if (isset($_GET['topClients']) && $auth) while ($row = $results->fetchArray()) { - $c = resolveOnlyHostname($row[0]); + $c = resolveHostname($row[0],false); if(array_key_exists($c, $clientnums)) { From c278428b288d985474c6f4c4b61f9f2593db1e6d Mon Sep 17 00:00:00 2001 From: DL6ER Date: Thu, 8 Mar 2018 06:56:28 +0100 Subject: [PATCH 07/13] Change header texts, move "show all" hyperlink out of the parentheses Signed-off-by: DL6ER --- queries.php | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/queries.php b/queries.php index 792ee2a3..be147ec1 100644 --- a/queries.php +++ b/queries.php @@ -19,47 +19,49 @@ if(isset($setupVars["API_QUERY_LOG_SHOW"])) { if($setupVars["API_QUERY_LOG_SHOW"] === "all") { - $showing = "showing all queries"; + $showing = "showing"; } elseif($setupVars["API_QUERY_LOG_SHOW"] === "permittedonly") { - $showing = "showing permitted queries only"; + $showing = "showing permitted"; } elseif($setupVars["API_QUERY_LOG_SHOW"] === "blockedonly") { - $showing = "showing blocked queries only"; + $showing = "showing blocked"; } elseif($setupVars["API_QUERY_LOG_SHOW"] === "nothing") { - $showing = "showing no queries at all"; + $showing = "showing no queries (due to setting)"; } } else { // If filter variable is not set, we // automatically show all queries - $showing = "showing all queries"; + $showing = "showing queries"; } +$showall = false; if(isset($_GET["all"])) { - $showing .= " within the Pi-hole log"; + $showing .= " all queries within the Pi-hole log"; } else if(isset($_GET["client"])) { - $showing .= " for client ".htmlentities($_GET["client"]); + $showing .= " queries for client ".htmlentities($_GET["client"]); } else if(isset($_GET["domain"])) { - $showing .= " for domain ".htmlentities($_GET["domain"]); + $showing .= " queries for domain ".htmlentities($_GET["domain"]); } -else if(isset($_GET["from"]) && isset($_GET["until"])) +else if(isset($_GET["from"]) || isset($_GET["until"])) { - $showing .= " within limited time interval"; + $showing .= " queries within specified time interval"; } else { - $showing .= ", most recent 100, show all"; + $showing .= " up to 100 queries"; + $showall = true; } if(isset($setupVars["API_PRIVACY_MODE"])) @@ -74,6 +76,8 @@ if(isset($setupVars["API_PRIVACY_MODE"])) if(strlen($showing) > 0) { $showing = "(".$showing.")"; + if($showall) + $showing .= ", show all"; } ?> From f1c516895f15f2046e6127fd3e0102da17e30e5f Mon Sep 17 00:00:00 2001 From: Jacob Salmela Date: Thu, 22 Mar 2018 23:56:36 -0500 Subject: [PATCH 08/13] align this readme with the core one. formatting and layout is now the same. also added a ton of updated screenshots. finally, updated donation and affiliate links Signed-off-by: Jacob Salmela --- README.md | 194 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 174 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index e3f3b257..505edf19 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,186 @@ -Pi-hole Admin Dashboard -============ -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/938b4d9e61b7487da77cf63ba05c683d)](https://www.codacy.com/app/Pi-hole/AdminLTE?utm_source=github.com&utm_medium=referral&utm_content=pi-hole/AdminLTE&utm_campaign=badger) -[![Join the chat at https://gitter.im/pi-hole/AdminLTE](https://badges.gitter.im/pi-hole/AdminLTE.svg)](https://gitter.im/pi-hole/AdminLTE?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +

+Pi-hole

+Network-wide ad blocking via your own Linux hardware
+
+Pi-hole Web interface
+

-[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif "AdminLTE Presentation")](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY "Donate") +Pi-hole[®](https://pi-hole.net/trademark-rules-and-brand-guidelines/)'s Web interface (based off of [AdminLTE](https://almsaeedstudio.com)) provides a central location to manage your Pi-hole and review the statistics generated by FTLDNS[™](https://pi-hole.net/trademark-rules-and-brand-guidelines/). -Using **[AdminLTE](https://almsaeedstudio.com)**, this project will create a Web interface for the ad-blocking Pi-hole: **a black hole for Internet advertisements**. +- **Easy-to-interpret**: simple graphs and beautiful colors make Pi-hole's stats easy to understand +- **Responsive**: looks great on desktop, tablets, and mobile devices +- **Useful**: control and configure your Pi-hole with our settings +- **Insightful**: use the query log, audit log, or long-term stats to gain insight into your networks activity -From this interface, you will be able to see stats on how well your Pi-hole is performing. You will also be able to update the lists used to block ads. +--- + +
-![Pi-hole Web interface](http://i.imgur.com/EgGZXbT.png) +# Installation + +The Web interface is enabled by default when you install Pi-hole. + +## Post-installation: access the Web interface and gain insight into your network's activity +There are several ways to [access the dashboard](https://discourse.pi-hole.net/t/how-do-i-access-pi-holes-dashboard-admin-interface/3168): + +1. `http:///admin/` +2. `http:/pi.hole/admin/` (when using Pi-hole as your DNS server) +3. `http://pi.hole/` (when using Pi-hole as your DNS server) + +Once logged in (forgot your password?), you can view your network stats to see things like: + +- the domains being queried on your network +- the time the queries were initiated +- the amount of domains that were blocked +- the upstream server queries were sent to +- the type of queries (`A`, `AAAA`, `CNAME`, `SRV`, `TXT`, etc.) +--- + +## Pi-hole is free, but powered by your support +There are many reoccurring costs involved with maintaining free, open source, and privacy respecting software; expenses which [our volunteer developers](https://github.com/orgs/pi-hole/people) pitch in to cover out-of-pocket. This is just one example of how strongly we feel about our software, as well as the importance of keeping it maintained. + +Make no mistake: **your support is absolutely vital to help keep us innovating!** + +### Donations +Sending a donation using our links below is **extremely helpful** in offsetting a portion of our monthly expenses: + +- PP Donate via PayPal
+- BTC [Bitcoin](https://commerce.coinbase.com/checkout/fb7facaf-bebd-46be-bb77-b358f4546763): 1GKnevUnVaQM2pQieMyeHkpr8DXfkpfAtL
+- BTC [Bitcoin Cash](https://commerce.coinbase.com/checkout/fb7facaf-bebd-46be-bb77-b358f4546763): qqh25hlmqaj99xraw00e47xmf8sysnyxhyww2d7dnh
+- BTC [Ethereum](https://commerce.coinbase.com/checkout/fb7facaf-bebd-46be-bb77-b358f4546763): 0xF00aF43d2431BAD585056492b310e48eC40D87e8 + +### Alternative support +If you'd rather not [donate](https://pi-hole.net/donate/) (_which is okay!_), there are other ways you can help support us: + +- [Digital Ocean](http://www.digitalocean.com/?refcode=344d234950e1) _affiliate link_ +- [UNIXstickers.com](http://unixstickers.refr.cc/jacobs) _save $5 when you spend $9 using our affiliate link_ +- [Pi-hole Swag Store](https://pi-hole.net/shop/) _affiliate link_ +- [Amazon](http://www.amazon.com/exec/obidos/redirect-home/pihole09-20) _affiliate link_ +- [Ho-ost](https://clients.ho-ost.com/aff.php?aff=19) _save 50% with our affiliate link_ +- [DNS Made Easy](https://cp.dnsmadeeasy.com/u/133706) _affiliate link_ +- [Vultr](http://www.vultr.com/?ref=7190426) _affiliate link_ +- Spreading the word about our software, and how you have benefited from it + +### Contributing via GitHub +We welcome _everyone_ to contribute to issue reports, suggest new features, and create pull requests. + +If you have something to add - anything from a typo through to a whole new feature, we're happy to check it out! Just make sure to fill out our template when submitting your request; the questions that it asks will help the volunteers quickly understand what you're aiming to achieve. + +### Presentations about Pi-hole +Word-of-mouth continues to help our project grow immensely, and so we are helping make this easier for people. + +If you are going to be presenting Pi-hole at a conference, meetup or even a school project, [get in touch with us](https://pi-hole.net/2017/05/17/giving-a-presentation-on-pi-hole-contact-us-first-for-some-goodies-and-support/) so we can hook you up with free swag to hand out to your audience! + +----- + +## Getting in touch with us +While we are primarily reachable on our Discourse User Forum, we can also be found on a variety of social media outlets. **Please be sure to check the FAQ's** before starting a new discussion, as we do not have the spare time to reply to every request for assistance. + + + +# Features + +## Mobile friendly interface +

+Mobile friendly +

+ +## Password protection +

+Password protection +

+ +## Detailed graphs and doughnut charts +

+Pie charts +

+ +## Top lists of domains and clients +

+Top domains/top clients +

+ +## A filterable and sortable query log +

+Query log +

+ +## An audit log +

+Pi-hole Web interface +

+ +## Long Term Statistics to view data over user defined time ranges +

+Long-term stats +

+ +## A built-in debugger +

+Debugger +

+ +## Black and white lists +

+Blacklist +

+Whitelist +

+ +## The ability to easily manage and configure Pi-hole features +

+Settings +

+ +## ... and all the main features of the Command Line Interface! +

+Tail the log +

+Query ad lists +

## API -A read-only API can be accessed at `/admin/api.php`. With either no parameters or `api.php?summary` it returns the following JSON: +Full usage available [here](https://discourse.pi-hole.net/t/pi-hole-api/1863). can be accessed at `/admin/api.php`. With either no parameters or `/admin/api.php?summary` it returns the following JSON: ```JSON -{ - "domains_being_blocked": "136,708", - "dns_queries_today": "18,108", - "ads_blocked_today": "14,648", - "ads_percentage_today": "80.9" +{ + "domains_being_blocked":243038, + "dns_queries_today":2385, + "ads_blocked_today":414, + "ads_percentage_today":17.35849, + "unique_domains":429, + "queries_forwarded":1537, + "queries_cached":434, + "clients_ever_seen":5, + "unique_clients":5, + "status":"enabled" } ``` -There are many more parameters, such as `summaryRaw`, `overTimeData10mins`, `topItems`, ` topClients` or `getQuerySources`, `getQueryTypes`, `getForwardDestinations`, and finally `getAllQueries`. -Together with a token it is also possible to enable and disable (also with a set timeout) blocking via the API +[There are many more parameters](https://discourse.pi-hole.net/t/pi-hole-api/1863), such as: -The API returns more information (in a slighly different format if `FTL` is running) - it supports a fall-back to the "old" PHP API if `FTL` is not running. Test the type and/or version of the API by using the parameter `type` and `version`. +- `type & version` +- `summaryRaw` +- `summary` +- `overTimeData10mins` +- `topItems` +- `getQuerySources` +- `getForwardDestinations` +- `getQueryTypes` +- `getAllQueries` +- `enable` +- `disable` +- `recentBlocked` -
-
-We use BrowserStack for multi-platform multi-browser testing. +Together with a token it is also possible to [enable and disable (also with a set timeout) blocking via the API](https://discourse.pi-hole.net/t/is-there-an-api-command-to-disable-ad-blocking/7693). + +The API returns more information (in a slightly different format if `FTL` is running) - it supports a fall-back to the "old" PHP API if `FTL` is not running. Test the type and/or version of the API by using the parameter `type` and `version`. From 5c8c6885dd9542e3d3c13733c2419adb174c2784 Mon Sep 17 00:00:00 2001 From: Jacob Salmela Date: Fri, 23 Mar 2018 19:33:45 -0500 Subject: [PATCH 09/13] add settings gif Signed-off-by: Jacob Salmela --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 505edf19..57412759 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ While we are primarily reachable on our -Settings +Settings

## ... and all the main features of the Command Line Interface! From 5e9c1aec9a117c699d99bcc13546a3c4677d0f63 Mon Sep 17 00:00:00 2001 From: Everett Southwick Date: Sun, 1 Apr 2018 18:02:09 -0500 Subject: [PATCH 10/13] Add support for public Cloudflare DNS servers. Signed-off-by: Everett Southwick --- scripts/pi-hole/php/savesettings.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php index a17bc5f7..af8a90ec 100644 --- a/scripts/pi-hole/php/savesettings.php +++ b/scripts/pi-hole/php/savesettings.php @@ -123,7 +123,8 @@ function isinserverlist($addr) { "Norton" => ["v4_1" => "199.85.126.10", "v4_2" => "199.85.127.10"], "Comodo" => ["v4_1" => "8.26.56.26", "v4_2" => "8.20.247.20"], "DNS.WATCH" => ["v4_1" => "84.200.69.80", "v4_2" => "84.200.70.40", "v6_1" => "2001:1608:10:25:0:0:1c04:b12f", "v6_2" => "2001:1608:10:25:0:0:9249:d69b"], - "Quad9" => ["v4_1" => "9.9.9.9", "v4_2" => "149.112.112.112", "v6_1" => "2620:fe::fe"] + "Quad9" => ["v4_1" => "9.9.9.9", "v4_2" => "149.112.112.112", "v6_1" => "2620:fe::fe"], + "Cloudflare" => ["v4_1" => "1.1.1.1", "v4_2" => "1.0.0.1", "v6_1" => "2606:4700:4700::1111", "v6_2" => "2606:4700:4700::1001"] ]; $adlist = []; From 8b2e7b89ace329704e859d7475e7a2ab3fc24088 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 2 Apr 2018 14:28:48 +0200 Subject: [PATCH 11/13] Add separate legends for pie charts on the dashboard. Fixes #635 Signed-off-by: DL6ER --- index.php | 14 ++++++++++---- scripts/pi-hole/js/index.js | 26 ++++++++++++++++++++++---- style/pi-hole.css | 28 ++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/index.php b/index.php index c56266a4..3874380e 100644 --- a/index.php +++ b/index.php @@ -132,8 +132,11 @@ else

Query Types (integrated)

-
- +
+ +
+
+
@@ -148,8 +151,11 @@ else

Forward Destinations (integrated)

-
- +
+ +
+
+
diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js index 9f8cb8c6..7636ed9d 100644 --- a/scripts/pi-hole/js/index.js +++ b/scripts/pi-hole/js/index.js @@ -178,6 +178,16 @@ function updateQueryTypesPie() { queryTypePieChart.update(); // Don't use rotation animation for further updates queryTypePieChart.options.animation.duration=0; + // Generate legend in separate div + $("#query-types-legend").html(queryTypePieChart.generateLegend()); + $("#query-types-legend > ul > li").on("click",function(e){ + $(this).toggleClass("strike"); + var index = $(this).index(); + var ci = e.view.queryTypePieChart; + var curr = ci.data.datasets[0]._meta[3].data[index]; + curr.hidden = !curr.hidden; + ci.update(); + }); }).done(function() { // Reload graph after minute setTimeout(updateQueryTypesPie, 60000); @@ -392,6 +402,16 @@ function updateForwardDestinationsPie() { forwardDestinationPieChart.update(); // Don't use rotation animation for further updates forwardDestinationPieChart.options.animation.duration=0; + // Generate legend in separate div + $("#forward-destinations-legend").html(forwardDestinationPieChart.generateLegend()); + $("#forward-destinations-legend > ul > li").on("click",function(e){ + $(this).toggleClass("strike"); + var index = $(this).index(); + var ci = e.view.forwardDestinationPieChart; + var curr = ci.data.datasets[0]._meta[3].data[index]; + curr.hidden = !curr.hidden; + ci.update(); + }); }).done(function() { // Reload graph after one minute setTimeout(updateForwardDestinationsPie, 60000); @@ -960,8 +980,7 @@ $(document).ready(function() { }, options: { legend: { - display: true, - position: "right" + display: false }, tooltips: { enabled: true, @@ -998,8 +1017,7 @@ $(document).ready(function() { }, options: { legend: { - display: true, - position: "right" + display: false }, tooltips: { enabled: true, diff --git a/style/pi-hole.css b/style/pi-hole.css index 541d5c6e..59389e9e 100644 --- a/style/pi-hole.css +++ b/style/pi-hole.css @@ -115,3 +115,31 @@ a.lookatme { -webkit-animation: fa-spin 1s infinite linear; animation: fa-spin 1s infinite linear; } + +.chart-legend { + height:250px; + overflow:auto; +} + +.chart-legend ul { + list-style-type: none; +} + +.chart-legend li { + cursor:pointer; +} + +.chart-legend li span { + display: inline-block; + width: 20px; + height: 12px; + margin-right: 5px; +} + +.strike { + text-decoration: line-through !important; +} + +.float-left{ + float:left; +} From e5e956ace65c29d6f59ed1270611fd8a21b022df Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 2 Apr 2018 22:07:07 +0200 Subject: [PATCH 12/13] Automatically detect which _meta to use Signed-off-by: DL6ER --- scripts/pi-hole/js/index.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js index 7636ed9d..75b275b5 100644 --- a/scripts/pi-hole/js/index.js +++ b/scripts/pi-hole/js/index.js @@ -184,8 +184,12 @@ function updateQueryTypesPie() { $(this).toggleClass("strike"); var index = $(this).index(); var ci = e.view.queryTypePieChart; - var curr = ci.data.datasets[0]._meta[3].data[index]; - curr.hidden = !curr.hidden; + var meta = ci.data.datasets[0]._meta; + for(let i in meta) + { + var curr = meta[i].data[index]; + curr.hidden = !curr.hidden; + } ci.update(); }); }).done(function() { @@ -408,8 +412,12 @@ function updateForwardDestinationsPie() { $(this).toggleClass("strike"); var index = $(this).index(); var ci = e.view.forwardDestinationPieChart; - var curr = ci.data.datasets[0]._meta[3].data[index]; - curr.hidden = !curr.hidden; + var meta = ci.data.datasets[0]._meta; + for(let i in meta) + { + var curr = meta[i].data[index]; + curr.hidden = !curr.hidden; + } ci.update(); }); }).done(function() { From 4cf0f4d6ff9ae4abace3555b696a1ebc33891dbe Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 2 Apr 2018 22:29:38 +0200 Subject: [PATCH 13/13] Make sure the properties exist when looping over objects Signed-off-by: DL6ER --- scripts/pi-hole/js/index.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js index 75b275b5..f9452cbd 100644 --- a/scripts/pi-hole/js/index.js +++ b/scripts/pi-hole/js/index.js @@ -187,8 +187,11 @@ function updateQueryTypesPie() { var meta = ci.data.datasets[0]._meta; for(let i in meta) { - var curr = meta[i].data[index]; - curr.hidden = !curr.hidden; + if ({}.hasOwnProperty.call(meta, i)) + { + var curr = meta[i].data[index]; + curr.hidden = !curr.hidden; + } } ci.update(); }); @@ -415,8 +418,11 @@ function updateForwardDestinationsPie() { var meta = ci.data.datasets[0]._meta; for(let i in meta) { - var curr = meta[i].data[index]; - curr.hidden = !curr.hidden; + if ({}.hasOwnProperty.call(meta, i)) + { + var curr = meta[i].data[index]; + curr.hidden = !curr.hidden; + } } ci.update(); });