mirror of
https://github.com/pi-hole/web.git
synced 2025-12-24 12:48:29 +00:00
333 lines
12 KiB
JavaScript
333 lines
12 KiB
JavaScript
/* Pi-hole: A black hole for Internet advertisements
|
|
* (c) 2017 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 utils:false, checkMessages:false, apiFailure:false */
|
|
var token = $("#token").text();
|
|
|
|
var hostinfoTimer = null;
|
|
function updateHostInfo() {
|
|
$.ajax({
|
|
url: "/api/info/host",
|
|
})
|
|
.done(function (data) {
|
|
var host = data.host;
|
|
var uname = host.uname;
|
|
if (uname.domainname !== "(none)") {
|
|
$("#sysinfo-hostname").text(uname.nodename + "." + uname.domainname);
|
|
} else {
|
|
$("#sysinfo-hostname").text(uname.nodename);
|
|
}
|
|
|
|
$("#sysinfo-kernel").text(
|
|
uname.sysname +
|
|
" " +
|
|
uname.nodename +
|
|
" " +
|
|
uname.release +
|
|
" " +
|
|
uname.version +
|
|
" " +
|
|
uname.machine
|
|
);
|
|
// Update every 120 seconds
|
|
clearTimeout(hostinfoTimer);
|
|
hostinfoTimer = setTimeout(updateHostInfo, 120000);
|
|
})
|
|
.fail(function (data) {
|
|
apiFailure(data);
|
|
});
|
|
}
|
|
|
|
var cacheinfoTimer = null;
|
|
function updateCacheInfo() {
|
|
$.ajax({
|
|
url: "/api/info/cache",
|
|
})
|
|
.done(function (data) {
|
|
var cache = data.cache;
|
|
$("#sysinfo-cache-size").text(cache.size);
|
|
$("#sysinfo-cache-inserted").text(cache.inserted);
|
|
$("#sysinfo-cache-evicted").text(cache.evicted);
|
|
$("#sysinfo-cache-expired").text(cache.expired);
|
|
$("#sysinfo-cache-immortal").text(cache.immortal);
|
|
$("#sysinfo-cache-valid-a").text(cache.valid.a);
|
|
$("#sysinfo-cache-valid-aaaa").text(cache.valid.aaaa);
|
|
$("#sysinfo-cache-valid-cname").text(cache.valid.cname);
|
|
$("#sysinfo-cache-valid-srv").text(cache.valid.srv);
|
|
$("#sysinfo-cache-valid-ds").text(cache.valid.ds);
|
|
$("#sysinfo-cache-valid-dnskey").text(cache.valid.dnskey);
|
|
$("#sysinfo-cache-valid-other").text(cache.valid.other);
|
|
$("#sysinfo-cache-overlay").hide();
|
|
// Update every 10 seconds
|
|
clearTimeout(cacheinfoTimer);
|
|
cacheinfoTimer = setTimeout(updateCacheInfo, 10000);
|
|
})
|
|
.fail(function (data) {
|
|
apiFailure(data);
|
|
});
|
|
}
|
|
|
|
function createDynamicConfigTabs() {
|
|
$.ajax({
|
|
url: "/api/config?detailed=true",
|
|
})
|
|
.done(function (data) {
|
|
var navTabs = $(".nav-tabs");
|
|
var tabContent = $(".tab-content");
|
|
|
|
// Remove the teleporter tab (it is added as the last tab after the loop)
|
|
var teleporter = $(".nav-tabs > li").last();
|
|
navTabs.remove(teleporter);
|
|
|
|
// Create the tabs for the dynamic config topics
|
|
data.topics.forEach(function (topic) {
|
|
var nav = '<li role="presentation"><a href="#' + topic.name + '" aria-controls="' + topic.name + '" aria-expanded="false" role="tab" data-toggle="tab">' + topic.title + '</a></li>';
|
|
navTabs.append(nav);
|
|
var content = '<div id="' + topic.name + '" class="tab-pane fade"> \
|
|
<div class="row"> \
|
|
<div class="col-md-12"> \
|
|
<div class="box"> \
|
|
<div class="box-header with-border"> \
|
|
<h3 class="box-title">' + topic.title + '</h3> \
|
|
<p>' + topic.description + '</p> \
|
|
<p><input type="checkbox" id="advanced-settings-toggle-' + topic.name + '"><label for="advanced-settings-toggle-' + topic.name + '"> Show advanced settings</label></p> \
|
|
</div> \
|
|
<div class="box-body"> \
|
|
<div class="row"> \
|
|
<div class="col-lg-12" id="' + topic.name + '-content"> \
|
|
</div> \
|
|
<div class="overlay" id="settings-' + topic.name + '-overlay"> \
|
|
<i class="fa fa-sync fa-spin"></i> \
|
|
</div> \
|
|
</div> \
|
|
</div> \
|
|
</div> \
|
|
</div>';
|
|
tabContent.append(content);
|
|
});
|
|
|
|
navTabs.append(teleporter);
|
|
|
|
// Create the content for the dynamic config topics
|
|
Object.keys(data.config).forEach(function (topic) {
|
|
Object.keys(data.config[topic]).forEach(function (key) {
|
|
var value = data.config[topic][key];
|
|
console.log(topic, value);
|
|
if('description' in value) {
|
|
var row = '<div class="col-md-6 ' + (value.flags.advanced ? 'advanced-setting" hidden':'"') + '> \
|
|
<div class="box box-warning"> \
|
|
<div class="box-header with-border"> \
|
|
<h3 class="box-title">' + key + (value.modified ? ' <i class="far fa-edit" title="Modified"></i>':'') + (value.flags.advanced ? ' <i class="fas fa-cogs" title="This is an advanced setting"></i>':'') + '</h3> \
|
|
<p>' + utils.escapeHtml(value.description).replace("\n","<br>") + '</p> \
|
|
</div> \
|
|
<div class="box-body"> \
|
|
<div class="row"> \
|
|
<div class="col-lg-12"> \
|
|
<div class="form-group">';
|
|
var resetToDefault = '';
|
|
if(value.modified) {
|
|
resetToDefault = '<button type="button" class="btn btn-default btn-sm pull-right" onclick="resetToDefault(\'' + topic + '\',\'' + key + '\')" title="Default option is: \"' + JSON.stringify(value.default) + '\""><i class="fas fa-redo"></i>  Reset to default</button>';
|
|
}
|
|
if(value['type'] == "string") {
|
|
row += '<label class="col-sm-4 control-label">Value (string)</label> \
|
|
<div class="col-sm-8"> \
|
|
<input type="text" class="form-control" value="' + value.value + '"> ' + resetToDefault + '\
|
|
<p><small>Allowed value: ' + utils.escapeHtml(value.allowed) + '</small></p> \
|
|
</div>';
|
|
} else if(value['type'] == "boolean") {
|
|
row += '<label class="col-sm-4 control-label">Enabled</label> \
|
|
<div class="col-sm-8"> \
|
|
<input type="checkbox" ' + (value.value ? ' checked':'') + '> ' + resetToDefault + '\
|
|
</div>';
|
|
} else if(value['type'] == "integer") {
|
|
row += '<label class="col-sm-4 control-label">Value (integer)</label> \
|
|
<div class="col-sm-8"> \
|
|
<input type="number" step="1" class="form-control" value="' + value.value + '"> ' + resetToDefault + '\
|
|
</div>';
|
|
} else if(value['type'] == "unsigned integer") {
|
|
row += '<label class="col-sm-4 control-label">Value (unsigned integer)</label> \
|
|
<div class="col-sm-8"> \
|
|
<input type="number" step="1" min="0" class="form-control" value="' + value.value + '"> ' + resetToDefault + '\
|
|
</div>';
|
|
} else if(value['type'] == "unsigned integer (16 bit)") {
|
|
row += '<label class="col-sm-4 control-label">Value (unsigned 16bit integer)</label> \
|
|
<div class="col-sm-8"> \
|
|
<input type="number" step="1" min="0" max="65535" class="form-control" value="' + value.value + '"> ' + resetToDefault + '\
|
|
</div>';
|
|
} else if(value['type'] == "string array") {
|
|
row += '<label class="col-sm-5 control-label">Values (one item per line)</label> \
|
|
<div class="col-sm-7"> \
|
|
<textarea class="form-control">' + value.value.join("\n") + '</textarea> ' + resetToDefault + '\
|
|
</div>';
|
|
} else if(value['type'] == "enum (string)") {
|
|
row += '<label class="col-sm-4 control-label">Selected Option</label> \
|
|
<div class="col-sm-8"> \
|
|
<select class="form-control">';
|
|
value.allowed.forEach(function(option) {
|
|
row += '<option value="' + option.item + '"' + (option.item == value.value ? ' selected':'') + '>' + option.item + '</option>';
|
|
});
|
|
row += '</select> ' + resetToDefault + '\
|
|
</div> \
|
|
<div class="col-sm-12"> \
|
|
<p>Available options: <ul><li>' + value.allowed.map(function(option) { return '<code>' + option.item + '</code>: ' + utils.escapeHtml(option.description); }).join('</li><li>') + '</li></ul></p> \
|
|
</div>';
|
|
} else {
|
|
row += "TYPE " + value.type + " NOT DEFINED";
|
|
}
|
|
row +=' </div> \
|
|
</div> \
|
|
</div> \
|
|
</div> ';
|
|
}
|
|
$("#" + topic + "-content").append(row);
|
|
});
|
|
$('#settings-' + topic + '-overlay').hide();
|
|
|
|
$("input[id^='advanced-settings-toggle']").on("click", function(data) {
|
|
var checked = data.target.checked;
|
|
// Synchronize all advanced settings checkboxes
|
|
$("input[id^='advanced-settings-toggle']").prop("checked", checked);
|
|
// Show/hide all advanced settings
|
|
$(".advanced-setting").toggle(checked);
|
|
});
|
|
});
|
|
|
|
// Remove the overlay
|
|
})
|
|
.fail(function (data) {
|
|
apiFailure(data);
|
|
});
|
|
}
|
|
|
|
$(function () {
|
|
updateHostInfo();
|
|
updateCacheInfo();
|
|
createDynamicConfigTabs();
|
|
});
|
|
|
|
$(".confirm-poweroff").confirm({
|
|
text: "Are you sure you want to send a poweroff command to your Pi-hole?",
|
|
title: "Confirmation required",
|
|
confirm: function () {
|
|
$("#poweroffform").submit();
|
|
},
|
|
cancel: function () {
|
|
// nothing to do
|
|
},
|
|
confirmButton: "Yes, poweroff",
|
|
cancelButton: "No, go back",
|
|
post: true,
|
|
confirmButtonClass: "btn-danger",
|
|
cancelButtonClass: "btn-success",
|
|
dialogClass: "modal-dialog",
|
|
});
|
|
$(".confirm-reboot").confirm({
|
|
text: "Are you sure you want to send a reboot command to your Pi-hole?",
|
|
title: "Confirmation required",
|
|
confirm: function () {
|
|
$("#rebootform").submit();
|
|
},
|
|
cancel: function () {
|
|
// nothing to do
|
|
},
|
|
confirmButton: "Yes, reboot",
|
|
cancelButton: "No, go back",
|
|
post: true,
|
|
confirmButtonClass: "btn-danger",
|
|
cancelButtonClass: "btn-success",
|
|
dialogClass: "modal-dialog",
|
|
});
|
|
|
|
$(".confirm-restartdns").confirm({
|
|
text: "Are you sure you want to send a restart command to your DNS server?",
|
|
title: "Confirmation required",
|
|
confirm: function () {
|
|
$("#restartdnsform").submit();
|
|
},
|
|
cancel: function () {
|
|
// nothing to do
|
|
},
|
|
confirmButton: "Yes, restart DNS",
|
|
cancelButton: "No, go back",
|
|
post: true,
|
|
confirmButtonClass: "btn-danger",
|
|
cancelButtonClass: "btn-success",
|
|
dialogClass: "modal-dialog",
|
|
});
|
|
|
|
$(".confirm-flushlogs").confirm({
|
|
text: "Are you sure you want to flush your logs?",
|
|
title: "Confirmation required",
|
|
confirm: function () {
|
|
$("#flushlogsform").submit();
|
|
},
|
|
cancel: function () {
|
|
// nothing to do
|
|
},
|
|
confirmButton: "Yes, flush logs",
|
|
cancelButton: "No, go back",
|
|
post: true,
|
|
confirmButtonClass: "btn-danger",
|
|
cancelButtonClass: "btn-success",
|
|
dialogClass: "modal-dialog",
|
|
});
|
|
|
|
$(".confirm-flusharp").confirm({
|
|
text: "Are you sure you want to flush your network table?",
|
|
title: "Confirmation required",
|
|
confirm: function () {
|
|
$("#flusharpform").submit();
|
|
},
|
|
cancel: function () {
|
|
// nothing to do
|
|
},
|
|
confirmButton: "Yes, flush my network table",
|
|
cancelButton: "No, go back",
|
|
post: true,
|
|
confirmButtonClass: "btn-warning",
|
|
cancelButtonClass: "btn-success",
|
|
dialogClass: "modal-dialog",
|
|
});
|
|
|
|
$(".confirm-disablelogging-noflush").confirm({
|
|
text: "Are you sure you want to disable logging?",
|
|
title: "Confirmation required",
|
|
confirm: function () {
|
|
$("#disablelogsform-noflush").submit();
|
|
},
|
|
cancel: function () {
|
|
// nothing to do
|
|
},
|
|
confirmButton: "Yes, disable logs",
|
|
cancelButton: "No, go back",
|
|
post: true,
|
|
confirmButtonClass: "btn-warning",
|
|
cancelButtonClass: "btn-success",
|
|
dialogClass: "modal-dialog",
|
|
});
|
|
|
|
// Handle hiding of alerts
|
|
$(function () {
|
|
$("[data-hide]").on("click", function () {
|
|
$(this)
|
|
.closest("." + $(this).attr("data-hide"))
|
|
.hide();
|
|
});
|
|
});
|
|
|
|
// DHCP leases tooltips
|
|
$(function () {
|
|
$('[data-toggle="tooltip"]').tooltip({ html: true, container: "body" });
|
|
});
|
|
|
|
// Change "?tab=" parameter in URL for save and reload
|
|
$(".nav-tabs a").on("shown.bs.tab", function (e) {
|
|
var tab = e.target.hash.substring(1);
|
|
window.history.pushState("", "", "?tab=" + tab);
|
|
window.scrollTo(0, 0);
|
|
});
|