From 6154576e40a3ee311cfeda25cfb8f494b751fed0 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sat, 27 Jan 2024 15:29:18 -0300 Subject: [PATCH 01/14] Replace textarea with a table to show separate fields and lines Signed-off-by: RD WebDesign --- settings-dns.lp | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/settings-dns.lp b/settings-dns.lp index a67b6e6d7..628b47e42 100644 --- a/settings-dns.lp +++ b/settings-dns.lp @@ -226,7 +226,44 @@ mg.include('scripts/pi-hole/lua/settings_header.lp','r')

Enabling Conditional Forwarding will also forward all hostnames (i.e., non-FQDNs) to the router when "Never forward non-FQDNs" is not enabled.

The following list contains all reverse servers you want to add. The expected format is one server per line in form of <enabled>,<ip-address>[/<prefix-len>],<server>[#<port>][,<domain>]. A valid config line could look like true,192.168.0.0/24,192.168.0.1,fritz.box

- + + + + + + + + + + + + + + + + + + + + + + + +
EnabledNetwork Range 1Server 2Domain 3
+ + + + + + + + + +
+
1: Local network range using CIDR notation
+
2: IP address of your DHCP server (or router)
+
3: Local domain name (optional)
+
From 746d0412000015a9416dc480df18dd90d9ed48da Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sat, 27 Jan 2024 15:32:30 -0300 Subject: [PATCH 02/14] Add the new table and functions to insert and delete reverse servers Signed-off-by: RD WebDesign --- scripts/pi-hole/js/settings-dns.js | 168 +++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index 7059fc5ed..4c8e29fe1 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.js @@ -107,6 +107,143 @@ function updateDNSserversTextfield(upstreams, customServers) { ); } +function RevServersField(data, fieldIndex) { + // If an invalid index is received, return null + if (fieldIndex < 0 || fieldIndex > 4) { + return null; + } + + let arrRevServers = data.split(","); + return arrRevServers.length > fieldIndex ? arrRevServers[fieldIndex] : ""; +} + +function revServerDataTable() { + var setByEnv = false; + $.ajax({ + url: "/api/config/dns/revServers?detailed=true", + }).done(function (data) { + // Set the title icons if needed + setConfigValues("dns", "dns", data.config.dns); + + // disable input fields if set by env var + if (data.config.dns.revServers.flags.env_var) { + $(".revServers").prop("disabled", true); + } + }); + + $("#revServers-table").DataTable({ + ajax: { + url: "/api/config/dns/revServers", + type: "GET", + dataSrc: "config.dns.revServers", + }, + autoWidth: false, + columns: [ + { data: null, class: "text-center", width: "60px" }, + { data: null }, + { data: null }, + { data: null }, + { data: null, width: "22px" }, + ], + ordering: false, + columnDefs: [ + { + targets: 0, + render: function(data) { + return RevServersField(data, 0) == "true" ? '' : ''; + } + }, + { + targets: "_all", + render: function (data, type, full, meta) { + return RevServersField(data, meta.col); + }, + }, + ], + drawCallback: function () { + $('button[id^="deleteRevServers"]').on("click", deleteRecord); + + // Remove visible dropdown to prevent orphaning + $("body > .bootstrap-select.dropdown").remove(); + }, + rowCallback: function (row, data) { + $(row).attr("data-id", data); + var button = ``; + $("td:eq(4)", row).html(button); + }, + dom: "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-12'i>>", + paging: false, + language: { + emptyTable: "No revese DNS servers defined.", + }, + stateSave: true, + stateDuration: 0, + processing: true, + stateSaveCallback: function (settings, data) { + utils.stateSaveCallback("revServers-records-table", data); + }, + stateLoadCallback: function () { + var data = utils.stateLoadCallback("revServers-records-table"); + // Return if not available + if (data === null) { + return null; + } + + // Apply loaded state to table + return data; + }, + }); +} + +function deleteRecord() { + // Get the tags + var tags = [$(this).attr("data-tag")]; + var types = [$(this).attr("data-type")]; + // Check input validity + if (!Array.isArray(tags)) return; + + // Exploit prevention: Return early for non-numeric IDs + for (var tag in tags) { + if (Object.hasOwnProperty.call(tags, tag)) { + delRevServers(tags); + } + } +} + +function delRevServers(elem) { + utils.disableAll(); + utils.showAlert("info", "", "Deleting reverse server...", elem); + const url = "/api/config/dns/revServers/" + encodeURIComponent(elem); + + $.ajax({ + url: url, + method: "DELETE", + }) + .done(function () { + utils.enableAll(); + utils.showAlert("success", "fas fa-trash-alt", "Successfully deleted reverse server", elem); + $("#revServers-table").DataTable().ajax.reload(null, false); + }) + .fail(function (data, exception) { + utils.enableAll(); + apiFailure(data); + utils.showAlert( + "error", + "", + "Error while deleting DNS record: " + elem + "", + data.responseText + ); + console.log(exception); // eslint-disable-line no-console + }); +} + function processDNSConfig() { $.ajax({ url: "/api/config/dns?detailed=true", // We need the detailed output to get the DNS server list @@ -123,4 +260,35 @@ function processDNSConfig() { $(document).ready(function () { processDNSConfig(); + revServerDataTable(); + + // Button to add a new reverse server + $("#btnAdd-revServers").on("click", function () { + utils.disableAll(); + var items = []; + items[0] = $("#enabled-revServers").is(":checked") ? "true" : "false"; + items[1] = $("#network-revServers").val(); + items[2] = $("#server-revServers").val(); + items[3] = $("#domain-revServers").val(); + const elem = items.join(","); + const url = "/api/config/dns/revServers/" + encodeURIComponent(elem); + utils.showAlert("info", "", "Adding reverse server...", elem); + $.ajax({ + url: url, + method: "PUT", + }) + .done(function () { + utils.enableAll(); + utils.showAlert("success", "fas fa-plus", "Successfully added reverse server", elem); + $("#revServers-table tfoot .form-control").val(""); + $("#enabled-revServers").prop("checked", true); + $("#revServers-table").DataTable().ajax.reload(null, false); + }) + .fail(function (data, exception) { + utils.enableAll(); + apiFailure(data); + utils.showAlert("error", "", "Error while deleting reverse server", data.responseText); + console.log(exception); // eslint-disable-line no-console + }); + }); }); From 927a8321ca794eecc639472e8cc52878e1c29924 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sat, 27 Jan 2024 15:34:33 -0300 Subject: [PATCH 03/14] Don't use "icheck" styling on the checkboxes in the table Signed-off-by: RD WebDesign --- scripts/pi-hole/js/footer.js | 7 +++++-- scripts/pi-hole/js/settings-dns.js | 8 +++++--- settings-dns.lp | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/scripts/pi-hole/js/footer.js b/scripts/pi-hole/js/footer.js index b1f715578..b1a416da5 100644 --- a/scripts/pi-hole/js/footer.js +++ b/scripts/pi-hole/js/footer.js @@ -183,13 +183,16 @@ function testCookies() { var iCheckStyle = "primary"; function applyCheckboxRadioStyle() { - // Get all radio/checkboxes for theming, with the exception of the two radio buttons on the custom disable timer, - // as well as every element with an id that starts with "status_" + // Get all radio/checkboxes for theming, with the exception of: + // - the two radio buttons on the custom disable timer, + // - radio/checkboxes elements with class "no-icheck", + // - every element with an id that starts with "status_" var sel = $("input[type='radio'],input[type='checkbox']") .not("#selSec") .not("#selMin") .not("#expert-settings") .not("#only-changed") + .not(".no-icheck") .not("[id^=status_]"); sel.parent().removeClass(); sel.parent().addClass("icheck-" + iCheckStyle); diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index 4c8e29fe1..edb8cac36 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.js @@ -149,9 +149,11 @@ function revServerDataTable() { columnDefs: [ { targets: 0, - render: function(data) { - return RevServersField(data, 0) == "true" ? '' : ''; - } + render: function (data) { + return RevServersField(data, 0) == "true" + ? '' + : ''; + }, }, { targets: "_all", diff --git a/settings-dns.lp b/settings-dns.lp index 628b47e42..40ea303c1 100644 --- a/settings-dns.lp +++ b/settings-dns.lp @@ -240,7 +240,7 @@ mg.include('scripts/pi-hole/lua/settings_header.lp','r') - + From 168876bdd0adce36166ba88180f36d11b1d784cc Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sat, 27 Jan 2024 17:07:39 -0300 Subject: [PATCH 04/14] Remove text explaining the textarea format Signed-off-by: RD WebDesign --- settings-dns.lp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings-dns.lp b/settings-dns.lp index 40ea303c1..3081b1b5a 100644 --- a/settings-dns.lp +++ b/settings-dns.lp @@ -225,7 +225,7 @@ mg.include('scripts/pi-hole/lua/settings_header.lp','r') in your DHCP server for this to work. You can likely find it within the DHCP settings.

Enabling Conditional Forwarding will also forward all hostnames (i.e., non-FQDNs) to the router when "Never forward non-FQDNs" is not enabled.

-

The following list contains all reverse servers you want to add. The expected format is one server per line in form of <enabled>,<ip-address>[/<prefix-len>],<server>[#<port>][,<domain>]. A valid config line could look like true,192.168.0.0/24,192.168.0.1,fritz.box

+

The following list contains all reverse servers you want to add.

From bdf85a8bd29fb76ad80a6e5bfa36570c8fe2535d Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sat, 27 Jan 2024 17:34:14 -0300 Subject: [PATCH 05/14] Remove unused variable and fix some declarations Signed-off-by: RD WebDesign --- scripts/pi-hole/js/settings-dns.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index edb8cac36..e4dbf1e10 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.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 applyCheckboxRadioStyle:false, setConfigValues: false, apiFailure: false */ +/* global utils:false, applyCheckboxRadioStyle:false, setConfigValues: false, apiFailure: false */ // Remove an element from an array (inline) function removeFromArray(arr, what) { @@ -107,13 +107,13 @@ function updateDNSserversTextfield(upstreams, customServers) { ); } -function RevServersField(data, fieldIndex) { +function revServersField(data, fieldIndex) { // If an invalid index is received, return null if (fieldIndex < 0 || fieldIndex > 4) { return null; } - let arrRevServers = data.split(","); + const arrRevServers = data.split(","); return arrRevServers.length > fieldIndex ? arrRevServers[fieldIndex] : ""; } @@ -150,7 +150,7 @@ function revServerDataTable() { { targets: 0, render: function (data) { - return RevServersField(data, 0) == "true" + return revServersField(data, 0) === "true" ? '' : ''; }, @@ -158,7 +158,7 @@ function revServerDataTable() { { targets: "_all", render: function (data, type, full, meta) { - return RevServersField(data, meta.col); + return revServersField(data, meta.col); }, }, ], @@ -180,7 +180,7 @@ function revServerDataTable() { `; $("td:eq(4)", row).html(button); }, - dom: "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-12'i>>", + dom: "<'row'<'col-sm-12'<'table-responsive'tr>>><'row'<'col-sm-12'i>>", paging: false, language: { emptyTable: "No revese DNS servers defined.", @@ -207,7 +207,7 @@ function revServerDataTable() { function deleteRecord() { // Get the tags var tags = [$(this).attr("data-tag")]; - var types = [$(this).attr("data-type")]; + // Check input validity if (!Array.isArray(tags)) return; From a15d410779739a03f5fef121aa04bf8f0f0e6860 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 4 Feb 2024 01:12:50 -0300 Subject: [PATCH 06/14] Use a function to format dataSrc and renderers to format each input field Signed-off-by: RD WebDesign --- scripts/pi-hole/js/settings-dns.js | 62 ++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index e4dbf1e10..259014300 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.js @@ -135,30 +135,68 @@ function revServerDataTable() { ajax: { url: "/api/config/dns/revServers", type: "GET", - dataSrc: "config.dns.revServers", + dataSrc: function (json) { + const output = []; + for (let i = 0; i < json.config.dns.revServers.length; i++) { + const cols = json.config.dns.revServers[i].split(","); + output.push({ + enabled: cols[0], + network: cols[1], + ip: cols[2], + domain: cols[3], + }); + } + + return output; + }, }, autoWidth: false, columns: [ - { data: null, class: "text-center", width: "60px" }, - { data: null }, - { data: null }, - { data: null }, - { data: null, width: "22px" }, + { data: null, width: "60px" }, + { data: "network" }, + { data: "ip" }, + { data: "domain" }, + { data: null, width: "50px" }, ], + bFilter: false, ordering: false, columnDefs: [ { targets: 0, - render: function (data) { - return revServersField(data, 0) === "true" - ? '' - : ''; + class: "input-checkbox text-center", + render: function (data, type, row, meta) { + const name = "enabled_" + meta.row; + const ckbox = + '"; + return ckbox; }, }, { targets: "_all", - render: function (data, type, full, meta) { - return revServersField(data, meta.col); + class: "input-text", + render: function (data, type, row, meta) { + let name; + switch (meta.col) { + case 1: + name = "network_" + meta.row; + break; + case 2: + name = "ip_" + meta.row; + break; + case 3: + name = "domain_" + meta.row; + break; + // No default + } + + return ( + '" + ); }, }, ], From e687cb83affaf1edda76821189c1487072e03bba Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 4 Feb 2024 01:15:56 -0300 Subject: [PATCH 07/14] Fix the Delete button, to use the new dataSrc values Signed-off-by: RD WebDesign --- scripts/pi-hole/js/settings-dns.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index 259014300..a1763589a 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.js @@ -206,13 +206,15 @@ function revServerDataTable() { // Remove visible dropdown to prevent orphaning $("body > .bootstrap-select.dropdown").remove(); }, - rowCallback: function (row, data) { - $(row).attr("data-id", data); + rowCallback: function (row, data, displayNum, displayIndex, dataIndex) { + $(row).attr("data-index", dataIndex); var button = ``; From 5a34fce9491c61abf6a79d88239a8bf80979c567 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 4 Feb 2024 01:19:07 -0300 Subject: [PATCH 08/14] Add Edit, Save and Cancel buttons to each row Signed-off-by: RD WebDesign --- scripts/pi-hole/js/settings-dns.js | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index a1763589a..355cf6077 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.js @@ -202,6 +202,9 @@ function revServerDataTable() { ], drawCallback: function () { $('button[id^="deleteRevServers"]').on("click", deleteRecord); + $('button[id^="editRevServers"]').on("click", editRecord); + $('button[id^="saveRevServers"]').on("click", saveRecord).hide(); + $('button[id^="cancelRevServers"]').on("click", restoreRecord).hide(); // Remove visible dropdown to prevent orphaning $("body > .bootstrap-select.dropdown").remove(); @@ -209,6 +212,14 @@ function revServerDataTable() { rowCallback: function (row, data, displayNum, displayIndex, dataIndex) { $(row).attr("data-index", dataIndex); var button = ` + + + `; $("td:eq(4)", row).html(button); }, @@ -244,6 +270,15 @@ function revServerDataTable() { }); } +function editRecord() { +} + +function saveRecord() { +} + +function restoreRecord() { +} + function deleteRecord() { // Get the tags var tags = [$(this).attr("data-tag")]; From fa838e800fc27af5481032408c3748e033bcab2f Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 4 Feb 2024 01:38:37 -0300 Subject: [PATCH 09/14] Remove unused function Signed-off-by: RD WebDesign --- scripts/pi-hole/js/settings-dns.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index 355cf6077..356cee69a 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.js @@ -107,16 +107,6 @@ function updateDNSserversTextfield(upstreams, customServers) { ); } -function revServersField(data, fieldIndex) { - // If an invalid index is received, return null - if (fieldIndex < 0 || fieldIndex > 4) { - return null; - } - - const arrRevServers = data.split(","); - return arrRevServers.length > fieldIndex ? arrRevServers[fieldIndex] : ""; -} - function revServerDataTable() { var setByEnv = false; $.ajax({ From 0b7da48e5a891c5c202f207fb34f370144f70ab6 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 4 Feb 2024 01:19:59 -0300 Subject: [PATCH 10/14] Fix rows vertical alignment Signed-off-by: RD WebDesign --- style/pi-hole.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/style/pi-hole.css b/style/pi-hole.css index 034fb2100..cff899417 100644 --- a/style/pi-hole.css +++ b/style/pi-hole.css @@ -388,7 +388,8 @@ td.lookatme { } /* Table footer row used to add new items, using inline input fields */ -tfoot.add-new-item > tr > th { +#revServers-table td, +#revServers-table tfoot > tr > th { font-weight: normal; vertical-align: inherit; } From 9f9ec583f72912b26df64838925a1f5abae81f64 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 4 Feb 2024 01:21:23 -0300 Subject: [PATCH 11/14] Add function to enable edit a row Signed-off-by: RD WebDesign --- scripts/pi-hole/js/settings-dns.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index 356cee69a..9abce68ed 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.js @@ -261,6 +261,14 @@ function revServerDataTable() { } function editRecord() { + // Enable fields on the selected row + $(this).closest("tr").find("td input").prop("disabled", false); + + // Hide EDIT and DELETE buttons. Show SAVE and UNDO buttons + $(this).hide(); + $(this).siblings('[id^="delete"]').hide(); + $(this).siblings('[id^="save"]').show(); + $(this).siblings('[id^="cancel"]').show(); } function saveRecord() { From bc13e1716553a57a9c0185bac453fea7da400de9 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 4 Feb 2024 01:22:51 -0300 Subject: [PATCH 12/14] Add function to restore previous values when user cancels the edition Signed-off-by: RD WebDesign --- scripts/pi-hole/js/settings-dns.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index 9abce68ed..813639f9c 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.js @@ -275,6 +275,26 @@ function saveRecord() { } function restoreRecord() { + // Find the row index + const index = $(this).attr("data-index"); + + // Reset values + $("#enabled_" + index).prop("checked", $("#enabled_" + index).attr("data-initial-value")); + $("#network_" + index).val($("#network_" + index).attr("data-initial-value")); + $("#ip_" + index).val($("#ip_" + index).attr("data-initial-value")); + $("#domain_" + index).val($("#domain_" + index).attr("data-initial-value")); + + // Show cancellation message + utils.showAlert("info", "fas fa-undo", "Operation canceled", "Original values restored"); + + // Finish the edition disabling the fields + $(this).closest("tr").find("td input").prop("disabled", true); + + // Show EDIT and DELETE buttons. Hide SAVE and UNDO buttons + $(this).siblings('[id^="edit"]').show(); + $(this).siblings('[id^="delete"]').show(); + $(this).siblings('[id^="save"]').hide(); + $(this).hide(); } function deleteRecord() { From 6dde3fa88e7df0d7d2fc06747efb22277bdba76c Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 4 Feb 2024 01:24:04 -0300 Subject: [PATCH 13/14] Add function to save edited values Signed-off-by: RD WebDesign --- scripts/pi-hole/js/settings-dns.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index 813639f9c..e0ac6200d 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.js @@ -272,6 +272,28 @@ function editRecord() { } function saveRecord() { + // Find the row index + const index = $(this).attr("data-index"); + + // Get the edited values from each field + const values = []; + values[0] = $("#enabled_" + index).prop("checked") ? "true" : "false"; + values[1] = $("#network_" + index).val(); + values[2] = $("#ip_" + index).val(); + values[3] = $("#domain_" + index).val(); + + // Save the new values + // --- insert $.ajax() call to actually save the data + console.log(values.join(",")); + + // Finish the edition disabling the fields + $(this).closest("tr").find("td input").prop("disabled", true); + + // Show EDIT and DELETE buttons. Hide SAVE and UNDO buttons + $(this).siblings('[id^="edit"]').show(); + $(this).siblings('[id^="delete"]').show(); + $(this).hide(); + $(this).siblings('[id^="cancel"]').hide(); } function restoreRecord() { From d988fdcb9909fab291d90857c0ce5499d1912813 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 4 Feb 2024 14:53:25 -0300 Subject: [PATCH 14/14] Allow console message for debug (temporary) This commit will be removed. Signed-off-by: RD WebDesign --- scripts/pi-hole/js/settings-dns.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pi-hole/js/settings-dns.js b/scripts/pi-hole/js/settings-dns.js index e0ac6200d..88d6d8b83 100644 --- a/scripts/pi-hole/js/settings-dns.js +++ b/scripts/pi-hole/js/settings-dns.js @@ -284,7 +284,7 @@ function saveRecord() { // Save the new values // --- insert $.ajax() call to actually save the data - console.log(values.join(",")); + console.log(values.join(",")); // eslint-disable-line no-console // Finish the edition disabling the fields $(this).closest("tr").find("td input").prop("disabled", true);