mirror of
https://github.com/pi-hole/web.git
synced 2026-08-23 14:51:12 +01:00
- DataTables: replace the combined BS3 download-builder bundles with
the official core + Bootstrap 5 styling-adapter package pairs
(datatables.net(-buttons/-select) + datatables.net-bs5/-buttons-bs5/
-select-bs5), loaded core-then-adapter.
- bootstrap-select -> Tom Select: bootstrap-select has no Bootstrap 5
build. Add utils.createGroupSelect(), a small wrapper around Tom
Select that recreates bootstrap-select's actionsBox (Select all/
Select none) via a couple of buttons injected into the dropdown, and
use it for all four "assign to group(s)" multi-selects (groups,
groups/clients, groups/domains, groups/lists). Two behavioral fixes
were needed to match the old widget: `hideSelected: false` (Tom
Select refuses to open its dropdown once every option is already
selected, which made the actions box unreachable) and
`dropdownParent: "body"` (otherwise the dropdown is clipped by the
surrounding .table-responsive/.card ancestors' overflow, same reason
bootstrap-select was configured with container: "body").
- bootstrap-toggle -> bootstrap5-toggle: drop-in replacement, same
$.fn.bootstrapToggle() API and onstyle/offstyle option names (all
call sites already used Bootstrap 5-valid color names).
- select2: bump to 4.1.0 and add the select2-bootstrap-5-theme package
for correct Bootstrap 5 styling; wire theme: "bootstrap-5" into both
call sites.
- Remove now-dead bootstrap-select cleanup code (the
"$('body > .bootstrap-select.dropdown').remove()" DataTables
drawCallback lines across 8 files) and dead icheck/bootstrap-select
CSS in pi-hole.css.
Also fixed a Phase 1 regression surfaced by this pass: utils.js's
loadingOverlay() still targeted the old ".wrapper" class instead of
".app-wrapper", throwing whenever a settings page triggered the
Save & Apply overlay.
Verified against a live container: groups/clients' per-row Tom Select
multiselect (open dropdown, Select all/none, Apply, restore-on-cancel),
bootstrap5-toggle switches on groups, select2 filters on the query log,
and DataTables' select/export button row on groups/lists all work with
zero console errors. Settings pages' Save & Apply overlay confirmed
fixed and no longer throwing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
127 lines
3.5 KiB
JavaScript
127 lines
3.5 KiB
JavaScript
/* Pi-hole: A black hole for Internet advertisements
|
|
* (c) 2023 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 apiFailure:false, utils:false, initTable:false, updateFtlInfo:false */
|
|
|
|
"use strict";
|
|
|
|
let groups = [];
|
|
|
|
function populateGroupSelect(selectEl) {
|
|
if (selectEl.length === 0) {
|
|
// No select element found, return
|
|
return;
|
|
}
|
|
|
|
// Add all known groups
|
|
for (const group of groups) {
|
|
const label = group.enabled ? group.name : group.name + " (disabled)";
|
|
|
|
selectEl.append($("<option/>").val(group.id).text(label));
|
|
}
|
|
|
|
// Default Group is pre-selected
|
|
selectEl.val(["0"]);
|
|
|
|
utils.createGroupSelect(selectEl);
|
|
}
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
function getGroups(groupSelector) {
|
|
$.ajax({
|
|
url: document.body.dataset.apiurl + "/groups",
|
|
type: "GET",
|
|
dataType: "json",
|
|
success(data) {
|
|
groups = data.groups;
|
|
|
|
// Get all <select> elements with the class "group-select"
|
|
const groupSelector = $(".group-select");
|
|
// Populate the groupSelector with the groups
|
|
for (const element of groupSelector) {
|
|
populateGroupSelect($(element));
|
|
}
|
|
|
|
// Actually load table contents
|
|
initTable();
|
|
},
|
|
error(data) {
|
|
apiFailure(data);
|
|
},
|
|
});
|
|
}
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
function processGroupResult(data, type, done, notDone) {
|
|
// Loop over data.processed.success and show toasts
|
|
for (const item of data.processed.success) {
|
|
utils.showAlert("success", "fas fa-pencil-alt", `Successfully ${done} ${type}`, item);
|
|
}
|
|
|
|
// Loop over errors and display them
|
|
for (const error of data.processed.errors) {
|
|
console.log(error); // eslint-disable-line no-console
|
|
utils.showAlert("error", "", `Error while ${notDone} ${type} ${error.item}`, error.error);
|
|
}
|
|
}
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
function delGroupItems(type, ids, table, listType = undefined) {
|
|
// Check input validity
|
|
if (!Array.isArray(ids)) {
|
|
return;
|
|
}
|
|
|
|
const url = document.body.dataset.apiurl + "/" + type + "s:batchDelete";
|
|
|
|
// use utils.hexDecode() to decode all clients
|
|
let idstring = "";
|
|
for (const id of ids) {
|
|
id.item = utils.hexDecode(id.item);
|
|
idstring += id.item + ", ";
|
|
}
|
|
|
|
// Remove last comma and space from idstring
|
|
idstring = idstring.substring(0, idstring.length - 2);
|
|
|
|
// Append "s" to type if more than one item is deleted
|
|
type += ids.length > 1 ? "s" : "";
|
|
|
|
// Prepend listType to type if it is not undefined
|
|
if (listType !== undefined) {
|
|
type = listType + " " + type;
|
|
}
|
|
|
|
utils.disableAll();
|
|
utils.showAlert("info", "", "Deleting " + ids.length + " " + type + "...", idstring);
|
|
|
|
$.ajax({
|
|
url,
|
|
data: JSON.stringify(ids),
|
|
contentType: "application/json",
|
|
method: "POST",
|
|
})
|
|
.done(() => {
|
|
utils.enableAll();
|
|
utils.showAlert("success", "far fa-trash-alt", "Successfully deleted " + type, idstring);
|
|
table.ajax.reload(null, false);
|
|
|
|
// Clear selection after deletion
|
|
table.rows().deselect();
|
|
utils.changeTableButtonStates(table);
|
|
|
|
// Update number of <type> items in the sidebar
|
|
updateFtlInfo();
|
|
})
|
|
.fail((data, exception) => {
|
|
apiFailure(data);
|
|
utils.enableAll();
|
|
utils.showAlert("error", "", "Error while deleting " + type, data.responseText);
|
|
console.log(exception); // eslint-disable-line no-console
|
|
});
|
|
}
|