Files
backend_parkir/public/js/setup/dhcp.js
T

383 lines
12 KiB
JavaScript

let editing = false;
/** Create */
function openCreateModal() {
editing = false;
document.getElementById("reservationModalTitle").innerText = "Add DHCP Reservation";
document.getElementById("reservationForm").reset();
document.getElementById("reservationId").value = "";
document.getElementById("enabled").checked = true;
clearValidation();
}
/*** Edit*/
function editReservation(hostname, mac, ip, enabled) {
editing = true;
document.getElementById("reservationModalTitle").innerText = "Edit DHCP Reservation";
document.getElementById("hostname").value = hostname;
document.getElementById("macAddress").value = mac;
document.getElementById("ipAddress").value = ip;
document.getElementById("enabled").checked = enabled;
const modal = new bootstrap.Modal(document.getElementById("reservationModal"));
modal.show();
}
/*** MAC formatting */
document.getElementById("macAddress").addEventListener("input", function () {
let value = this.value.replace(/[^a-fA-F0-9]/g, "").toUpperCase();
let pairs = value.match(/.{1,2}/g);
this.value = pairs ? pairs.join(":").substring(0, 17) : "";
});
function clearValidation() {
document.getElementById("macAddress").classList.remove("is-invalid");
document.getElementById("ipAddress").classList.remove("is-invalid");
document.getElementById("macError").innerText = "Invalid MAC address.";
document.getElementById("ipError").innerText = "Invalid IP address.";
}
document.getElementById("reservationForm").addEventListener("submit", function (event) {
event.preventDefault();
clearValidation();
const id = document.getElementById("reservationId").value;
const payload = {
hostname: document.getElementById("hostname").value.trim(),
mac_address: document.getElementById("macAddress").value.trim(),
ip_address: document.getElementById("ipAddress").value.trim(),
enabled: document.getElementById("enabled").checked,
};
const macValid = /^([0-9A-F]{2}:){5}[0-9A-F]{2}$/i.test(payload.mac_address);
const ipValid = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}$/.test(
payload.ip_address,
);
if (!macValid) {
document.getElementById("macAddress").classList.add("is-invalid");
return;
}
if (!ipValid) {
document.getElementById("ipAddress").classList.add("is-invalid");
return;
}
const url = id ? dhcpConfig.reservationBaseUrl + "/" + id : dhcpConfig.reservationStoreUrl;
const method = id ? "PUT" : "POST";
const submitButton = this.querySelector('button[type="submit"]');
if (submitButton) {
submitButton.disabled = true;
submitButton.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>' + "Saving...";
}
fetch(url, {
method: method,
headers: {
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute("content"),
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
})
.then(async (response) => {
const data = await response.json();
if (!response.ok) {
throw data;
}
return data;
})
.then((data) => {
if (!data.success) {
throw data;
}
const modal = bootstrap.Modal.getInstance(document.getElementById("reservationModal"));
if (modal) {
modal.hide();
}
window.location.reload();
})
.catch((error) => {
console.error("Reservation save error:", error);
if (error.errors && error.errors.mac_address) {
document.getElementById("macAddress").classList.add("is-invalid");
document.getElementById("macError").innerText = error.errors.mac_address[0];
}
if (error.errors && error.errors.ip_address) {
document.getElementById("ipAddress").classList.add("is-invalid");
document.getElementById("ipError").innerText = error.errors.ip_address[0];
}
Swal.fire({icon: 'error', title: 'Gagal menyimpan', text: error.message || "Failed to save reservation."});
})
.finally(() => {
if (submitButton) {
submitButton.disabled = false;
submitButton.innerHTML = '<i class="bi bi-check-lg me-1"></i>' + "Save Reservation";
}
});
});
/*** Search*/
document.getElementById("searchReservation").addEventListener("input", function () {
const keyword = this.value.toLowerCase();
document.querySelectorAll("#reservationTable tbody tr").forEach(function (row) {
row.style.display = row.innerText.toLowerCase().includes(keyword) ? "" : "none";
});
});
/*** Delete*/
function deleteReservation(hostname) {
Swal.fire({title: 'Hapus reservasi "' + hostname + '"?', icon: 'warning', showCancelButton: true, confirmButtonText: 'Ya, hapus', cancelButtonText: 'Batal', confirmButtonColor: '#dc3545'})
.then((res) => {
if (!res.isConfirmed) return;
Swal.fire({icon: 'info', title: 'Mode demo', text: 'Reservation "' + hostname + '" deleted.'});
});
}
/**
* Test DHCP
*/
function testDhcp() {
Swal.fire({icon: 'info', title: 'Mode demo', text: "DHCP configuration is valid."});
}
/**
* Apply
*/
function applyDhcp() {
const modal = new bootstrap.Modal(document.getElementById("applyModal"));
modal.show();
}
/*** Confirm Apply */
function confirmApply() {
const modalElement = document.getElementById("applyModal");
const modal = bootstrap.Modal.getInstance(modalElement);
if (modal) {
modal.hide();
}
const button = document.querySelector('#applyModal [onclick="confirmApply()"]');
if (button) {
button.disabled = true;
button.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>' + "Applying...";
}
fetch(dhcpConfig.applyUrl, {
method: "POST",
headers: {
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute("content"),
Accept: "application/json",
},
})
.then(async (response) => {
const data = await response.json();
if (!response.ok) {
throw data;
}
return data;
})
.then((data) => {
if (!data.success) {
throw data;
}
Swal.fire({icon: 'success', title: 'Berhasil', text: data.message || "DHCP configuration applied successfully."});
refreshDhcpStatus();
window.location.reload();
})
.catch((error) => {
console.error("DHCP apply error:", error);
Swal.fire({icon: 'error', title: 'Gagal apply', text: error.message || "Failed to apply DHCP configuration."});
})
.finally(() => {
if (button) {
button.disabled = false;
button.innerHTML = "Apply Configuration";
}
});
}
function refreshDhcpStatus() {
fetch(dhcpConfig.statusUrl)
.then(async (response) => {
if (!response.ok) {
throw new Error("HTTP " + response.status);
}
return response.json();
})
.then((data) => {
document.getElementById("dhcpServerHostname").innerText = data.hostname ?? "DHCP Server";
const badge = document.getElementById("dhcpStatusBadge");
const clients = document.getElementById("activeClients");
const lastApplied = document.getElementById("lastApplied");
const serverIp = document.getElementById("dhcpServerIp");
const serverInterface = document.getElementById("dhcpServerInterface");
serverIp.innerText = data.ip ?? "-";
serverInterface.innerText = data.interface ?? "-";
// STATUS
if (data.running) {
badge.innerHTML = `
<span class="badge rounded-pill bg-success bg-opacity-10 text-success">
<span
class="d-inline-block rounded-circle bg-success me-1"
style="width:7px;height:7px;"
></span>
Running
</span>
`;
} else {
badge.innerHTML = `
<span class="badge rounded-pill bg-danger bg-opacity-10 text-danger">
<span
class="d-inline-block rounded-circle bg-danger me-1"
style="width:7px;height:7px;"
></span>
Stopped
</span>
`;
}
// ACTIVE CLIENTS
clients.innerHTML =
(data.reservations_count ?? data.active_clients ?? 0) +
' <span class="text-muted fw-normal small">registered</span>';
// LAST APPLIED
if (data.last_applied) {
const date = new Date(data.last_applied.replace(" ", "T"));
lastApplied.innerText = date.toLocaleString("id-ID", {
day: "2-digit",
month: "short",
hour: "2-digit",
minute: "2-digit",
});
} else {
lastApplied.innerText = "Never";
}
})
.catch((error) => {
console.error("DHCP status error:", error);
});
}
function loadDhcpLogs() {
const container = document.getElementById("dhcpLogs");
container.innerHTML = `
<div class="text-muted p-4">
Loading...
</div>
`;
fetch(dhcpConfig.logsUrl)
.then(async (response) => {
if (!response.ok) {
throw new Error("HTTP " + response.status);
}
return response.json();
})
.then((data) => {
if (!data.logs || !data.logs.length) {
container.innerHTML = `
<div class="text-muted p-4">
No DHCP events found.
</div>
`;
return;
}
container.innerHTML = data.logs
.map((log) => {
const escaped = escapeHtml(log);
let className = "text-muted";
if (log.includes("DHCPACK")) {
className = "text-success";
} else if (log.includes("DHCPNAK")) {
className = "text-danger";
} else if (log.includes("DHCPREQUEST")) {
className = "text-primary";
} else if (log.includes("DHCPDISCOVER")) {
className = "text-warning";
}
return `
<div class="px-4 py-2 border-bottom
${className}">
${escaped}
</div>
`;
})
.join("");
})
.catch((error) => {
console.error("DHCP logs error:", error);
container.innerHTML = `
<div class="text-danger p-4">
Failed to load DHCP logs.
</div>
`;
});
}
function escapeHtml(value) {
const div = document.createElement("div");
div.textContent = value;
return div.innerHTML;
}
refreshDhcpStatus();
loadDhcpLogs();
setInterval(refreshDhcpStatus, 5000, loadDhcpLogs, 5000);